Nicer file input

This commit is contained in:
Andy Smith
2026-01-20 12:02:00 -06:00
committed by Stanko K.R.
parent d55aa25f9a
commit ba260db8a2
4 changed files with 70 additions and 28 deletions
+34 -13
View File
@@ -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]
}
}
+13 -9
View File
@@ -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>
+1 -1
View File
@@ -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>