feat(home): in-card "+ Add more files" replaces Streamlit's dropzone

Mockup §file-add lands as the canonical import affordance:

- Streamlit's ``st.file_uploader`` widget is still mounted (only path
  that actually receives browser file events), but parked off-screen
  via a new ``[data-testid="stFileUploader"] { position:absolute;
  left:-10000px; … pointer-events:none }`` rule. Its hidden
  ``<input type="file">`` stays reachable to JavaScript.
- The Files card is now always rendered (header + bordered body).
  The bottom row of the card is a ``button.dt-file-add`` styled per
  mockup §file-add: dashed top border bleeding to the card edges,
  surface-hover background, ``+ Add more files`` text in
  ``--ink-secondary``, accent-fill on hover.
- A small ``<script>`` shipped through ``st.iframe`` wires the
  button: ``click → input.click()`` on the off-screen
  ``stFileUploaderDropzoneInput``. Streamlit's HTML sanitizer
  strips inline ``onclick`` from ``unsafe_allow_html`` content, so
  the binding has to come from a real script element — same pattern
  the sticky footer and Upload→Import rewriter use. A
  ``MutationObserver`` re-wires the button when Streamlit remounts
  it across reruns. The ``dataset.dtWired`` guard prevents double
  binding.

Section structure also tightened to match the mockup:

- Section heading is now ``<h2>Files</h2>`` (was ``### Import one
  or more files to start``) with the count + total size on the
  right of the same flex row. When no files: ``No files imported
  yet``. When files exist: ``1 file · 4.8 KB total``.
- Dropped the ``upload.intro_multi`` caption and the
  ``upload.empty_state`` info banner — the card itself plus the
  in-card Add button cover both prompts.
- Empty state now ends after the Files card (no stats / no action
  bar / no findings rendered) — matches mockup's single-section
  empty view.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-19 00:56:11 +00:00
parent a9788ba712
commit 6703e2c15c
2 changed files with 211 additions and 98 deletions

View File

@@ -520,6 +520,61 @@ div[data-testid="stContainer"][data-border="true"] {
font-feature-settings: "ss02";
}
/* "+ Add more files" — last row of the files card (mockup §file-add).
The button stays in the document; ``onclick`` triggers a programmatic
click on Streamlit's (off-screen) file_uploader input so the OS file
picker opens. Negative margins bleed the button to the card edges so
the dashed top-border and corner radii match the surrounding card
chrome. */
.dt-file-add {
display: flex !important;
align-items: center;
justify-content: center;
gap: 8px;
width: calc(100% + 2rem);
padding: 12px 16px;
background: var(--surface-hover);
border: none;
border-top: 1px dashed var(--border-strong);
border-radius: 0 0 var(--r-lg) var(--r-lg);
cursor: pointer;
font-family: var(--font-sans) !important;
font-size: 13px !important;
font-weight: 500 !important;
color: var(--ink-secondary) !important;
margin: 14px -1rem -1rem;
line-height: 1;
transition: background 0.12s ease, color 0.12s ease;
}
.dt-file-add:hover {
background: var(--accent-fill);
color: var(--accent) !important;
}
.dt-file-add svg {
width: 14px; height: 14px;
stroke-width: 2;
}
/* Empty-state placeholder centered in the empty files card. */
.dt-files-empty {
margin: 8px 0 4px !important;
text-align: center;
color: var(--ink-tertiary) !important;
font-size: 13px;
}
/* Streamlit's file_uploader is rendered off-screen so the OS file
picker stays wired up to our in-card "Add more files" button — its
input element is still reachable via JS ``.click()``. */
.dt-fileuploader-offscreen [data-testid="stFileUploader"] {
position: absolute !important;
left: -10000px !important;
width: 1px !important;
height: 1px !important;
overflow: hidden !important;
pointer-events: none !important;
}
/* ---------- Findings — per-file group cards (mockup §findings) ---------- */
.dt-finding-group-head {
display: flex;