From c60bb0b4387a8f17593522fd3d3b89f33b92e382 Mon Sep 17 00:00:00 2001 From: Tucker McCoy Date: Wed, 2 Sep 2026 10:10:55 -0400 Subject: [PATCH] feat(badge): add an archived variant and a brand-orange token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Archived is a lifecycle state consumers were painting by hand — Guardian Studio carried a `bg-orange-400/20! text-orange-400!` override on Badge because no variant covered it. `Badge/Background/Archived` and `Badge/Text/Archived` alias the Orange ramp with the same 200/700/800 recipe every other badge variant uses, so the pill inverts correctly between themes. `Brand/Orange` is a new colorItem at #FB923C, giving status dots and archive banners a token to resolve against rather than a raw Tailwind value. Archived shares its orange with ControlStatusBadge's In Progress. The two describe different things and are not expected to share a view, so the docs tell consumers to lean on the icon and label rather than colour alone. The variant defaults to the `Archive` glyph, matching how success, warning and danger supply their own. Co-Authored-By: Claude Opus 5 (1M context) --- .../demo/src/content/components/badge.mdx | 36 ++++++++++------- packages/tokens/equality-tokens.json | 40 +++++++++++++++++++ packages/tokens/equality-tokens.pinwheel | 36 +++++++++++++++++ packages/ui/package.json | 2 +- .../ui/src/components/badge/badge.module.css | 5 +++ packages/ui/src/components/badge/badge.tsx | 2 + .../ui/src/theme/generated/color-vars.css | 5 +++ .../ui/src/theme/generated/dark-tokens.css | 2 + .../theme/generated/global-dark-tokens.css | 2 + .../theme/generated/global-light-tokens.css | 3 ++ .../ui/src/theme/generated/light-tokens.css | 3 ++ .../src/theme/generated/tailwind-tokens.css | 3 ++ 12 files changed, 123 insertions(+), 16 deletions(-) diff --git a/packages/demo/src/content/components/badge.mdx b/packages/demo/src/content/components/badge.mdx index b8b01bb5..df4b078d 100644 --- a/packages/demo/src/content/components/badge.mdx +++ b/packages/demo/src/content/components/badge.mdx @@ -12,7 +12,7 @@ import { ## Overview -The Badge component comes with four color variants to visually communicate different statuses or contexts: +The Badge component comes with several color variants to visually communicate different statuses or contexts: - **Primary:** The default style, suitable for general labeling. - **Secondary:** Use after primary but information is of secondary (or equal) importance @@ -20,6 +20,9 @@ The Badge component comes with four color variants to visually communicate diffe - **Warning:** Indicates something that is worthy of more attention. - **Danger:** Indicates an error or danger state that requires serious attention. - **Success:** Represents positive outcomes or completed statuses. +- **Archived:** Marks something withdrawn from active use but still on record. + +`archived` draws on the same orange as [ControlStatusBadge](control-status-badge)'s In Progress. The two describe different things and are not expected to share a view, so let an archived badge carry its icon and label rather than separating them by colour alone. For control compliance and resource types see [ControlStatusBadge](control-status-badge) and [ResourceBadge](resource-badge) respectively. @@ -48,6 +51,7 @@ import { Badge } from "@eqtylab/equality"; Warning Danger Success + Archived
@@ -63,6 +67,7 @@ import { Badge } from "@eqtylab/equality"; Warning Danger Success + Archived
@@ -72,6 +77,7 @@ import { Badge } from "@eqtylab/equality"; +
@@ -202,17 +208,17 @@ You can enhance your badge by displaying an icon. The `icon` prop accepts either ## Props -| Prop | Type | Default | Description | -| ---------------- | --------------------------------------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------- | -| `variant` | `"neutral"` \| `"primary"` \| `"secondary"` \| `"warning"` \| `"danger"` \| `"success"` | `"primary"` | The visual style variant of the badge. | -| `size` | `"sm"` \| `"md"` | `"md"` | The size of the badge. `"md"` renders at 20px tall, `"sm"` at 16px tall. | -| `display` | `"both"` \| `"text-only"` \| `"icon-only"` | `"both"` | Controls what elements are displayed. `"both"` shows icon and text, `"text-only"` shows only text, `"icon-only"` shows only icon. | -| `icon` | `string` \| `ReactElement` | - | Icon to display. Can be a Lucide icon name or a custom React element. | -| `pill` | `boolean` | `true` | When true (default), badge is pill-shaped. Set to `false` for a square badge with subtle border radius. | -| `monospace` | `boolean` | `false` | When true, renders badge text in a monospace font. | -| `closeable` | `boolean` | `false` | When true and `handleClosable` is provided, displays a close button on the badge. | -| `handleClosable` | `() => void` | - | Callback function called when the close button is clicked. Required to render the close button when `closeable` is true. | -| `closeLabel` | `string` | `"Remove"` | Accessible label (`aria-label`) for the close button. Used by screen readers to describe the action. | -| `truncate` | `boolean` | `false` | When true, truncates long text with an ellipsis and shows full text on hover. | -| `truncateLength` | `number` | `50` | Maximum character length before truncation occurs. | -| `className` | `string` | - | Additional CSS classes to apply to the badge. | +| Prop | Type | Default | Description | +| ---------------- | ------------------------------------------------------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------- | +| `variant` | `"neutral"` \| `"primary"` \| `"secondary"` \| `"warning"` \| `"danger"` \| `"success"` \| `"archived"` | `"primary"` | The visual style variant of the badge. | +| `size` | `"sm"` \| `"md"` | `"md"` | The size of the badge. `"md"` renders at 20px tall, `"sm"` at 16px tall. | +| `display` | `"both"` \| `"text-only"` \| `"icon-only"` | `"both"` | Controls what elements are displayed. `"both"` shows icon and text, `"text-only"` shows only text, `"icon-only"` shows only icon. | +| `icon` | `string` \| `ReactElement` | - | Icon to display. Can be a Lucide icon name or a custom React element. | +| `pill` | `boolean` | `true` | When true (default), badge is pill-shaped. Set to `false` for a square badge with subtle border radius. | +| `monospace` | `boolean` | `false` | When true, renders badge text in a monospace font. | +| `closeable` | `boolean` | `false` | When true and `handleClosable` is provided, displays a close button on the badge. | +| `handleClosable` | `() => void` | - | Callback function called when the close button is clicked. Required to render the close button when `closeable` is true. | +| `closeLabel` | `string` | `"Remove"` | Accessible label (`aria-label`) for the close button. Used by screen readers to describe the action. | +| `truncate` | `boolean` | `false` | When true, truncates long text with an ellipsis and shows full text on hover. | +| `truncateLength` | `number` | `50` | Maximum character length before truncation occurs. | +| `className` | `string` | - | Additional CSS classes to apply to the badge. | diff --git a/packages/tokens/equality-tokens.json b/packages/tokens/equality-tokens.json index c53a2d73..4b4fa911 100644 --- a/packages/tokens/equality-tokens.json +++ b/packages/tokens/equality-tokens.json @@ -67,6 +67,14 @@ "hex": "#3F2A86" } }, + "archived": { + "$type": "color", + "$value": { + "colorSpace": "display-p3", + "components": [0.4118, 0.2185, 0.1135], + "hex": "#69381D" + } + }, "comment": { "$type": "color", "$value": { @@ -197,6 +205,14 @@ "hex": "#CCC6FF" } }, + "archived": { + "$type": "color", + "$value": { + "colorSpace": "display-p3", + "components": [0.9272, 0.788, 0.7058], + "hex": "#ECC9B4" + } + }, "comment": { "$type": "color", "$value": { @@ -1061,6 +1077,14 @@ "hex": "#CCC6FF" } }, + "archived": { + "$type": "color", + "$value": { + "colorSpace": "display-p3", + "components": [0.9272, 0.788, 0.7058], + "hex": "#ECC9B4" + } + }, "comment": { "$type": "color", "$value": { @@ -1191,6 +1215,14 @@ "hex": "#291D57" } }, + "archived": { + "$type": "color", + "$value": { + "colorSpace": "display-p3", + "components": [0.2598, 0.1437, 0.0748], + "hex": "#422513" + } + }, "comment": { "$type": "color", "$value": { @@ -1460,6 +1492,14 @@ "hex": "#70A369" } }, + "orange": { + "$type": "color", + "$value": { + "colorSpace": "display-p3", + "components": [0.9843, 0.5725, 0.2353], + "hex": "#FB923C" + } + }, "primary": { "$type": "color", "$value": { diff --git a/packages/tokens/equality-tokens.pinwheel b/packages/tokens/equality-tokens.pinwheel index 1eb20709..71b92499 100644 --- a/packages/tokens/equality-tokens.pinwheel +++ b/packages/tokens/equality-tokens.pinwheel @@ -1496,6 +1496,17 @@ 1 86B9D7D8-F74A-4CAE-B006-65451BBEDAB9 + + Archived + 3 + 3 + lightanddark + E70AEB3A-46D2-4910-AA0C-8DE1F122368D + 7 + E70AEB3A-46D2-4910-AA0C-8DE1F122368D + 1 + 86B9D7D8-F74A-4CAE-B006-65451BBEDAB9 + Not Started 3 @@ -1677,6 +1688,17 @@ 6 86B9D7D8-F74A-4CAE-B006-65451BBEDAB9 + + Archived + 3 + 3 + lightanddark + E70AEB3A-46D2-4910-AA0C-8DE1F122368D + 1 + E70AEB3A-46D2-4910-AA0C-8DE1F122368D + 6 + 86B9D7D8-F74A-4CAE-B006-65451BBEDAB9 + Not Started 3 @@ -2741,6 +2763,20 @@ 3 86B9D7D8-F74A-4CAE-B006-65451BBEDAB9 + + 4C6C13BE-9A84-4771-9D54-32BE6DF8FB1A + Orange + DisplayP3 + 7 + + + + 0.98431 0.57255 0.23529 1 + + + + 86B9D7D8-F74A-4CAE-B006-65451BBEDAB9 + D7B954B6-4112-44FA-A9F9-570423BEA0FB diff --git a/packages/ui/package.json b/packages/ui/package.json index 2cab3f65..2d933c08 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -2,7 +2,7 @@ "name": "@eqtylab/equality", "description": "EQTYLab's component and token-based design system", "homepage": "https://equality.eqtylab.io/", - "version": "3.2.6", + "version": "3.3.0", "license": "Apache-2.0", "keywords": [ "component library", diff --git a/packages/ui/src/components/badge/badge.module.css b/packages/ui/src/components/badge/badge.module.css index 4bab1a53..6c259f3a 100644 --- a/packages/ui/src/components/badge/badge.module.css +++ b/packages/ui/src/components/badge/badge.module.css @@ -54,6 +54,11 @@ --badge-fg-color: var(--color-badge-text-success); } +.badge--archived { + --badge-bg-color: var(--color-badge-background-archived); + --badge-fg-color: var(--color-badge-text-archived); +} + /* Closable Variant */ .badge .closable-btn { diff --git a/packages/ui/src/components/badge/badge.tsx b/packages/ui/src/components/badge/badge.tsx index d552ae5b..e7cd28a8 100644 --- a/packages/ui/src/components/badge/badge.tsx +++ b/packages/ui/src/components/badge/badge.tsx @@ -24,6 +24,7 @@ const badgeVariants = cva(styles['badge'], { neutral: styles['badge--neutral'], warning: styles['badge--warning'], success: styles['badge--success'], + archived: styles['badge--archived'], }, size: { sm: styles['badge--sm'], @@ -56,6 +57,7 @@ const defaultVariantIcons: Record = { success: 'Check', warning: 'OctagonAlert', danger: 'TriangleAlert', + archived: 'Archive', }; function Badge({ diff --git a/packages/ui/src/theme/generated/color-vars.css b/packages/ui/src/theme/generated/color-vars.css index 8d38a97e..e03df3c7 100644 --- a/packages/ui/src/theme/generated/color-vars.css +++ b/packages/ui/src/theme/generated/color-vars.css @@ -17,6 +17,7 @@ --color-background-top: color(display-p3 0.9294 0.9355 0.9426); --color-background: color(display-p3 1 1 1); --color-badge-background-accepted: color(display-p3 0.795 0.7755 0.9866); + --color-badge-background-archived: color(display-p3 0.9272 0.788 0.7058); --color-badge-background-comment: color(display-p3 0.795 0.7755 0.9866); --color-badge-background-compliant: color(display-p3 0.7403 0.8486 0.7417); --color-badge-background-danger: color(display-p3 0.9358 0.751 0.7228); @@ -33,6 +34,7 @@ --color-badge-background-success: color(display-p3 0.7403 0.8486 0.7417); --color-badge-background-warning: color(display-p3 0.9327 0.8528 0.7204); --color-badge-text-accepted: color(display-p3 0.1608 0.1145 0.3417); + --color-badge-text-archived: color(display-p3 0.2598 0.1437 0.0748); --color-badge-text-comment: color(display-p3 0.1608 0.1145 0.3417); --color-badge-text-compliant: color(display-p3 0.1097 0.1998 0.08667); --color-badge-text-danger: color(display-p3 0.2625 0.1106 0.09605); @@ -66,6 +68,7 @@ --color-border-top: color(display-p3 0.8011 0.807 0.814); --color-border: color(display-p3 0.7432 0.7432 0.7432); --color-brand-green: color(display-p3 0.4374 0.6383 0.4134); + --color-brand-orange: color(display-p3 0.9843 0.5725 0.2353); --color-brand-primary: color(display-p3 0.7319 0.6108 0.8873); --color-brand-red: color(display-p3 0.8114 0.4167 0.3761); --color-brand-secondary: color(display-p3 0.3895 0.4853 0.8187); @@ -270,6 +273,7 @@ --dark-color-background-top: color(display-p3 0.1399 0.14 0.1485); --dark-color-background: color(display-p3 0.06018 0.06019 0.06787); --dark-color-badge-background-accepted: color(display-p3 0.2473 0.1645 0.5241); + --dark-color-badge-background-archived: color(display-p3 0.4118 0.2185 0.1135); --dark-color-badge-background-comment: color(display-p3 0.2473 0.1645 0.5241); --dark-color-badge-background-compliant: color(display-p3 0.1689 0.3045 0.136); --dark-color-badge-background-danger: color(display-p3 0.4113 0.1505 0.1319); @@ -286,6 +290,7 @@ --dark-color-badge-background-success: color(display-p3 0.1689 0.3045 0.136); --dark-color-badge-background-warning: color(display-p3 0.4487 0.322 0.1436); --dark-color-badge-text-accepted: color(display-p3 0.795 0.7755 0.9866); + --dark-color-badge-text-archived: color(display-p3 0.9272 0.788 0.7058); --dark-color-badge-text-comment: color(display-p3 0.795 0.7755 0.9866); --dark-color-badge-text-compliant: color(display-p3 0.7403 0.8486 0.7417); --dark-color-badge-text-danger: color(display-p3 0.9358 0.751 0.7228); diff --git a/packages/ui/src/theme/generated/dark-tokens.css b/packages/ui/src/theme/generated/dark-tokens.css index 763778b0..2eca8868 100644 --- a/packages/ui/src/theme/generated/dark-tokens.css +++ b/packages/ui/src/theme/generated/dark-tokens.css @@ -8,6 +8,7 @@ --color-background-top: color(display-p3 0.1399 0.14 0.1485); --color-background: color(display-p3 0.06018 0.06019 0.06787); --color-badge-background-accepted: color(display-p3 0.2473 0.1645 0.5241); + --color-badge-background-archived: color(display-p3 0.4118 0.2185 0.1135); --color-badge-background-comment: color(display-p3 0.2473 0.1645 0.5241); --color-badge-background-compliant: color(display-p3 0.1689 0.3045 0.136); --color-badge-background-danger: color(display-p3 0.4113 0.1505 0.1319); @@ -24,6 +25,7 @@ --color-badge-background-success: color(display-p3 0.1689 0.3045 0.136); --color-badge-background-warning: color(display-p3 0.4487 0.322 0.1436); --color-badge-text-accepted: color(display-p3 0.795 0.7755 0.9866); + --color-badge-text-archived: color(display-p3 0.9272 0.788 0.7058); --color-badge-text-comment: color(display-p3 0.795 0.7755 0.9866); --color-badge-text-compliant: color(display-p3 0.7403 0.8486 0.7417); --color-badge-text-danger: color(display-p3 0.9358 0.751 0.7228); diff --git a/packages/ui/src/theme/generated/global-dark-tokens.css b/packages/ui/src/theme/generated/global-dark-tokens.css index 0b46c79d..f95a6211 100644 --- a/packages/ui/src/theme/generated/global-dark-tokens.css +++ b/packages/ui/src/theme/generated/global-dark-tokens.css @@ -8,6 +8,7 @@ html[data-equality-theme='dark'] { --color-background-top: color(display-p3 0.1399 0.14 0.1485); --color-background: color(display-p3 0.06018 0.06019 0.06787); --color-badge-background-accepted: color(display-p3 0.2473 0.1645 0.5241); + --color-badge-background-archived: color(display-p3 0.4118 0.2185 0.1135); --color-badge-background-comment: color(display-p3 0.2473 0.1645 0.5241); --color-badge-background-compliant: color(display-p3 0.1689 0.3045 0.136); --color-badge-background-danger: color(display-p3 0.4113 0.1505 0.1319); @@ -24,6 +25,7 @@ html[data-equality-theme='dark'] { --color-badge-background-success: color(display-p3 0.1689 0.3045 0.136); --color-badge-background-warning: color(display-p3 0.4487 0.322 0.1436); --color-badge-text-accepted: color(display-p3 0.795 0.7755 0.9866); + --color-badge-text-archived: color(display-p3 0.9272 0.788 0.7058); --color-badge-text-comment: color(display-p3 0.795 0.7755 0.9866); --color-badge-text-compliant: color(display-p3 0.7403 0.8486 0.7417); --color-badge-text-danger: color(display-p3 0.9358 0.751 0.7228); diff --git a/packages/ui/src/theme/generated/global-light-tokens.css b/packages/ui/src/theme/generated/global-light-tokens.css index 09930acb..2dffbd4c 100644 --- a/packages/ui/src/theme/generated/global-light-tokens.css +++ b/packages/ui/src/theme/generated/global-light-tokens.css @@ -21,6 +21,7 @@ html { --color-background-top: color(display-p3 0.9294 0.9355 0.9426); --color-background: color(display-p3 1 1 1); --color-badge-background-accepted: color(display-p3 0.795 0.7755 0.9866); + --color-badge-background-archived: color(display-p3 0.9272 0.788 0.7058); --color-badge-background-comment: color(display-p3 0.795 0.7755 0.9866); --color-badge-background-compliant: color(display-p3 0.7403 0.8486 0.7417); --color-badge-background-danger: color(display-p3 0.9358 0.751 0.7228); @@ -37,6 +38,7 @@ html { --color-badge-background-success: color(display-p3 0.7403 0.8486 0.7417); --color-badge-background-warning: color(display-p3 0.9327 0.8528 0.7204); --color-badge-text-accepted: color(display-p3 0.1608 0.1145 0.3417); + --color-badge-text-archived: color(display-p3 0.2598 0.1437 0.0748); --color-badge-text-comment: color(display-p3 0.1608 0.1145 0.3417); --color-badge-text-compliant: color(display-p3 0.1097 0.1998 0.08667); --color-badge-text-danger: color(display-p3 0.2625 0.1106 0.09605); @@ -70,6 +72,7 @@ html { --color-border-top: color(display-p3 0.8011 0.807 0.814); --color-border: color(display-p3 0.7432 0.7432 0.7432); --color-brand-green: color(display-p3 0.4374 0.6383 0.4134); + --color-brand-orange: color(display-p3 0.9843 0.5725 0.2353); --color-brand-primary: color(display-p3 0.7319 0.6108 0.8873); --color-brand-red: color(display-p3 0.8114 0.4167 0.3761); --color-brand-secondary: color(display-p3 0.3895 0.4853 0.8187); diff --git a/packages/ui/src/theme/generated/light-tokens.css b/packages/ui/src/theme/generated/light-tokens.css index 0ce4ba1d..0d5f9396 100644 --- a/packages/ui/src/theme/generated/light-tokens.css +++ b/packages/ui/src/theme/generated/light-tokens.css @@ -21,6 +21,7 @@ --color-background-top: color(display-p3 0.9294 0.9355 0.9426); --color-background: color(display-p3 1 1 1); --color-badge-background-accepted: color(display-p3 0.795 0.7755 0.9866); + --color-badge-background-archived: color(display-p3 0.9272 0.788 0.7058); --color-badge-background-comment: color(display-p3 0.795 0.7755 0.9866); --color-badge-background-compliant: color(display-p3 0.7403 0.8486 0.7417); --color-badge-background-danger: color(display-p3 0.9358 0.751 0.7228); @@ -37,6 +38,7 @@ --color-badge-background-success: color(display-p3 0.7403 0.8486 0.7417); --color-badge-background-warning: color(display-p3 0.9327 0.8528 0.7204); --color-badge-text-accepted: color(display-p3 0.1608 0.1145 0.3417); + --color-badge-text-archived: color(display-p3 0.2598 0.1437 0.0748); --color-badge-text-comment: color(display-p3 0.1608 0.1145 0.3417); --color-badge-text-compliant: color(display-p3 0.1097 0.1998 0.08667); --color-badge-text-danger: color(display-p3 0.2625 0.1106 0.09605); @@ -70,6 +72,7 @@ --color-border-top: color(display-p3 0.8011 0.807 0.814); --color-border: color(display-p3 0.7432 0.7432 0.7432); --color-brand-green: color(display-p3 0.4374 0.6383 0.4134); + --color-brand-orange: color(display-p3 0.9843 0.5725 0.2353); --color-brand-primary: color(display-p3 0.7319 0.6108 0.8873); --color-brand-red: color(display-p3 0.8114 0.4167 0.3761); --color-brand-secondary: color(display-p3 0.3895 0.4853 0.8187); diff --git a/packages/ui/src/theme/generated/tailwind-tokens.css b/packages/ui/src/theme/generated/tailwind-tokens.css index 960ba0b0..47760bab 100644 --- a/packages/ui/src/theme/generated/tailwind-tokens.css +++ b/packages/ui/src/theme/generated/tailwind-tokens.css @@ -21,6 +21,7 @@ --color-background-top: color(display-p3 0.9294 0.9355 0.9426); --color-background: color(display-p3 1 1 1); --color-badge-background-accepted: color(display-p3 0.795 0.7755 0.9866); + --color-badge-background-archived: color(display-p3 0.9272 0.788 0.7058); --color-badge-background-comment: color(display-p3 0.795 0.7755 0.9866); --color-badge-background-compliant: color(display-p3 0.7403 0.8486 0.7417); --color-badge-background-danger: color(display-p3 0.9358 0.751 0.7228); @@ -37,6 +38,7 @@ --color-badge-background-success: color(display-p3 0.7403 0.8486 0.7417); --color-badge-background-warning: color(display-p3 0.9327 0.8528 0.7204); --color-badge-text-accepted: color(display-p3 0.1608 0.1145 0.3417); + --color-badge-text-archived: color(display-p3 0.2598 0.1437 0.0748); --color-badge-text-comment: color(display-p3 0.1608 0.1145 0.3417); --color-badge-text-compliant: color(display-p3 0.1097 0.1998 0.08667); --color-badge-text-danger: color(display-p3 0.2625 0.1106 0.09605); @@ -70,6 +72,7 @@ --color-border-top: color(display-p3 0.8011 0.807 0.814); --color-border: color(display-p3 0.7432 0.7432 0.7432); --color-brand-green: color(display-p3 0.4374 0.6383 0.4134); + --color-brand-orange: color(display-p3 0.9843 0.5725 0.2353); --color-brand-primary: color(display-p3 0.7319 0.6108 0.8873); --color-brand-red: color(display-p3 0.8114 0.4167 0.3761); --color-brand-secondary: color(display-p3 0.3895 0.4853 0.8187);