feat(ui): migrate the canonical action-button surface onto <Button>

Sweep the rounded-lg solid/ghost/outline action-button family onto the shared primitive:
ConfirmProvider, ErrorDialog, DownloadDialog, DownloadCenter, downloadModals, downloadAdmin,
ProfileEditor, PersonalViewsModal, SettingsPanel, WatchPage, DraftSaveBar. Deliberately left
on their own styles per the agreed scope: login/onboarding rounded-xl CTAs (Welcome/Onboarding/
Setup/KeyGate), glass Plex surfaces, segmented pills/toggles/switches/chips, dropdown triggers,
data-driven Banner/tone maps, text-xs dense buttons, and tiny inline p-1/p-1.5 icon controls —
none map 1:1 to a variant+size without a visual change, and the repo has no tailwind-merge.
This commit is contained in:
2026-08-28 03:12:29 +02:00
parent 4892c38466
commit 5280949667
11 changed files with 97 additions and 98 deletions
+14 -10
View File
@@ -18,6 +18,7 @@ import {
import { CSS } from "@dnd-kit/utilities";
import { coercePlexFilters, type FeedFilters, type PlexFilters, type SavedView } from "../lib/api";
import Modal from "./Modal";
import { Button } from "./ui/Button";
import { useSavedViews, asFilters } from "./SavedViewsProvider";
import { useActiveFilters } from "../lib/useActiveFilters";
import { buildPlexActiveFilters } from "./usePlexActiveFilters";
@@ -202,14 +203,16 @@ export default function PersonalViewsModal() {
placeholder={t("views.namePlaceholder")}
className="min-w-0 flex-1 rounded-lg border border-border bg-surface px-2 py-1.5 text-sm focus:border-accent focus:outline-hidden focus:ring-2 focus:ring-accent/30"
/>
<button
<Button
variant="primary"
size="sm"
iconOnly
icon={<BookmarkPlus className="h-4 w-4" />}
label={t("views.save")}
onClick={onCreate}
disabled={!createName.trim()}
title={t("views.save")}
className="inline-flex shrink-0 items-center gap-1 rounded-lg btn-primary px-2.5 py-1.5 text-sm font-semibold disabled:opacity-40"
>
<BookmarkPlus className="h-4 w-4" />
</button>
className="shrink-0"
/>
</div>
</div>
@@ -272,13 +275,14 @@ export default function PersonalViewsModal() {
)}
</div>
<div className="mt-auto flex flex-wrap items-center gap-2 border-t border-border/60 pt-3">
<button
<Button
variant="primary"
size="sm"
icon={<Play className="h-3.5 w-3.5" />}
onClick={() => apply(selected)}
className="inline-flex items-center gap-1.5 rounded-lg btn-primary px-3 py-1.5 text-sm font-semibold"
>
<Play className="h-3.5 w-3.5" />
{t("views.apply")}
</button>
</Button>
<button
onClick={async () => {
const saved = await saveCurrent(selected.id);