fix(web): UI polish — select placeholder, locked-field note, list overflow, sidebar toggle, heading wrap (#73)

Five small design/layout nits from the UI sweep:

- form.selectPlaceholder "— select —" → "Select…" / "Välj…", matching
  the affordance style of every other placeholder (Filter…, Search…).
- FieldForm in edit mode now explains its locked controls with a muted
  fields.lockedNote caption ("Key and type can't be changed after
  creation.") instead of leaving four silently disabled inputs.
- FieldList rows truncate long labels (min-w-0 on the row button +
  truncate on the label, shrink-0 on the badge and required marker)
  instead of overflowing the 20rem column.
- The sidebar collapse toggle is hidden on narrow viewports (hidden
  md:flex) instead of rendered permanently disabled/grayed — the rail
  is forced collapsed there anyway.
- PageTitle gains text-balance so long titles wrap evenly.

Closes #73

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 13:47:22 +02:00
parent 3ad0e56ecd
commit 62c569741f
7 changed files with 22 additions and 12 deletions
+9 -4
View File
@@ -90,18 +90,23 @@ export function FieldList({
>
<button
type="button"
className={cn("flex flex-1 items-center gap-2 rounded-sm text-left", focusRing)}
className={cn(
"flex min-w-0 flex-1 items-center gap-2 rounded-sm text-left",
focusRing,
)}
aria-pressed={def.key === selectedKey}
onClick={() => onSelect(def)}
>
<span className="font-medium">{labelText(def.labels, lang)}</span>
<span className="min-w-0 truncate font-medium">
{labelText(def.labels, lang)}
</span>
<span className="text-xs text-muted-foreground">{def.key}</span>
<Badge variant="secondary">
<Badge variant="secondary" className="shrink-0">
{t(`fields.types.${def.data_type}`)}
</Badge>
{def.required && (
<span
className="text-xs text-destructive"
className="shrink-0 text-xs text-destructive"
title={t("fields.required")}
aria-label={t("fields.required")}
>