Files
platform/todo/inputs-outside-forms/_index.md
T
pastilhas be29ae7aa7 delete two unreferenced components from another codebase
MarkdownEditor and ui/start-confetti-button had no importers anywhere in the repo
and both carried a different product's content: MarkdownEditor hardcoded
https://app.pertento.ai/logo.png with alt="Pertento", and start-confetti-button
spoke about 'the experiment' and 'Draft/Created' statuses.

Translating either would have put feature words into ui.*, which D6 forbids —
a shared namespace may not name a feature.

todo/inputs-outside-forms named MarkdownEditor as deliberately-unwrapped, so that
entry is updated rather than left pointing at a deleted file.
2026-08-23 04:18:08 +00:00

5.4 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 has zero call sites anywhere in the repo right now; it is shaped to be embedded in a future caller's own form (uncontrolled inputs with name attributes), so there's nothing to wrap yet. MarkdownEditor was named here too and was deleted on 2026-08-23 during the localization pass — it had no call sites and hardcoded another product's logo URL.
  • 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.