From 6dd4c7b21e97bf7bb83ce6cffeb6270b43247eea Mon Sep 17 00:00:00 2001 From: Tsahi Matsliah Date: Mon, 1 Jun 2026 23:58:09 +0300 Subject: [PATCH 1/6] feat(shared): redesign checkbox & radio to match Toggle + Button system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align Checkbox and RadioItem with the redesigned Toggle/Switch and Button system so fields, buttons, toggles, checkboxes and radios read as one family: - single semantic brand fill when selected (accent-cabbage-default) with a solid white glyph (white check / white center dot), identical in light & dark - surface-hover halo, surface-focus blue keyboard ring, and a subtle press squeeze — theme-aware via semantic tokens, removing the per-theme overrides Adds /dev/checkbox-radio: a before/after comparison table across all states and variants in light & dark, with live hover/focus/press. Co-Authored-By: Claude Opus 4.8 --- .../src/components/fields/Checkbox.module.css | 114 ++-- .../shared/src/components/fields/Checkbox.tsx | 2 +- .../components/fields/RadioItem.module.css | 87 +-- .../src/components/fields/RadioItem.tsx | 2 +- .../LegacyCheckbox.module.css | 106 ++++ .../devCheckboxRadio/LegacyCheckbox.tsx | 102 ++++ .../devCheckboxRadio/LegacyRadio.tsx | 152 ++++++ .../LegacyRadioItem.module.css | 59 ++ packages/webapp/pages/dev/checkbox-radio.tsx | 503 ++++++++++++++++++ 9 files changed, 1026 insertions(+), 101 deletions(-) create mode 100644 packages/webapp/components/devCheckboxRadio/LegacyCheckbox.module.css create mode 100644 packages/webapp/components/devCheckboxRadio/LegacyCheckbox.tsx create mode 100644 packages/webapp/components/devCheckboxRadio/LegacyRadio.tsx create mode 100644 packages/webapp/components/devCheckboxRadio/LegacyRadioItem.module.css create mode 100644 packages/webapp/pages/dev/checkbox-radio.tsx diff --git a/packages/shared/src/components/fields/Checkbox.module.css b/packages/shared/src/components/fields/Checkbox.module.css index 8676d8c232b..d2b7b01025c 100644 --- a/packages/shared/src/components/fields/Checkbox.module.css +++ b/packages/shared/src/components/fields/Checkbox.module.css @@ -1,4 +1,20 @@ +/* + * Checkbox — daily.dev design system. + * Aligned with the redesigned Toggle/Switch and Button system so fields, + * buttons, toggles, checkboxes and radios read as one family: + * - a single semantic brand fill when checked (accent-cabbage-default) with a + * solid white glyph, identical in light & dark (no per-theme overrides); + * - a soft surface-hover halo behind the box on hover; + * - a surface-focus (blueCheese) keyboard ring on :focus-visible; + * - a subtle press squeeze for tactile feedback (à la the Switch knob). + */ + .checkmark { + background: transparent; + transition: background-color 0.12s linear, border-color 0.12s linear, + box-shadow 0.1s linear, transform 0.15s cubic-bezier(0.16, 1, 0.3, 1); + + /* Soft surface halo behind the box; the offset trick centers a 2rem square. */ &:before { content: ''; position: absolute; @@ -10,94 +26,70 @@ height: 2rem; margin: auto; border-radius: 0.625rem; + background: var(--theme-surface-hover); opacity: 0; - transition: background-color 0.1s linear, opacity 0.1s linear; + transition: background-color 0.12s linear, opacity 0.12s linear; pointer-events: none; z-index: -1; } } +/* The check glyph stays solid white in every theme/state for contrast. */ +.checkmark :global(.icon) { + color: theme('colors.raw.salt.0'); +} + .label { - &:global(.disabled), &:global(.checked.disabled) { + &:global(.disabled), + &:global(.checked.disabled) { color: var(--theme-text-disabled); } &:global(.checked) { color: var(--theme-text-primary); - & .checkmark { - & :global(.icon) { - opacity: 1; - } + & .checkmark :global(.icon) { + opacity: 1; } } - /* &:hover, */ - &:hover:not(:global(.disabled)), - &:focus-within:not(:global(.disabled)) { - & .checkmark { - border-color: var(--theme-text-primary); + /* Hover / keyboard focus lift the border and reveal the halo. */ + &:hover:not(:global(.disabled)) .checkmark, + & input:focus-visible ~ .checkmark { + border-color: var(--theme-text-primary); - &:before { - background: var(--theme-surface-hover); - opacity: 1; - } + &:before { + opacity: 1; } } - &:active { - & .checkmark:before { - background: var(--theme-active); - } + /* Keyboard focus — an even blue ring (matches Switch / fields v2). */ + & input:focus-visible ~ .checkmark { + box-shadow: 0 0 0 2px var(--theme-surface-focus); } - &:global(.checked) { - & .checkmark { - background: theme('colors.raw.cabbage.40'); - border-color: transparent; - } - - &:global(.disabled) { - & .checkmark { - background: var(--theme-text-disabled); - } - } - - &:hover:not(:global(.disabled)), - &:focus-within:not(:global(.disabled)) { - & .checkmark { - background: theme('colors.raw.cabbage.20'); - - &:before { - background: theme('colors.overlay.quaternary.cabbage'); - } - } - } - - &:active { - & .checkmark:before { - background: theme('colors.overlay.tertiary.cabbage'); - } - } + /* Press — a subtle squeeze for tactile feedback. */ + &:active:not(:global(.disabled)) .checkmark { + transform: scale(0.9); } -} -:global(.light) .label:global(.checked) .checkmark { - background: theme('colors.raw.cabbage.60'); -} + /* Checked — solid brand fill, identical in light & dark. */ + &:global(.checked) .checkmark { + background: var(--theme-accent-cabbage-default); + border-color: transparent; + } -:global(.light) .label:global(.checked):hover .checkmark, -:global(.light) .label:global(.checked):focus-within .checkmark { - background: theme('colors.raw.cabbage.80'); -} + &:global(.checked):hover:not(:global(.disabled)) .checkmark:before, + &:global(.checked) input:focus-visible ~ .checkmark:before { + background: theme('colors.overlay.quaternary.cabbage'); + } -@media (prefers-color-scheme: light) { - :global(.auto) .label:global(.checked) .checkmark { - background: theme('colors.raw.cabbage.60'); + /* Disabled — muted surface, no brand. */ + &:global(.disabled) .checkmark { + border-color: var(--theme-surface-disabled); } - :global(.auto) .label:global(.checked):hover .checkmark, - :global(.auto) .label:global(.checked):focus-within .checkmark { - background: theme('colors.raw.cabbage.80'); + &:global(.checked.disabled) .checkmark { + background: var(--theme-surface-disabled); } } diff --git a/packages/shared/src/components/fields/Checkbox.tsx b/packages/shared/src/components/fields/Checkbox.tsx index 947cae7f16a..3329884e416 100644 --- a/packages/shared/src/components/fields/Checkbox.tsx +++ b/packages/shared/src/components/fields/Checkbox.tsx @@ -86,7 +86,7 @@ export const Checkbox = forwardRef(function Checkbox( > diff --git a/packages/shared/src/components/fields/RadioItem.module.css b/packages/shared/src/components/fields/RadioItem.module.css index d9eae1c7c2a..63564f99c5d 100644 --- a/packages/shared/src/components/fields/RadioItem.module.css +++ b/packages/shared/src/components/fields/RadioItem.module.css @@ -1,55 +1,66 @@ -.item { - &.checked { - @apply text-text-primary; +/* + * Radio — daily.dev design system. + * Same family as the redesigned Toggle/Switch, Checkbox and Button system: + * - selected = a solid brand disc (accent-cabbage-default) with a white center + * dot, identical in light & dark (no per-theme overrides); + * - a soft surface-hover halo behind the control on hover/focus; + * - a surface-focus (blueCheese) keyboard ring on :focus-visible; + * - a subtle press squeeze for tactile feedback. + */ - & .innerRing { - @apply border-4 border-raw-cabbage-40 bg-raw-cabbage-80; - } +.checkmark { + transition: background-color 0.12s linear; +} + +.innerRing { + position: relative; + transition: background-color 0.12s linear, border-color 0.12s linear, + box-shadow 0.1s linear, transform 0.15s cubic-bezier(0.16, 1, 0.3, 1); + + /* White center dot — scales in when selected. */ + &:after { + content: ''; + position: absolute; + inset: 0; + margin: auto; + width: 0.5rem; + height: 0.5rem; + border-radius: 9999px; + background: theme('colors.raw.salt.0'); + transform: scale(0); + transition: transform 0.15s cubic-bezier(0.16, 1, 0.3, 1); } } -.item:hover .checkmark, input:focus-visible ~ .checkmark { - @apply bg-surface-hover; +.item.checked .innerRing { + @apply border-accent-cabbage-default bg-accent-cabbage-default; - & .innerRing { - @apply border-4 border-text-primary; + &:after { + transform: scale(1); } } -.item.checked:hover .checkmark, .checked input:focus-visible ~ .checkmark { - background: theme('colors.raw.cabbage.50')3D; +/* Hover / keyboard focus reveal the halo and lift the resting border. */ +.item:hover .checkmark, +.item input:focus-visible ~ .checkmark { + @apply bg-surface-hover; & .innerRing { - @apply border-raw-cabbage-20; + @apply border-text-primary; } } -:global(.light) { - & .item.checked { - & .innerRing { - @apply border-raw-cabbage-60 bg-raw-cabbage-20; - } - } +.item.checked:hover .checkmark .innerRing, +.item.checked input:focus-visible ~ .checkmark .innerRing { + @apply border-accent-cabbage-default; +} - & .item.checked:hover .checkmark, & .checked input:focus-visible ~ .checkmark { - & .innerRing { - @apply border-raw-cabbage-80; - } - } +/* Keyboard focus — an even blue ring (matches Switch / fields v2). */ +.item input:focus-visible ~ .checkmark .innerRing { + box-shadow: 0 0 0 2px var(--theme-surface-focus); } -@media (prefers-color-scheme: light) { - :global(.auto) { - & .item.checked { - & .innerRing { - @apply border-raw-cabbage-60 bg-raw-cabbage-20; - } - } - - & .item.checked:hover .checkmark, & .checked input:focus-visible ~ .checkmark { - & .innerRing { - @apply border-raw-cabbage-80; - } - } - } +/* Press — a subtle squeeze for tactile feedback. */ +.item:active .innerRing { + transform: scale(0.9); } diff --git a/packages/shared/src/components/fields/RadioItem.tsx b/packages/shared/src/components/fields/RadioItem.tsx index 1502677dbf0..11920e700bb 100644 --- a/packages/shared/src/components/fields/RadioItem.tsx +++ b/packages/shared/src/components/fields/RadioItem.tsx @@ -69,7 +69,7 @@ export function RadioItem({ > { + name: string; + checked?: boolean; + id?: string; + children?: ReactNode; + className?: string; + checkmarkClassName?: string; + onToggleCallback?: (checked: boolean) => unknown; +} + +export const LegacyCheckbox = forwardRef(function LegacyCheckbox( + { + name, + checked, + children, + className, + checkmarkClassName, + onToggleCallback, + id = '', + disabled, + defaultChecked, + ...props + }: LegacyCheckboxProps, + ref: LegacyRef, +): ReactElement { + const [actualChecked, setActualChecked] = useState(checked ?? defaultChecked); + const checkId = useId(); + const inputId = id.concat(checkId); + + useEffect(() => { + setActualChecked(checked ?? defaultChecked); + }, [checked, defaultChecked]); + + const onChange = (event: ChangeEvent): void => { + setActualChecked(event.target.checked); + onToggleCallback?.(event.target.checked); + }; + + return ( + + ); +}); diff --git a/packages/webapp/components/devCheckboxRadio/LegacyRadio.tsx b/packages/webapp/components/devCheckboxRadio/LegacyRadio.tsx new file mode 100644 index 00000000000..226d01e2478 --- /dev/null +++ b/packages/webapp/components/devCheckboxRadio/LegacyRadio.tsx @@ -0,0 +1,152 @@ +import type { InputHTMLAttributes, ReactElement, ReactNode } from 'react'; +import React from 'react'; +import classNames from 'classnames'; +import ConditionalWrapper from '@dailydotdev/shared/src/components/ConditionalWrapper'; +import styles from './LegacyRadioItem.module.css'; + +// Frozen snapshot of the previous Radio design, used only by the +// /dev/checkbox-radio review page. Do not use in production code. + +interface ItemClassName { + wrapper?: string; + content?: string; +} + +export interface LegacyRadioItemProps + extends Omit, 'type' | 'className'> { + value?: T; + label?: ReactNode; + className?: ItemClassName; + afterElement?: ReactNode; + reverse?: boolean; +} + +function LegacyRadioItem({ + children, + className = {}, + checked, + disabled, + afterElement, + reverse, + ...props +}: LegacyRadioItemProps): ReactElement { + const { id } = props; + return ( + ( +
+ {component} +
+ )} + > + + {afterElement} +
+ ); +} + +export interface LegacyClassName { + container?: string; + content?: string; + label?: string; +} + +export interface LegacyRadioProps { + name: string; + options: LegacyRadioItemProps[]; + value?: T; + onChange: (value: T) => unknown; + className?: LegacyClassName; + disabled?: boolean; + reverse?: boolean; + valid?: boolean; +} + +export function LegacyRadio({ + name, + options, + value, + onChange, + className = {}, + disabled, + reverse, + valid, +}: LegacyRadioProps): ReactElement { + return ( +
+ {options.map((option) => ( + option.value !== undefined && onChange(option.value)} + className={{ + content: classNames( + 'truncate', + className.content, + option?.className?.content, + ), + wrapper: option.className?.wrapper, + }} + afterElement={option.afterElement} + reverse={reverse} + > + + {option.label} + + + ))} +
+ ); +} diff --git a/packages/webapp/components/devCheckboxRadio/LegacyRadioItem.module.css b/packages/webapp/components/devCheckboxRadio/LegacyRadioItem.module.css new file mode 100644 index 00000000000..14e15a245d2 --- /dev/null +++ b/packages/webapp/components/devCheckboxRadio/LegacyRadioItem.module.css @@ -0,0 +1,59 @@ +/* Frozen snapshot of the PREVIOUS Radio design, used only by the + * /dev/checkbox-radio review page for the before/after comparison. + * Do not use in production code. */ + +.item { + &.checked { + @apply text-text-primary; + + & .innerRing { + @apply border-4 border-raw-cabbage-40 bg-raw-cabbage-80; + } + } +} + +.item:hover .checkmark, input:focus-visible ~ .checkmark { + @apply bg-surface-hover; + + & .innerRing { + @apply border-4 border-text-primary; + } +} + +.item.checked:hover .checkmark, .checked input:focus-visible ~ .checkmark { + background: theme('colors.raw.cabbage.50')3D; + + & .innerRing { + @apply border-raw-cabbage-20; + } +} + +:global(.light) { + & .item.checked { + & .innerRing { + @apply border-raw-cabbage-60 bg-raw-cabbage-20; + } + } + + & .item.checked:hover .checkmark, & .checked input:focus-visible ~ .checkmark { + & .innerRing { + @apply border-raw-cabbage-80; + } + } +} + +@media (prefers-color-scheme: light) { + :global(.auto) { + & .item.checked { + & .innerRing { + @apply border-raw-cabbage-60 bg-raw-cabbage-20; + } + } + + & .item.checked:hover .checkmark, & .checked input:focus-visible ~ .checkmark { + & .innerRing { + @apply border-raw-cabbage-80; + } + } + } +} diff --git a/packages/webapp/pages/dev/checkbox-radio.tsx b/packages/webapp/pages/dev/checkbox-radio.tsx new file mode 100644 index 00000000000..450ed60a735 --- /dev/null +++ b/packages/webapp/pages/dev/checkbox-radio.tsx @@ -0,0 +1,503 @@ +import type { ReactElement, ReactNode } from 'react'; +import React, { useEffect, useId, useState } from 'react'; +import { NextSeo } from 'next-seo'; +import { Checkbox } from '@dailydotdev/shared/src/components/fields/Checkbox'; +import { Radio } from '@dailydotdev/shared/src/components/fields/Radio'; +import { LegacyCheckbox } from '../../components/devCheckboxRadio/LegacyCheckbox'; +import { LegacyRadio } from '../../components/devCheckboxRadio/LegacyRadio'; + +/** + * /dev/checkbox-radio — internal review surface for the Checkbox + Radio + * redesign that aligns them with the Toggle/Switch and Button system. + * + * Side-by-side PREVIOUS vs NEW across every state and variant, in light and + * dark. Hover / focus / press are live — interact with any control to see + * those states. Carries `noindex`/`nofollow`; reachable on preview + local + * but blocked on the canonical production host. + */ + +// --- Theme + gating -------------------------------------------------------- + +const useTheme = (initial: 'dark' | 'light') => { + const [theme, setTheme] = useState<'dark' | 'light'>(initial); + useEffect(() => { + if (typeof document === 'undefined') { + return; + } + const root = document.documentElement; + if (theme === 'light') { + root.classList.add('light'); + } else { + root.classList.remove('light'); + } + }, [theme]); + return [theme, setTheme] as const; +}; + +const useReviewAllowed = (): boolean => { + const [allowed, setAllowed] = useState(true); + useEffect(() => { + if (typeof window === 'undefined') { + return; + } + const { hostname } = window.location; + // Block the canonical production hosts only; allow localhost and the + // *.preview.app.daily.dev preview deployments so reviewers can open it. + setAllowed(hostname !== 'app.daily.dev' && hostname !== 'www.daily.dev'); + }, []); + return allowed; +}; + +// --- Interactive wrappers (own their state so states are live) ------------- + +const InteractiveCheckbox = ({ + variant, + checked: initial, + ...props +}: { + variant: 'previous' | 'new'; + checked?: boolean; + disabled?: boolean; + children?: ReactNode; + className?: string; + checkmarkClassName?: string; + 'aria-label'?: string; +}) => { + const id = useId(); + const [checked, setChecked] = useState(Boolean(initial)); + const Component = variant === 'previous' ? LegacyCheckbox : Checkbox; + return ( + setChecked(next)} + /> + ); +}; + +const RADIO_OPTIONS = [ + { label: 'Daily digest', value: 'digest' }, + { label: 'Weekly summary', value: 'weekly' }, + { label: 'Off', value: 'off' }, +]; + +const InteractiveRadio = ({ + variant, + initial = 'digest', + disabled, + reverse, + valid, + options = RADIO_OPTIONS, + container, +}: { + variant: 'previous' | 'new'; + initial?: string; + disabled?: boolean; + reverse?: boolean; + valid?: boolean; + options?: { label: string; value: string; afterElement?: ReactNode }[]; + container?: string; +}) => { + const name = useId(); + const [value, setValue] = useState(initial); + const Component = variant === 'previous' ? LegacyRadio : Radio; + return ( + + ); +}; + +// --- Layout primitives ----------------------------------------------------- + +const Section = ({ + title, + description, + children, +}: { + title: string; + description?: string; + children: ReactNode; +}) => ( +
+
+

{title}

+ {description ? ( +

+ {description} +

+ ) : null} +
+ {children} +
+); + +const tableGrid = { gridTemplateColumns: '240px 1fr 1fr' } as const; + +const TableHeader = () => ( +
+ + State / variant + + + Previous + + + New design + +
+); + +const TableRow = ({ + title, + caption, + previous, + next, + align = 'center', +}: { + title: string; + caption?: string; + previous: ReactNode; + next: ReactNode; + align?: 'center' | 'start'; +}) => ( +
+
+ {title} + {caption ? ( + {caption} + ) : null} +
+
+ {previous} +
+
{next}
+
+); + +const Table = ({ children }: { children: ReactNode }) => ( +
+ + {children} +
+); + +// --- Page ------------------------------------------------------------------ + +const CheckboxRadioDevPage = (): ReactElement => { + const [theme, setTheme] = useTheme('dark'); + const allowed = useReviewAllowed(); + + if (!allowed) { + return ( + <> + +
+

+ This review page is only available on preview and local builds. +

+
+ + ); + } + + return ( + <> + +
+ {/* Sticky controls bar */} +
+
+

+ Checkbox & Radio · PREVIOUS vs NEW +

+
+ Theme + +
+ + Hover, click & hold (press), and Tab (focus ring) are live on + every control. + +
+
+ +
+
+ + Design system · Review + +

+ Checkbox & Radio — before & after +

+

+ The checkbox and radio were realigned with the redesigned + Toggle/Switch and the Button system so fields, buttons, toggles, + checkboxes and radios read as one family. The new design uses a + single semantic brand fill when selected ( + accent-cabbage-default) with a solid white glyph, a{' '} + surface-hover halo, a surface-focus blue + keyboard ring, and a subtle press squeeze — all theme-aware with + no per-theme overrides. Toggle the theme above and interact with + each control to review hover, focus and press. +

+
+ + {/* ---------------- Checkbox ---------------- */} +
+ + + Checkbox label + + } + next={ + + Checkbox label + + } + /> + + Checkbox label + + } + next={ + + Checkbox label + + } + /> + + Checkbox label + + } + next={ + + Checkbox label + + } + /> + + Checkbox label + + } + next={ + + Checkbox label + + } + /> +
+
+ +
+ + + } + next={ + + } + /> + + + A longer checkbox label that wraps onto multiple lines to + verify alignment. + + + } + next={ +
+ + A longer checkbox label that wraps onto multiple lines to + verify alignment. + +
+ } + /> + + } + next={ + + } + /> +
+
+ + {/* ---------------- Radio ---------------- */} +
+ + + } + next={} + /> + } + next={} + /> + + } + next={ + + } + /> +
+
+ +
+ + + } + next={ + + } + /> + + } + next={ + + } + /> + + } + next={ + + } + /> +
+
+
+
+ + ); +}; + +CheckboxRadioDevPage.getLayout = (page: ReactNode): ReactNode => page; + +export default CheckboxRadioDevPage; From 06a35b058008066f78550de6c458e266655ceed8 Mon Sep 17 00:00:00 2001 From: Tsahi Matsliah Date: Tue, 2 Jun 2026 00:17:05 +0300 Subject: [PATCH 2/6] fix(shared): bolder checkbox check + restore radio hover-fatten MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Checkbox: use the filled (secondary) V glyph, scaled up, so the checkmark reads bold and solid instead of thin/outlined. - Radio: restore the legacy hover affordance where the ring thickens (border 2px → 4px) to text-primary on hover/focus, animated. Co-Authored-By: Claude Opus 4.8 --- packages/shared/src/components/fields/Checkbox.tsx | 3 ++- .../src/components/fields/RadioItem.module.css | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/shared/src/components/fields/Checkbox.tsx b/packages/shared/src/components/fields/Checkbox.tsx index 3329884e416..7818f8eafc1 100644 --- a/packages/shared/src/components/fields/Checkbox.tsx +++ b/packages/shared/src/components/fields/Checkbox.tsx @@ -86,7 +86,8 @@ export const Checkbox = forwardRef(function Checkbox( > diff --git a/packages/shared/src/components/fields/RadioItem.module.css b/packages/shared/src/components/fields/RadioItem.module.css index 63564f99c5d..55941991014 100644 --- a/packages/shared/src/components/fields/RadioItem.module.css +++ b/packages/shared/src/components/fields/RadioItem.module.css @@ -15,7 +15,8 @@ .innerRing { position: relative; transition: background-color 0.12s linear, border-color 0.12s linear, - box-shadow 0.1s linear, transform 0.15s cubic-bezier(0.16, 1, 0.3, 1); + border-width 0.12s linear, box-shadow 0.1s linear, + transform 0.15s cubic-bezier(0.16, 1, 0.3, 1); /* White center dot — scales in when selected. */ &:after { @@ -40,16 +41,21 @@ } } -/* Hover / keyboard focus reveal the halo and lift the resting border. */ +/* + * Hover / keyboard focus reveal the halo and thicken the ring to text-primary + * (the well-liked legacy "fattening" hover affordance). + */ .item:hover .checkmark, .item input:focus-visible ~ .checkmark { @apply bg-surface-hover; & .innerRing { - @apply border-text-primary; + @apply border-4 border-text-primary; } } +/* Checked stays brand-coloured on hover/focus; the thicker border is hidden + * behind the filled disc, so only the unchecked ring visibly fattens. */ .item.checked:hover .checkmark .innerRing, .item.checked input:focus-visible ~ .checkmark .innerRing { @apply border-accent-cabbage-default; From 02435d76a4236fba678e1281c1d96dca3bc15b72 Mon Sep 17 00:00:00 2001 From: Tsahi Matsliah Date: Tue, 2 Jun 2026 00:35:01 +0300 Subject: [PATCH 3/6] fix(shared): align checkbox/radio label typography with toggle; trim check size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Labels now match the redesigned Switch: font-medium, antialiased, typo-footnote, text-secondary at rest → text-primary when selected/hover (radio was font-bold/tertiary; checkbox was tertiary). - Reduce the checkbox check glyph from scale-125 to scale-110. Co-Authored-By: Claude Opus 4.8 --- packages/shared/src/components/fields/Checkbox.tsx | 4 ++-- packages/shared/src/components/fields/RadioItem.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/shared/src/components/fields/Checkbox.tsx b/packages/shared/src/components/fields/Checkbox.tsx index 7818f8eafc1..5b8fd2380df 100644 --- a/packages/shared/src/components/fields/Checkbox.tsx +++ b/packages/shared/src/components/fields/Checkbox.tsx @@ -51,7 +51,7 @@ export const Checkbox = forwardRef(function Checkbox( return (