From f3c1b52a0bcd769f38003368ab935f14d18c253f Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Tue, 29 Sep 2026 10:51:30 -0300 Subject: [PATCH 1/5] feat(chip): add semantic variants, a solid fill and a status dot The five status colours, the one filled variant, and ChipDot, a leading dot in currentColor so it follows the variant with nothing to wire. Co-Authored-By: Claude Opus 5 (1M context) --- frontend/web/components/base/Chip/Chip.scss | 25 ++++++++++++++++ frontend/web/components/base/Chip/Chip.tsx | 30 +++++++++++++++++-- frontend/web/components/base/Chip/ChipDot.tsx | 6 ++++ frontend/web/components/base/Chip/index.ts | 1 + 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 frontend/web/components/base/Chip/ChipDot.tsx diff --git a/frontend/web/components/base/Chip/Chip.scss b/frontend/web/components/base/Chip/Chip.scss index 854427ce3f98..3407d57ff58d 100644 --- a/frontend/web/components/base/Chip/Chip.scss +++ b/frontend/web/components/base/Chip/Chip.scss @@ -13,13 +13,38 @@ border-color: var(--color-border-action); } + // Status colours carry their meaning in the fill, so an outline only adds + // noise. Transparent rather than removed, so a status chip is the same + // height as a bordered one beside it. + &--success, + &--warning, + &--danger, + &--info, + &--muted, + &--solid { + border-color: transparent; + } + + // Status dot. currentColor, so it follows the variant with nothing to wire. + &__dot { + width: 6px; + height: 6px; + border-radius: var(--radius-full); + background: currentColor; + flex-shrink: 0; + } + // Sizes (default is the base above). &--sm { padding: 3px 8px; font-size: 0.75rem; } + // 24px is fixed in the tags frame, so it is stated rather than left to derive + // from the inherited line-height. The frame's 8px vertical padding is an + // artefact of a height override on the auto-layout and is not applied. &--xs { + height: 24px; padding: 1px 6px; font-size: 0.6875rem; } diff --git a/frontend/web/components/base/Chip/Chip.tsx b/frontend/web/components/base/Chip/Chip.tsx index 296219372dda..d36339af60ab 100644 --- a/frontend/web/components/base/Chip/Chip.tsx +++ b/frontend/web/components/base/Chip/Chip.tsx @@ -5,7 +5,15 @@ import { colorIconSecondary } from 'common/theme/tokens' import './Chip.scss' export type ChipSize = 'default' | 'sm' | 'xs' -export type ChipVariant = 'neutral' | 'accent' +export type ChipVariant = + | 'neutral' + | 'accent' + | 'success' + | 'warning' + | 'danger' + | 'info' + | 'muted' + | 'solid' export type ChipProps = { children: ReactNode @@ -30,7 +38,21 @@ export type ChipProps = { // bg + text come from token utilities; the variant border lives in Chip.scss. const VARIANT_UTILITIES: Record = { accent: 'bg-surface-action-subtle text-action', + + danger: 'bg-surface-danger text-danger', + + info: 'bg-surface-info text-info', + + muted: 'bg-surface-muted text-secondary', + neutral: 'bg-surface-subtle text-default', + // The one filled variant. `text-white` rather than a token because there is + // no inverse-text token yet; white on --color-surface-action is 5.93:1, so AA + // but not AAA. Note the app has a second, darker solid (`bg-primary900`, used + // by BetaFlag and PlanBasedAccess) that this deliberately does not cover. + solid: 'bg-surface-action text-white', + success: 'bg-surface-success text-success', + warning: 'bg-surface-warning text-warning', } // Token-based chip primitive. Uses `ds-chip` rather than the legacy `.chip` @@ -58,10 +80,12 @@ const Chip = ({