From 7033d6584630401ccef6afe176fda884dc1d1e7f Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Sun, 6 Sep 2026 21:30:13 +0200 Subject: [PATCH] fix(ui): make shared switches visible across CMS themes --- src/app/admin/banners/banners-manager.tsx | 3 +- .../catalog-items-table/field-helpers.tsx | 8 +- .../permissions/[id]/rank-edit-client.tsx | 10 +- src/app/admin/polls/poll-form.tsx | 8 +- .../catalog-manager/catalog-access.module.css | 26 ----- .../admin/catalog-manager/inline-editor.tsx | 1 - src/components/ui/switch.module.css | 105 ++++++++++++++++++ src/components/ui/switch.tsx | 31 +----- 8 files changed, 131 insertions(+), 61 deletions(-) create mode 100644 src/components/ui/switch.module.css diff --git a/src/app/admin/banners/banners-manager.tsx b/src/app/admin/banners/banners-manager.tsx index 8fed05ce05..a0d196d97c 100644 --- a/src/app/admin/banners/banners-manager.tsx +++ b/src/app/admin/banners/banners-manager.tsx @@ -192,12 +192,13 @@ export function BannersManager({ banners }: Props) {
diff --git a/src/app/admin/catalog/[id]/catalog-items-table/field-helpers.tsx b/src/app/admin/catalog/[id]/catalog-items-table/field-helpers.tsx index 7f1d41ccc1..008904f0b9 100644 --- a/src/app/admin/catalog/[id]/catalog-items-table/field-helpers.tsx +++ b/src/app/admin/catalog/[id]/catalog-items-table/field-helpers.tsx @@ -1,7 +1,7 @@ "use client"; import { Check, ChevronsUpDown, Star } from "lucide-react"; -import { useMemo, useState } from "react"; +import { useId, useMemo, useState } from "react"; import { Button } from "@/components/ui/button"; import { Command, @@ -37,11 +37,15 @@ export function ToggleField({ onChange: (v: boolean) => void; disabled?: boolean; }) { + const id = useId(); const isChecked = checked ?? (value === 1 || value === "1"); return (
- +
- +

Hide from public

setGeneral({ ...general, hidden_rank: v ? "1" : "0" }) @@ -361,12 +364,15 @@ export function RankEditClient({
- +

Record to audit log

setGeneral({ ...general, log_commands: v ? "1" : "0" }) diff --git a/src/app/admin/polls/poll-form.tsx b/src/app/admin/polls/poll-form.tsx index 014e5c4fa6..a91b65ba6b 100644 --- a/src/app/admin/polls/poll-form.tsx +++ b/src/app/admin/polls/poll-form.tsx @@ -146,19 +146,23 @@ export function PollForm({ defaultValues }: PollFormProps) {
form.setValue("showResults", v ? 1 : 0)} /> - +
form.setValue("multipleChoice", v ? 1 : 0) } /> - +
diff --git a/src/components/admin/catalog-manager/catalog-access.module.css b/src/components/admin/catalog-manager/catalog-access.module.css index 11b4bcb7a4..a585a2eac8 100644 --- a/src/components/admin/catalog-manager/catalog-access.module.css +++ b/src/components/admin/catalog-manager/catalog-access.module.css @@ -39,32 +39,6 @@ line-height: 1.5; color: var(--admin-text-muted); } -.toggle[data-slot="switch"] { - width: 44px; - height: 24px; - border: 1px solid var(--admin-text-muted); - background: var(--admin-border); - cursor: pointer; -} -.toggle[data-checked] { - background: var(--admin-accent); - border-color: var(--admin-accent); -} -.toggle [data-slot="switch-thumb"] { - width: 18px; - height: 18px; - left: 2px; - background: var(--admin-text); - color: var(--admin-canvas); -} -.toggle[data-checked] [data-slot="switch-thumb"] { - left: 22px; -} -.toggle:focus-visible { - outline: 2px solid var(--admin-accent); - outline-offset: 3px; -} -.option[data-disabled] .toggle, .option[data-disabled] .label { cursor: not-allowed; } diff --git a/src/components/admin/catalog-manager/inline-editor.tsx b/src/components/admin/catalog-manager/inline-editor.tsx index 564a77ddaf..a8879b0579 100644 --- a/src/components/admin/catalog-manager/inline-editor.tsx +++ b/src/components/admin/catalog-manager/inline-editor.tsx @@ -864,7 +864,6 @@ function ToggleRow({ onCheckedChange={onChange} disabled={disabled} aria-describedby={`${id}-description`} - className={styles.toggle} />
diff --git a/src/components/ui/switch.module.css b/src/components/ui/switch.module.css new file mode 100644 index 0000000000..9378228864 --- /dev/null +++ b/src/components/ui/switch.module.css @@ -0,0 +1,105 @@ +.root { + --switch-off: var(--color-input); + --switch-on: var(--color-primary); + --switch-border: var(--color-muted-foreground); + --switch-thumb: var(--color-foreground); + --switch-mark: var(--color-background); + position: relative; + display: inline-flex; + flex-shrink: 0; + width: 44px; + height: 24px; + border: 1px solid var(--switch-border); + border-radius: 999px; + background: var(--switch-off); + cursor: pointer; + outline: none; + transition: + background-color 150ms, + border-color 150ms; +} +body:has([data-admin]) .root { + --switch-off: var(--admin-border); + --switch-on: var(--admin-accent); + --switch-border: var(--admin-text-muted); + --switch-thumb: var(--admin-text); + --switch-mark: var(--admin-canvas); +} +.root[data-checked] { + background: var(--switch-on); + border-color: var(--switch-on); +} +.root:focus-visible { + outline: 2px solid var(--switch-on); + outline-offset: 3px; +} +.root[data-disabled] { + cursor: not-allowed; + opacity: 0.5; +} +.thumb { + pointer-events: none; + position: absolute; + display: flex; + align-items: center; + justify-content: center; + width: 18px; + height: 18px; + top: 50%; + left: 2px; + transform: translateY(-50%); + border-radius: 999px; + background: var(--switch-thumb); + color: var(--switch-mark); + transition: left 150ms; +} +.root[data-checked] .thumb { + left: 22px; +} +.check { + width: 10px; + height: 10px; + stroke-width: 3; + opacity: 0; +} +.root[data-checked] .check { + opacity: 1; +} +.root[data-size="sm"] { + width: 32px; + height: 20px; +} +.root[data-size="sm"] .thumb { + width: 14px; + height: 14px; +} +.root[data-size="sm"][data-checked] .thumb { + left: 14px; +} +.root[data-size="sm"] .check { + width: 8px; + height: 8px; +} +@media (prefers-reduced-motion: reduce) { + .root, + .thumb { + transition: none; + } +} +@media (forced-colors: active) { + .root { + border-color: ButtonText; + background: Canvas; + } + .root[data-checked] { + background: Highlight; + border-color: Highlight; + } + .thumb { + background: ButtonText; + color: Canvas; + } + .root:focus-visible { + outline-color: Highlight; + } +} diff --git a/src/components/ui/switch.tsx b/src/components/ui/switch.tsx index 3d140508e5..0da12dfd3e 100644 --- a/src/components/ui/switch.tsx +++ b/src/components/ui/switch.tsx @@ -4,6 +4,7 @@ import { Switch as SwitchPrimitive } from "@base-ui/react/switch"; import { CheckIcon } from "lucide-react"; import { cn } from "@/lib/utils"; +import styles from "./switch.module.css"; function Switch({ className, @@ -16,35 +17,11 @@ function Switch({ - - + + );