feat(design): every button on its family, the chip primitive, the lint rule (E28 S3b2)
The second half of the button sweep: the remaining hand-rolled buttons in
feature components, the design lab and the components/ui composites now
stand on Button, IconButton, Pressable, Chip or DragHandle.
- Chip + DismissibleChip (filter / token / tag / suggest / ghost, 24px
floor, 44 on touch) replace five chip geometries; FilterChipGroup
renders Chips; overflow lanes measure a mirror painted by chipClass.
- The Plex control row is IconButton's player rung (36, 20px glyph,
round, overlay; 44 on touch); the YT modal bar is on the sm rung with
pressed cycle toggles and names that survive a folded label.
- New variants: IconButton ghost-accent, danger-soft; Button warn on a
new state-warn utility. The .btn-{tone} recipes and btnCls are gone.
- Fixed on the way: membership rows (collection editor, Plex playlist
add) announce checked/mixed; a one-letter tag chip was 21px wide;
descriptionLinks moved out of lib/ (it renders components).
- local/button-primitive: a raw <button>/<FocusSafeButton> outside the
control-primitive files is a lint error (contract-tested, seen red).
This commit is contained in:
@@ -12,7 +12,8 @@ import { LoadingState, StateMessage } from "./ui/QueryState";
|
||||
import PosterTile from "./PosterTile";
|
||||
import PlexLibraryPicker from "./PlexLibraryPicker";
|
||||
import NavGrid from "./ui/NavGrid";
|
||||
import { FocusSafeButton } from "./ui/FocusSafeButton";
|
||||
import { Button } from "./ui/Button";
|
||||
import { IconButton } from "./ui/IconButton";
|
||||
|
||||
// A collection tile's sub-line: item count · total runtime (each dropped when unknown, e.g. show-only
|
||||
// collections have no movie runtime).
|
||||
@@ -109,13 +110,9 @@ function NewCollectionPanel({
|
||||
<div className="glass-card mb-6 rounded-2xl p-4">
|
||||
<div className="mb-2 flex items-center justify-between gap-2">
|
||||
<h3 className="text-sm font-semibold">{t("plex.collection.newCollection")}</h3>
|
||||
<button
|
||||
onClick={onClose}
|
||||
aria-label={t("common.close")}
|
||||
className="glass-hover grid h-8 w-8 place-items-center rounded-lg"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</button>
|
||||
<IconButton size="md" onClick={onClose} label={t("common.close")}>
|
||||
<X />
|
||||
</IconButton>
|
||||
</div>
|
||||
<input
|
||||
autoFocus
|
||||
@@ -146,14 +143,15 @@ function NewCollectionPanel({
|
||||
term={term}
|
||||
enabled={nameOk}
|
||||
renderAction={(c) => (
|
||||
<FocusSafeButton
|
||||
<Button
|
||||
variant="glass"
|
||||
size="xs"
|
||||
icon={<Check />}
|
||||
onClick={() => create(c)}
|
||||
disabled={busy}
|
||||
className="glass-card glass-hover inline-flex items-center gap-1 rounded-lg px-2.5 py-1 text-xs disabled:opacity-50"
|
||||
loading={busy}
|
||||
>
|
||||
<Check className="h-3.5 w-3.5" />
|
||||
{t("plex.collection.createWith")}
|
||||
</FocusSafeButton>
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -190,13 +188,9 @@ export function PlexCollectionsBrowse({ onPick }: { onPick: (id: string, title:
|
||||
className="glass-card w-full max-w-sm rounded-lg px-3 py-1.5 text-sm focus:outline-hidden focus:ring-2 focus:ring-accent/40"
|
||||
/>
|
||||
{isAdmin && !creating && (
|
||||
<button
|
||||
onClick={() => setCreating(true)}
|
||||
className="glass-card glass-hover inline-flex shrink-0 items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
<Button variant="glass" size="sm" icon={<Plus />} onClick={() => setCreating(true)}>
|
||||
{t("plex.collection.newCollection")}
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{creating && (
|
||||
|
||||
Reference in New Issue
Block a user