Nicer file input
This commit is contained in:
@@ -57,18 +57,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
.input--file {
|
||||
.input--file,
|
||||
.input--upload {
|
||||
cursor: pointer;
|
||||
display: grid;
|
||||
inline-size: auto;
|
||||
place-items: center;
|
||||
|
||||
> * {
|
||||
grid-area: 1 / 1;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 0.4em;
|
||||
&:has(input[type="file"]:focus-visible) {
|
||||
outline: 0.15rem solid var(--color-selected-dark);
|
||||
}
|
||||
|
||||
input[type="file"] {
|
||||
@@ -88,10 +82,19 @@
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:has(input[type="file"]:focus),
|
||||
&:has(input[type="file"]:focus-visible) {
|
||||
outline: 0.15rem solid var(--color-selected-dark);
|
||||
.input--file {
|
||||
display: grid;
|
||||
inline-size: auto;
|
||||
place-items: center;
|
||||
|
||||
> * {
|
||||
grid-area: 1 / 1;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 0.4em;
|
||||
}
|
||||
|
||||
&:is(.avatar) {
|
||||
@@ -101,6 +104,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
.input--upload {
|
||||
--btn-border-color: var(--color-ink);
|
||||
|
||||
border-style: dashed;
|
||||
position: relative;
|
||||
|
||||
input[type="file"] {
|
||||
inset: 0;
|
||||
outline: none;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&:has([data-upload-preview-target="fileName"]:not([hidden])) {
|
||||
--btn-border-color: var(--color-positive);
|
||||
--btn-color: var(--color-positive);
|
||||
}
|
||||
}
|
||||
|
||||
.input--select {
|
||||
--input-border-radius: 2em;
|
||||
--input-padding: 0.5em 1.8em 0.5em 1.2em;
|
||||
|
||||
@@ -1,14 +1,31 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = [ "image", "input" ]
|
||||
static targets = [ "image", "input", "fileName", "placeholder" ]
|
||||
|
||||
previewImage() {
|
||||
const file = this.inputTarget.files[0]
|
||||
|
||||
if (file) {
|
||||
this.imageTarget.src = URL.createObjectURL(file)
|
||||
if (this.#file) {
|
||||
this.imageTarget.src = URL.createObjectURL(this.#file)
|
||||
this.imageTarget.onload = () => URL.revokeObjectURL(this.imageTarget.src)
|
||||
}
|
||||
}
|
||||
|
||||
previewFileName() {
|
||||
this.#file ? this.#showFileName() : this.#showPlaceholder()
|
||||
}
|
||||
|
||||
#showFileName() {
|
||||
this.fileNameTarget.innerHTML = this.#file.name
|
||||
this.fileNameTarget.removeAttribute("hidden")
|
||||
this.placeholderTarget.setAttribute("hidden", true)
|
||||
}
|
||||
|
||||
#showPlaceholder() {
|
||||
this.placeholderTarget.removeAttribute("hidden")
|
||||
this.fileNameTarget.setAttribute("hidden", true)
|
||||
}
|
||||
|
||||
get #file() {
|
||||
return this.inputTarget.files[0]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
<% @page_title = "Import an account" %>
|
||||
|
||||
<div class="panel panel--centered flex flex-column gap-half">
|
||||
<h1 class="txt-x-large font-weight-black margin-block-end">Import an account</h1>
|
||||
<div class="panel panel--centered flex flex-column gap">
|
||||
<header>
|
||||
<h1 class="txt-x-large font-weight-black txt-tight-lines margin-block-end-half">Import a Fizzy account</h1>
|
||||
<div>Upload the .zip file from your Fizzy export</div>
|
||||
</header>
|
||||
|
||||
<%= form_with url: imports_path, class: "flex flex-column gap", data: { controller: "form" }, multipart: true do |form| %>
|
||||
<div class="flex flex-column gap-half">
|
||||
<%= form.file_field :file, accept: ".zip", required: true, class: "input" %>
|
||||
<p class="txt-small txt-deemphasized margin-none">Upload the .zip file from your Fizzy export.</p>
|
||||
</div>
|
||||
<%= form_with url: imports_path, class: "flex flex-column gap", data: { controller: "form upload-preview" }, multipart: true do |form| %>
|
||||
|
||||
<label class="btn input--upload">
|
||||
<div data-upload-preview-target="placeholder">Choose a file…</div>
|
||||
<div data-upload-preview-target="fileName" hidden></div>
|
||||
<%= form.file_field :file, accept: ".zip", required: true, data: { action: "upload-preview#previewFileName", upload_preview_target: "input" } %>
|
||||
</label>
|
||||
|
||||
<button type="submit" class="btn btn--link center txt-medium" data-form-target="submit">
|
||||
<span>Import</span>
|
||||
<%= icon_tag "arrow-right" %>
|
||||
<span>Start Import →</span>
|
||||
</button>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<% case @import.status %>
|
||||
<% when "pending", "processing" %>
|
||||
<p class="txt-medium">Your import is in progress. This may take a while for large accounts.</p>
|
||||
<p class="txt-small txt-deemphasized">This page will refresh automatically.</p>
|
||||
<p class="txt-small">This page will refresh automatically.</p>
|
||||
<meta http-equiv="refresh" content="5">
|
||||
<% when "completed" %>
|
||||
<p class="txt-medium txt-positive">Your import has completed successfully!</p>
|
||||
|
||||
Reference in New Issue
Block a user