diff --git a/docs/design-rules.md b/docs/design-rules.md index fbabdc87d0..aa03269fc3 100644 --- a/docs/design-rules.md +++ b/docs/design-rules.md @@ -97,8 +97,10 @@ bordered box takes its parent's radius minus 1px: `before:rounded-lg-inset` insi step of the hue in light, where the fill itself is near 3:1 as type, and the fill in dark. Fills, borders and strokes keep the tone. Write the utility; never a fill token as `color` in a style object. -- Selected text takes `primary-a4` as its highlight and reads in `foreground`, set once in - tokens.css. No `selection:` utility at a call site. +- Selected text is `primary-foreground` on `primary`, set once in tokens.css: an opaque pair, so it + reads the same over muted text or a tone. A chip keeps its own look when selected (a kit `badge`, + or a label on a solid fill: `text-on-fill`, `text-primary-foreground`): a band inside a fill + only fights it, so a thin underline in the chip's own ink marks the selected letters. No `selection:` utility at a call site. - Washes are translucent and read the same on any surface: `surface-faint`, `surface-sunken`, `surface-strong`. - A see-through surface is a token, never `bg-background/NN` or `bg-card/NN` diff --git a/packages/ui/src/styles/tokens.css b/packages/ui/src/styles/tokens.css index e470314dc7..60023a559d 100644 --- a/packages/ui/src/styles/tokens.css +++ b/packages/ui/src/styles/tokens.css @@ -812,11 +812,25 @@ * { @apply border-border outline-ring/50; } - /* Selected text takes the primary's strong wash instead of the system blue, and reads in - `foreground`: a muted or toned run would fall under 4.5:1 on the wash. */ + /* Selected text takes the primary instead of the system blue. Both halves are opaque, so the + pair reads the same over a muted run, a tone, or a filled badge. */ ::selection { - background-color: var(--color-primary-a4); - color: var(--color-foreground); + background-color: var(--color-primary); + color: var(--color-primary-foreground); + } + /* A chip keeps its own look when selected: a band inside a fill or a tint only fights it. A + thin underline in its own ink marks the selected letters instead. */ + [data-slot="badge"]::selection, + [data-slot="badge"] ::selection, + .text-on-fill::selection, + .text-on-fill ::selection, + .text-primary-foreground::selection, + .text-primary-foreground ::selection { + background-color: transparent; + color: currentColor; + text-decoration: underline; + text-decoration-thickness: 1px; + text-underline-offset: 2px; } body { @apply font-sans bg-background text-foreground; diff --git a/packages/views/src/ui/native-select.styles.ts b/packages/views/src/ui/native-select.styles.ts index ca737f5460..c8922d6a95 100644 --- a/packages/views/src/ui/native-select.styles.ts +++ b/packages/views/src/ui/native-select.styles.ts @@ -1,7 +1,7 @@ export const nativeSelectWrapperStyles = "group/native-select relative w-fit has-[select:disabled]:opacity-50" export const nativeSelectStyles = - "border-input placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 dark:hover:bg-input/50 dark:active:bg-input/50 focus-visible:border-ring focus-visible:ring-ring aria-invalid:ring-destructive-a3 dark:aria-invalid:ring-destructive-a4 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 h-8 w-full min-w-0 appearance-none rounded-lg border bg-transparent py-1 pr-8 pl-2.5 text-xs select-none focus-visible:ring-1 aria-invalid:ring-1 data-[size=sm]:h-7 data-[size=sm]:rounded-lg data-[size=sm]:py-0.5 data-leading:pl-7 outline-none disabled:pointer-events-none disabled:cursor-not-allowed" + "border-input placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 dark:active:bg-input/50 focus-visible:border-ring focus-visible:ring-ring aria-invalid:ring-destructive-a3 dark:aria-invalid:ring-destructive-a4 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 h-8 w-full min-w-0 appearance-none rounded-lg border bg-transparent py-1 pr-8 pl-2.5 text-xs select-none focus-visible:ring-1 aria-invalid:ring-1 data-[size=sm]:h-7 data-[size=sm]:rounded-lg data-[size=sm]:py-0.5 data-leading:pl-7 outline-none disabled:pointer-events-none disabled:cursor-not-allowed" export const nativeSelectIconStyles = "text-muted-foreground top-1/2 right-2.5 size-4 -translate-y-1/2 pointer-events-none absolute select-none"