Files
platform/todo/inputs-outside-forms/_index.md
T
pastilhasandClaude Fable 5 6071ded175 todo: one file per item, grouped by theme, with a generated index
TODO.md had reached 1050 lines and 72 open items across 28 sections, read mostly
on a phone. It is now a directory: todo/<theme>/<item>.md, one card per file, with
frontmatter carrying id, status, created date and order, and the prose body copied
across verbatim. TODO.md becomes a generated index (bun run todo:index).

Dates: where an item's prose stated one it is used; otherwise its old section's;
otherwise 2026-08-20, floored at the day before the split rather than invented.
date_source records which.

Shaped for a two-way Kanban board, filed as todo/tooling — a card is a file, id is
the identity, frontmatter is the machine's half and the body is the owner's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 05:42:39 +00:00

5.3 KiB

theme, heading, kind
theme heading kind
inputs-outside-forms Inputs outside forms (2026-08-19) — swept, fixed, closed theme

The "19 files" count in the previous version of this entry came from one grep (components/ui/input) and was a starting point, not the answer. A wider sweep — bare <input> and <textarea> too, across the platform and every installed plugin — found 87 files with a matching element and no enclosing <form>. Three were false positives (the Input/Textarea primitives themselves, and a DataTable test file). Of the remaining 84, 41 were fixed (real forms, single fields with an obvious action, or multi-field editors) and 43 were left alone, almost all because they're a search/filter box with nothing to submit.

Fixed — platform (24 files, one commit): CapabilityPage, ApifyConfig, ApiKeys, DavAppPasswords, GoogleOAuthConfig, AIHarnessesSection (local-provider connect, its auth step, and both API-key edit rows), OCRSection, SMTPSection (split into two independent forms — save vs. send-test-email, since one form would have made Enter in the test-email field trigger Save), STTSection, TTSSection, AppStoreDetail, ChatHeader, BackgroundJobDialog, QuestionActivity, WebpageDialog, DirPickerModal, SessionRow, CommandHqCategories, FileItem, NewEntryDialog, TaskRunnerModal (the Agentic and Pipeline ready phases), PreviewHeader, widgets/DailyGoals, widgets/Pomodoro.

Fixed — plugins (17 files, one commit per plugin, each pushed to its own remote): bitcoin-wallet (ChainSourceCard, RescanCard, WalletSettingsView), email (Compose, EmailAccounts), invoices (DocumentEditor, RecordEditors, SendDocumentDialog), offscale (NodesView — rename and tags fields), soulseek (SoulseekConnection), transmission (ConnectionView, SettingsView, AddTorrentDialog, MoveTorrentDialog, RenameDialog, TorrentOptionsDialog), vault (VaultPanel). jellyfin and music needed no changes.

Left alone — search/filter boxes with no submit action (the large majority of the 43): JobsPage, SettingsPanel, SearchInput, sounds/Catalog, widgets/QuickNotes, Dashboards/DashboardListApp, SystemMonitor/DockerView, FileBrowser* toolbar/header/view-container files, ChatHistory list filters, invoices' six list views (CustomersListView, EstimatesListView, ExpensesListView, InvoicesListView, ItemsListView, ReportsView, components.tsx), jellyfin (PlayerControls — range sliders, not text fields — and SearchSection), music (MusicBrowser, MusicPlayerHost), offscale (Cards, PolicyAssistant — already handles Enter/Shift+Enter correctly, PolicyView — a textarea, never auto-submits), soulseek (SearchResults, SharesBrowser), transmission (TorrentToolbar), FileViewer renderers (AudioRenderer/VideoRenderer — volume/seek sliders), and the main chat composers (InputArea, ChatLauncher, SoulseekChat) — all textareas with their own Enter-sends/Shift+Enter-newlines handling, where a <form> would add nothing and risks regressing that handling.

Left alone — genuinely ambiguous, flagged rather than guessed:

  • TaskRunnerModal's ScriptRunner ready phase offers three simultaneously-visible, non-equivalent primary actions ("Run here" / "Queue" / "Run as job"); there's no single canonical action for Enter to trigger.
  • Dashboards/DashboardPreview's NamePanel (name + description) has its submit button in a different, independently-mounted panel (CreatePanel) elsewhere in the workspace layout tree — a <form> can't span two panels without restructuring the wizard.
  • ColorPicker and MarkdownEditor have zero call sites anywhere in the repo right now; both are shaped to be embedded in a future caller's own form (uncontrolled inputs with name attributes, or a plain controlled textarea with no submit of its own), so there's nothing to wrap yet.
  • widgets/Weather's LocationSetup is a live autocomplete with several result rows and no single obvious Enter target (which of N matches?).

Noticed, out of scope, not fixed:

  • ModelSelector's provider-picker button has no type attribute — harmless today only because it currently sits outside every <form>; a landmine if that layout changes.
  • MusicBrowser's filter input uses (e) => instead of the house ev convention — pre-existing, not touched since the file needed no fix.
  • EmailList.tsx, and a few plugin files touched by this sweep (VaultPanel, ConnectionView, SoulseekConnection, ChainSourceCard), have pre-existing prettier --check drift outside the lines this pass touched — left as found, not reformatted, per "don't reformat what you're not fixing." Relatedly: prettier --write on a plugins/<name>/… path silently no-ops when run from the platform root, because Prettier v3 respects the root .gitignore and /plugins/*/ is in it — it exits 0 with no diff and no error. Formatting a plugin file requires running prettier from inside that plugin's own directory (still resolves the platform's .prettierrc by walking up).
  • A few "Save"/"I've saved it"-style buttons (ApiKeys, DavAppPasswords, DirPickerModal) have no type attribute but currently sit outside any <form>, so it's harmless today — worth remembering if a future edit wraps that region.