@atelier-ui/react 0.2.13 → 0.2.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/package.json +1 -1
  3. package/src/lib/accordion/atl-accordion.css +21 -5
  4. package/src/lib/accordion/atl-accordion.d.ts.map +1 -1
  5. package/src/lib/accordion/atl-accordion.js +2 -3
  6. package/src/lib/accordion/atl-accordion.js.map +1 -1
  7. package/src/lib/alert/atl-alert.css +11 -1
  8. package/src/lib/alert/atl-alert.d.ts.map +1 -1
  9. package/src/lib/alert/atl-alert.js +2 -1
  10. package/src/lib/alert/atl-alert.js.map +1 -1
  11. package/src/lib/avatar/atl-avatar.css +19 -3
  12. package/src/lib/avatar/atl-avatar.d.ts.map +1 -1
  13. package/src/lib/avatar/atl-avatar.js +2 -1
  14. package/src/lib/avatar/atl-avatar.js.map +1 -1
  15. package/src/lib/badge/atl-badge.css +16 -6
  16. package/src/lib/breadcrumbs/atl-breadcrumbs.css +16 -0
  17. package/src/lib/button/atl-button.css +30 -8
  18. package/src/lib/card/atl-card.css +24 -4
  19. package/src/lib/chat/atl-chat.css +37 -11
  20. package/src/lib/chat/atl-chat.d.ts.map +1 -1
  21. package/src/lib/chat/atl-chat.js +2 -1
  22. package/src/lib/chat/atl-chat.js.map +1 -1
  23. package/src/lib/checkbox/atl-checkbox.css +12 -2
  24. package/src/lib/checkbox/atl-checkbox.d.ts +1 -5
  25. package/src/lib/checkbox/atl-checkbox.d.ts.map +1 -1
  26. package/src/lib/checkbox/atl-checkbox.js +2 -3
  27. package/src/lib/checkbox/atl-checkbox.js.map +1 -1
  28. package/src/lib/code-block/atl-code-block.css +25 -6
  29. package/src/lib/code-block/atl-code-block.d.ts.map +1 -1
  30. package/src/lib/code-block/atl-code-block.js +2 -1
  31. package/src/lib/code-block/atl-code-block.js.map +1 -1
  32. package/src/lib/combobox/atl-combobox.css +56 -5
  33. package/src/lib/combobox/atl-combobox.d.ts.map +1 -1
  34. package/src/lib/combobox/atl-combobox.js +4 -2
  35. package/src/lib/combobox/atl-combobox.js.map +1 -1
  36. package/src/lib/dialog/atl-dialog.css +24 -4
  37. package/src/lib/dialog/atl-dialog.d.ts.map +1 -1
  38. package/src/lib/dialog/atl-dialog.js +2 -1
  39. package/src/lib/dialog/atl-dialog.js.map +1 -1
  40. package/src/lib/drawer/atl-drawer.css +24 -4
  41. package/src/lib/drawer/atl-drawer.d.ts.map +1 -1
  42. package/src/lib/drawer/atl-drawer.js +2 -1
  43. package/src/lib/drawer/atl-drawer.js.map +1 -1
  44. package/src/lib/icon/atl-icon.css +18 -0
  45. package/src/lib/icon/atl-icon.d.ts +2 -1
  46. package/src/lib/icon/atl-icon.d.ts.map +1 -1
  47. package/src/lib/icon/atl-icon.js +6 -25
  48. package/src/lib/icon/atl-icon.js.map +1 -1
  49. package/src/lib/icons.d.ts +39 -0
  50. package/src/lib/icons.d.ts.map +1 -0
  51. package/src/lib/icons.js +49 -0
  52. package/src/lib/icons.js.map +1 -0
  53. package/src/lib/input/atl-input.css +28 -9
  54. package/src/lib/input/atl-input.d.ts.map +1 -1
  55. package/src/lib/input/atl-input.js +2 -1
  56. package/src/lib/input/atl-input.js.map +1 -1
  57. package/src/lib/menu/atl-menu.css +28 -3
  58. package/src/lib/pagination/atl-pagination.css +11 -1
  59. package/src/lib/progress/atl-progress.css +10 -0
  60. package/src/lib/radio/atl-radio.css +11 -1
  61. package/src/lib/radio/atl-radio.d.ts.map +1 -1
  62. package/src/lib/radio/atl-radio.js +5 -3
  63. package/src/lib/radio/atl-radio.js.map +1 -1
  64. package/src/lib/radio-group/atl-radio-group.css +10 -0
  65. package/src/lib/select/atl-select.css +21 -3
  66. package/src/lib/select/atl-select.d.ts +1 -5
  67. package/src/lib/select/atl-select.d.ts.map +1 -1
  68. package/src/lib/select/atl-select.js +1 -3
  69. package/src/lib/select/atl-select.js.map +1 -1
  70. package/src/lib/skeleton/atl-skeleton.css +10 -0
  71. package/src/lib/spec.d.ts +20 -6
  72. package/src/lib/spec.d.ts.map +1 -1
  73. package/src/lib/spec.js +1 -1
  74. package/src/lib/spec.js.map +1 -1
  75. package/src/lib/stepper/atl-stepper.css +11 -1
  76. package/src/lib/stepper/atl-stepper.d.ts.map +1 -1
  77. package/src/lib/stepper/atl-stepper.js +2 -1
  78. package/src/lib/stepper/atl-stepper.js.map +1 -1
  79. package/src/lib/table/atl-table.css +42 -3
  80. package/src/lib/table/atl-table.d.ts.map +1 -1
  81. package/src/lib/table/atl-table.js +2 -1
  82. package/src/lib/table/atl-table.js.map +1 -1
  83. package/src/lib/tabs/atl-tabs.css +27 -5
  84. package/src/lib/textarea/atl-textarea.css +22 -7
  85. package/src/lib/textarea/atl-textarea.d.ts.map +1 -1
  86. package/src/lib/textarea/atl-textarea.js +2 -1
  87. package/src/lib/textarea/atl-textarea.js.map +1 -1
  88. package/src/lib/toast/atl-toast.css +16 -0
  89. package/src/lib/toast/atl-toast.d.ts.map +1 -1
  90. package/src/lib/toast/atl-toast.js +2 -1
  91. package/src/lib/toast/atl-toast.js.map +1 -1
  92. package/src/lib/toggle/atl-toggle.css +11 -1
  93. package/src/lib/toggle/atl-toggle.d.ts +1 -5
  94. package/src/lib/toggle/atl-toggle.d.ts.map +1 -1
  95. package/src/lib/toggle/atl-toggle.js +2 -3
  96. package/src/lib/toggle/atl-toggle.js.map +1 -1
  97. package/src/lib/tooltip/atl-tooltip.css +16 -0
  98. package/styles/tokens.css +24 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,32 @@
1
+ ## 0.2.15 (2026-08-26)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **tokens:** bind the literals that duplicate a token ([024faef](https://github.com/DominikPieper/atelier-ui/commit/024faef))
6
+ - **icons:** one concept, one drawing ([67784ec](https://github.com/DominikPieper/atelier-ui/commit/67784ec))
7
+ - **gates:** ship the geometry contract with every component ([6b706ce](https://github.com/DominikPieper/atelier-ui/commit/6b706ce))
8
+
9
+ ### 🩹 Fixes
10
+
11
+ - **geometry:** a stated height cannot be content-driven ([44dc31e](https://github.com/DominikPieper/atelier-ui/commit/44dc31e))
12
+ - **spec:** readonly lives only where it is enforced ([a1f6159](https://github.com/DominikPieper/atelier-ui/commit/a1f6159))
13
+
14
+ ### ❤️ Thank You
15
+
16
+ - Claude Opus 5
17
+ - Dominik Pieper @DominikPieper
18
+
19
+ ## 0.2.14 (2026-08-26)
20
+
21
+ ### 🩹 Fixes
22
+
23
+ - **tokens:** the control height is the primitive, padding is derived (ADR-0041) ([df973f7](https://github.com/DominikPieper/atelier-ui/commit/df973f7))
24
+
25
+ ### ❤️ Thank You
26
+
27
+ - Claude Opus 5
28
+ - Dominik Pieper @DominikPieper
29
+
1
30
  ## 0.2.13 (2026-08-26)
2
31
 
3
32
  ### 🩹 Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atelier-ui/react",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
4
4
  "description": "Atelier component library for React — LLM-optimised, accessible, design-token-driven",
5
5
  "keywords": [
6
6
  "react",
@@ -1,3 +1,19 @@
1
+ /* Geometry contract: every size this component states is a border-box size.
2
+ * Declared with the component rather than as a global reset, so it ships in the
3
+ * same file as the sizes it governs and no consuming app has to supply one.
4
+ * Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
5
+ * See ADR-0043. */
6
+ :is(
7
+ .atl-accordion-group,
8
+ .atl-accordion-item
9
+ ),
10
+ :is(
11
+ .atl-accordion-group,
12
+ .atl-accordion-item
13
+ ) * {
14
+ box-sizing: border-box;
15
+ }
16
+
1
17
  /* ── AccordionGroup ──────────────────────────────────────────────────────── */
2
18
  .atl-accordion-group {
3
19
  display: block;
@@ -7,22 +23,22 @@
7
23
 
8
24
  /* ── Default variant — shared borders between items ──────────────────────── */
9
25
  .atl-accordion-group.variant-default {
10
- border-top: 1px solid var(--ui-color-border);
26
+ border-top: var(--ui-border-width) solid var(--ui-color-border);
11
27
  }
12
28
 
13
29
  .atl-accordion-group.variant-default .atl-accordion-item {
14
- border-bottom: 1px solid var(--ui-color-border);
30
+ border-bottom: var(--ui-border-width) solid var(--ui-color-border);
15
31
  }
16
32
 
17
33
  /* ── Bordered variant — outer border + radius ────────────────────────────── */
18
34
  .atl-accordion-group.variant-bordered {
19
- border: 1px solid var(--ui-color-border);
35
+ border: var(--ui-border-width) solid var(--ui-color-border);
20
36
  border-radius: var(--ui-radius-lg);
21
37
  overflow: hidden;
22
38
  }
23
39
 
24
40
  .atl-accordion-group.variant-bordered .atl-accordion-item:not(:last-child) {
25
- border-bottom: 1px solid var(--ui-color-border);
41
+ border-bottom: var(--ui-border-width) solid var(--ui-color-border);
26
42
  }
27
43
 
28
44
  /* ── Separated variant — card-like items with gap ────────────────────────── */
@@ -33,7 +49,7 @@
33
49
  }
34
50
 
35
51
  .atl-accordion-group.variant-separated .atl-accordion-item {
36
- border: 1px solid var(--ui-color-border);
52
+ border: var(--ui-border-width) solid var(--ui-color-border);
37
53
  border-radius: var(--ui-radius-lg);
38
54
  overflow: hidden;
39
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"atl-accordion.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/accordion/atl-accordion.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,SAAS,EACT,cAAc,EAEf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AACjB,OAAO,qBAAqB,CAAC;AAoB7B;;GAEG;AACH,MAAM,WAAW,sBACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EACpC,qBAAqB;IACvB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;IAC/C;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,KAAa,EACb,OAAmB,EACnB,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,sBAAsB,+BA+DxB;AAED;;GAEG;AACH,MAAM,WAAW,qBACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EACpC,oBAAoB;IACtB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EAAE,gBAAgB,EAC1B,gBAAgB,EAChB,QAAgB,EAChB,YAAgB,EAChB,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,qBAAqB,+BAuGvB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,eAAe,CAAC,GAAG;IACnC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,+BASA"}
1
+ {"version":3,"file":"atl-accordion.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/accordion/atl-accordion.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,SAAS,EACT,cAAc,EAEf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AACjB,OAAO,qBAAqB,CAAC;AAqB7B;;GAEG;AACH,MAAM,WAAW,sBACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EACpC,qBAAqB;IACvB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;IAC/C;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,KAAa,EACb,OAAmB,EACnB,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,sBAAsB,+BA+DxB;AAED;;GAEG;AACH,MAAM,WAAW,qBACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EACpC,oBAAoB;IACtB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EAAE,gBAAgB,EAC1B,gBAAgB,EAChB,QAAgB,EAChB,YAAgB,EAChB,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,qBAAqB,+BAsFvB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,eAAe,CAAC,GAAG;IACnC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,+BASA"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { createContext, useContext, useState, useRef, useId, useLayoutEffect, useCallback, } from 'react';
3
3
  import './atl-accordion.css';
4
+ import { AtlIcon } from '../icon/atl-icon';
4
5
  const AccordionGroupContext = createContext({
5
6
  multi: false,
6
7
  openItems: new Set(),
@@ -111,9 +112,7 @@ export function AtlAccordionItem({ expanded: externalExpanded, onExpandedChange,
111
112
  const Heading = `h${headingLevel}`;
112
113
  return (_jsxs("div", { className: classes, ...rest, children: [_jsx(Heading, { className: "accordion-heading", children: _jsxs("button", { ref: triggerRef, type: "button", id: triggerId, className: ['accordion-trigger', disabled && 'is-disabled']
113
114
  .filter(Boolean)
114
- .join(' '), "aria-expanded": isExpanded, "aria-controls": panelId, "aria-disabled": disabled || undefined, disabled: disabled, onClick: toggle, onKeyDown: (e) => ctx.handleKeydown(e, id), children: [headerNode, _jsx("svg", { className: ['chevron', isExpanded && 'is-expanded']
115
- .filter(Boolean)
116
- .join(' '), width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M4 6L8 10L12 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })] }) }), _jsx("div", { className: ['accordion-panel-wrapper', isExpanded && 'is-expanded']
115
+ .join(' '), "aria-expanded": isExpanded, "aria-controls": panelId, "aria-disabled": disabled || undefined, disabled: disabled, onClick: toggle, onKeyDown: (e) => ctx.handleKeydown(e, id), children: [headerNode, _jsx(AtlIcon, { name: "chevron-down", size: "sm", className: ['chevron', isExpanded && 'is-expanded'].filter(Boolean).join(' ') })] }) }), _jsx("div", { className: ['accordion-panel-wrapper', isExpanded && 'is-expanded']
117
116
  .filter(Boolean)
118
117
  .join(' '), children: _jsx("div", { id: panelId, role: "region", "aria-labelledby": triggerId, className: "accordion-panel", children: bodyNodes }) })] }));
119
118
  }
@@ -1 +1 @@
1
- {"version":3,"file":"atl-accordion.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/accordion/atl-accordion.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n createContext,\n useContext,\n useState,\n useRef,\n useId,\n useLayoutEffect,\n useCallback,\n ReactNode,\n HTMLAttributes,\n KeyboardEvent,\n} from 'react';\nimport type {\n AtlAccordionGroupSpec,\n AtlAccordionItemSpec,\n} from '../spec';\nimport './atl-accordion.css';\n\ninterface AccordionGroupContextValue {\n multi: boolean;\n openItems: Set<string>;\n toggleItem: (id: string) => void;\n registerItem: (id: string, ref: React.RefObject<HTMLButtonElement | null>, disabled: boolean) => void;\n unregisterItem: (id: string) => void;\n handleKeydown: (e: KeyboardEvent, id: string) => void;\n}\n\nconst AccordionGroupContext = createContext<AccordionGroupContextValue>({\n multi: false,\n openItems: new Set(),\n toggleItem: () => { /* noop */ },\n registerItem: () => { /* noop */ },\n unregisterItem: () => { /* noop */ },\n handleKeydown: () => { /* noop */ },\n});\n\n/**\n * Properties for the AtlAccordionGroup component.\n */\nexport interface AtlAccordionGroupProps\n extends HTMLAttributes<HTMLDivElement>,\n AtlAccordionGroupSpec {\n /**\n * Whether multiple items can be expanded simultaneously.\n */\n multi?: boolean;\n /**\n * The visual style variant of the accordion.\n */\n variant?: 'default' | 'bordered' | 'separated';\n /**\n * The accordion items to be rendered.\n */\n children?: ReactNode;\n}\n\n/**\n * A container component that manages a group of accordion items.\n */\nexport function AtlAccordionGroup({\n multi = false,\n variant = 'default',\n children,\n className,\n ...rest\n}: AtlAccordionGroupProps) {\n const [openItems, setOpenItems] = useState<Set<string>>(new Set());\n const itemsRef = useRef<{ id: string; triggerRef: React.RefObject<HTMLButtonElement | null>; disabled: boolean }[]>([]);\n\n const classes = ['atl-accordion-group', `variant-${variant}`, className]\n .filter(Boolean)\n .join(' ');\n\n const toggleItem = useCallback((id: string) => {\n setOpenItems((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n if (!multi) next.clear();\n next.add(id);\n }\n return next;\n });\n }, [multi]);\n\n const registerItem = useCallback((id: string, ref: React.RefObject<HTMLButtonElement | null>, disabled: boolean) => {\n itemsRef.current = [...itemsRef.current.filter((i) => i.id !== id), { id, triggerRef: ref, disabled }];\n }, []);\n\n const unregisterItem = useCallback((id: string) => {\n itemsRef.current = itemsRef.current.filter((i) => i.id !== id);\n }, []);\n\n const handleKeydown = useCallback((e: KeyboardEvent, currentId: string) => {\n const enabled = itemsRef.current.filter((i) => !i.disabled);\n if (enabled.length === 0) return;\n\n const pos = enabled.findIndex((i) => i.id === currentId);\n const n = enabled.length;\n let target: (typeof enabled)[0] | null = null;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n target = enabled[(pos + 1) % n];\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n target = enabled[(pos - 1 + n) % n];\n } else if (e.key === 'Home') {\n e.preventDefault();\n target = enabled[0];\n } else if (e.key === 'End') {\n e.preventDefault();\n target = enabled[n - 1];\n }\n\n target?.triggerRef.current?.focus();\n }, []);\n\n return (\n <AccordionGroupContext.Provider\n value={{ multi, openItems, toggleItem, registerItem, unregisterItem, handleKeydown }}\n >\n <div className={classes} role=\"presentation\" {...rest}>\n {children}\n </div>\n </AccordionGroupContext.Provider>\n );\n}\n\n/**\n * Properties for the AtlAccordionItem component.\n */\nexport interface AtlAccordionItemProps\n extends HTMLAttributes<HTMLDivElement>,\n AtlAccordionItemSpec {\n /**\n * Whether the item is currently expanded.\n */\n expanded?: boolean;\n /**\n * Callback triggered when the expanded state changes.\n */\n onExpandedChange?: (expanded: boolean) => void;\n /**\n * Whether the accordion item is disabled.\n */\n disabled?: boolean;\n /**\n * HTML heading level wrapping the trigger button. Default `3`.\n * Match your page's heading outline so heading order stays valid.\n */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n /**\n * The content of the accordion item, typically including an AtlAccordionHeader.\n */\n children?: ReactNode;\n}\n\n/**\n * An individual item within an accordion group.\n */\nexport function AtlAccordionItem({\n expanded: externalExpanded,\n onExpandedChange,\n disabled = false,\n headingLevel = 3,\n children,\n className,\n ...rest\n}: AtlAccordionItemProps) {\n const ctx = useContext(AccordionGroupContext);\n const id = useId();\n const triggerId = `${id}-trigger`;\n const panelId = `${id}-panel`;\n const triggerRef = useRef<HTMLButtonElement>(null);\n\n const { registerItem, unregisterItem } = ctx;\n\n // Register/unregister with parent\n useLayoutEffect(() => {\n registerItem(id, triggerRef, disabled);\n return () => unregisterItem(id);\n }, [id, triggerRef, disabled, registerItem, unregisterItem]);\n\n const isControlled = externalExpanded !== undefined;\n const isExpanded = isControlled ? externalExpanded : ctx.openItems.has(id);\n\n const toggle = () => {\n if (disabled) return;\n const next = !isExpanded;\n if (!isControlled) ctx.toggleItem(id);\n onExpandedChange?.(next);\n };\n\n const classes = [\n 'atl-accordion-item',\n isExpanded && 'is-expanded',\n disabled && 'is-disabled',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n // Separate header child from body children\n const childArray = Array.isArray(children) ? children : [children];\n const headerNode = childArray.find(\n (c): c is React.ReactElement =>\n typeof c === 'object' &&\n c !== null &&\n 'type' in (c as object) &&\n (c as React.ReactElement).type === AtlAccordionHeader\n );\n const bodyNodes = childArray.filter((c) => c !== headerNode);\n\n // Render the heading wrapper at the level the consumer asked for.\n // We can't use a JSX expression as a tag, so React.createElement is\n // the cleanest path here.\n const Heading = `h${headingLevel}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n return (\n <div className={classes} {...rest}>\n <Heading className=\"accordion-heading\">\n <button\n ref={triggerRef}\n type=\"button\"\n id={triggerId}\n className={['accordion-trigger', disabled && 'is-disabled']\n .filter(Boolean)\n .join(' ')}\n aria-expanded={isExpanded}\n aria-controls={panelId}\n aria-disabled={disabled || undefined}\n disabled={disabled}\n onClick={toggle}\n onKeyDown={(e) => ctx.handleKeydown(e, id)}\n >\n {headerNode}\n <svg\n className={['chevron', isExpanded && 'is-expanded']\n .filter(Boolean)\n .join(' ')}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M4 6L8 10L12 6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n </Heading>\n <div\n className={['accordion-panel-wrapper', isExpanded && 'is-expanded']\n .filter(Boolean)\n .join(' ')}\n >\n <div\n id={panelId}\n role=\"region\"\n aria-labelledby={triggerId}\n className=\"accordion-panel\"\n >\n {bodyNodes}\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * The header component for an AtlAccordionItem.\n */\nexport function AtlAccordionHeader({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLSpanElement> & {\n /**\n * The content to be rendered in the header.\n */\n children?: ReactNode;\n}) {\n return (\n <span\n className={['accordion-header-content', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {children}\n </span>\n );\n}\n"]}
1
+ {"version":3,"file":"atl-accordion.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/accordion/atl-accordion.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n createContext,\n useContext,\n useState,\n useRef,\n useId,\n useLayoutEffect,\n useCallback,\n ReactNode,\n HTMLAttributes,\n KeyboardEvent,\n} from 'react';\nimport type {\n AtlAccordionGroupSpec,\n AtlAccordionItemSpec,\n} from '../spec';\nimport './atl-accordion.css';\nimport { AtlIcon } from '../icon/atl-icon';\n\ninterface AccordionGroupContextValue {\n multi: boolean;\n openItems: Set<string>;\n toggleItem: (id: string) => void;\n registerItem: (id: string, ref: React.RefObject<HTMLButtonElement | null>, disabled: boolean) => void;\n unregisterItem: (id: string) => void;\n handleKeydown: (e: KeyboardEvent, id: string) => void;\n}\n\nconst AccordionGroupContext = createContext<AccordionGroupContextValue>({\n multi: false,\n openItems: new Set(),\n toggleItem: () => { /* noop */ },\n registerItem: () => { /* noop */ },\n unregisterItem: () => { /* noop */ },\n handleKeydown: () => { /* noop */ },\n});\n\n/**\n * Properties for the AtlAccordionGroup component.\n */\nexport interface AtlAccordionGroupProps\n extends HTMLAttributes<HTMLDivElement>,\n AtlAccordionGroupSpec {\n /**\n * Whether multiple items can be expanded simultaneously.\n */\n multi?: boolean;\n /**\n * The visual style variant of the accordion.\n */\n variant?: 'default' | 'bordered' | 'separated';\n /**\n * The accordion items to be rendered.\n */\n children?: ReactNode;\n}\n\n/**\n * A container component that manages a group of accordion items.\n */\nexport function AtlAccordionGroup({\n multi = false,\n variant = 'default',\n children,\n className,\n ...rest\n}: AtlAccordionGroupProps) {\n const [openItems, setOpenItems] = useState<Set<string>>(new Set());\n const itemsRef = useRef<{ id: string; triggerRef: React.RefObject<HTMLButtonElement | null>; disabled: boolean }[]>([]);\n\n const classes = ['atl-accordion-group', `variant-${variant}`, className]\n .filter(Boolean)\n .join(' ');\n\n const toggleItem = useCallback((id: string) => {\n setOpenItems((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n if (!multi) next.clear();\n next.add(id);\n }\n return next;\n });\n }, [multi]);\n\n const registerItem = useCallback((id: string, ref: React.RefObject<HTMLButtonElement | null>, disabled: boolean) => {\n itemsRef.current = [...itemsRef.current.filter((i) => i.id !== id), { id, triggerRef: ref, disabled }];\n }, []);\n\n const unregisterItem = useCallback((id: string) => {\n itemsRef.current = itemsRef.current.filter((i) => i.id !== id);\n }, []);\n\n const handleKeydown = useCallback((e: KeyboardEvent, currentId: string) => {\n const enabled = itemsRef.current.filter((i) => !i.disabled);\n if (enabled.length === 0) return;\n\n const pos = enabled.findIndex((i) => i.id === currentId);\n const n = enabled.length;\n let target: (typeof enabled)[0] | null = null;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n target = enabled[(pos + 1) % n];\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n target = enabled[(pos - 1 + n) % n];\n } else if (e.key === 'Home') {\n e.preventDefault();\n target = enabled[0];\n } else if (e.key === 'End') {\n e.preventDefault();\n target = enabled[n - 1];\n }\n\n target?.triggerRef.current?.focus();\n }, []);\n\n return (\n <AccordionGroupContext.Provider\n value={{ multi, openItems, toggleItem, registerItem, unregisterItem, handleKeydown }}\n >\n <div className={classes} role=\"presentation\" {...rest}>\n {children}\n </div>\n </AccordionGroupContext.Provider>\n );\n}\n\n/**\n * Properties for the AtlAccordionItem component.\n */\nexport interface AtlAccordionItemProps\n extends HTMLAttributes<HTMLDivElement>,\n AtlAccordionItemSpec {\n /**\n * Whether the item is currently expanded.\n */\n expanded?: boolean;\n /**\n * Callback triggered when the expanded state changes.\n */\n onExpandedChange?: (expanded: boolean) => void;\n /**\n * Whether the accordion item is disabled.\n */\n disabled?: boolean;\n /**\n * HTML heading level wrapping the trigger button. Default `3`.\n * Match your page's heading outline so heading order stays valid.\n */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n /**\n * The content of the accordion item, typically including an AtlAccordionHeader.\n */\n children?: ReactNode;\n}\n\n/**\n * An individual item within an accordion group.\n */\nexport function AtlAccordionItem({\n expanded: externalExpanded,\n onExpandedChange,\n disabled = false,\n headingLevel = 3,\n children,\n className,\n ...rest\n}: AtlAccordionItemProps) {\n const ctx = useContext(AccordionGroupContext);\n const id = useId();\n const triggerId = `${id}-trigger`;\n const panelId = `${id}-panel`;\n const triggerRef = useRef<HTMLButtonElement>(null);\n\n const { registerItem, unregisterItem } = ctx;\n\n // Register/unregister with parent\n useLayoutEffect(() => {\n registerItem(id, triggerRef, disabled);\n return () => unregisterItem(id);\n }, [id, triggerRef, disabled, registerItem, unregisterItem]);\n\n const isControlled = externalExpanded !== undefined;\n const isExpanded = isControlled ? externalExpanded : ctx.openItems.has(id);\n\n const toggle = () => {\n if (disabled) return;\n const next = !isExpanded;\n if (!isControlled) ctx.toggleItem(id);\n onExpandedChange?.(next);\n };\n\n const classes = [\n 'atl-accordion-item',\n isExpanded && 'is-expanded',\n disabled && 'is-disabled',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n // Separate header child from body children\n const childArray = Array.isArray(children) ? children : [children];\n const headerNode = childArray.find(\n (c): c is React.ReactElement =>\n typeof c === 'object' &&\n c !== null &&\n 'type' in (c as object) &&\n (c as React.ReactElement).type === AtlAccordionHeader\n );\n const bodyNodes = childArray.filter((c) => c !== headerNode);\n\n // Render the heading wrapper at the level the consumer asked for.\n // We can't use a JSX expression as a tag, so React.createElement is\n // the cleanest path here.\n const Heading = `h${headingLevel}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n return (\n <div className={classes} {...rest}>\n <Heading className=\"accordion-heading\">\n <button\n ref={triggerRef}\n type=\"button\"\n id={triggerId}\n className={['accordion-trigger', disabled && 'is-disabled']\n .filter(Boolean)\n .join(' ')}\n aria-expanded={isExpanded}\n aria-controls={panelId}\n aria-disabled={disabled || undefined}\n disabled={disabled}\n onClick={toggle}\n onKeyDown={(e) => ctx.handleKeydown(e, id)}\n >\n {headerNode}\n <AtlIcon name=\"chevron-down\" size=\"sm\" className={['chevron', isExpanded && 'is-expanded'].filter(Boolean).join(' ')} />\n </button>\n </Heading>\n <div\n className={['accordion-panel-wrapper', isExpanded && 'is-expanded']\n .filter(Boolean)\n .join(' ')}\n >\n <div\n id={panelId}\n role=\"region\"\n aria-labelledby={triggerId}\n className=\"accordion-panel\"\n >\n {bodyNodes}\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * The header component for an AtlAccordionItem.\n */\nexport function AtlAccordionHeader({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLSpanElement> & {\n /**\n * The content to be rendered in the header.\n */\n children?: ReactNode;\n}) {\n return (\n <span\n className={['accordion-header-content', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {children}\n </span>\n );\n}\n"]}
@@ -1,10 +1,20 @@
1
+ /* Geometry contract: every size this component states is a border-box size.
2
+ * Declared with the component rather than as a global reset, so it ships in the
3
+ * same file as the sizes it governs and no consuming app has to supply one.
4
+ * Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
5
+ * See ADR-0043. */
6
+ .atl-alert,
7
+ .atl-alert * {
8
+ box-sizing: border-box;
9
+ }
10
+
1
11
  .atl-alert {
2
12
  display: flex;
3
13
  align-items: flex-start;
4
14
  gap: var(--ui-spacing-3);
5
15
  padding: var(--ui-spacing-4) var(--ui-spacing-5);
6
16
  border-radius: var(--ui-radius-lg);
7
- border: 1px solid transparent;
17
+ border: var(--ui-border-width) solid transparent;
8
18
  font-family: var(--ui-font-family);
9
19
  font-size: var(--ui-font-size-sm);
10
20
  line-height: var(--ui-line-height-normal);
@@ -1 +1 @@
1
- {"version":3,"file":"atl-alert.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/alert/atl-alert.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,iBAAiB,CAAC;AAEzB,KAAK,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AASjE;;GAEG;AACH,MAAM,WAAW,aACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EACpC,YAAY;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,EACvB,OAAgB,EAChB,WAAmB,EACnB,WAAW,EACX,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,aAAa,+BAoCf"}
1
+ {"version":3,"file":"atl-alert.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/alert/atl-alert.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,iBAAiB,CAAC;AAGzB,KAAK,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AASjE;;GAEG;AACH,MAAM,WAAW,aACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EACpC,YAAY;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,EACvB,OAAgB,EAChB,WAAmB,EACnB,WAAW,EACX,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,aAAa,+BAsBf"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import './atl-alert.css';
3
+ import { AtlIcon } from '../icon/atl-icon';
3
4
  const VARIANT_ICONS = {
4
5
  info: 'ℹ',
5
6
  success: '✓',
@@ -12,6 +13,6 @@ const VARIANT_ICONS = {
12
13
  export function AtlAlert({ variant = 'info', dismissible = false, onDismissed, children, className, ...rest }) {
13
14
  const classes = ['atl-alert', `variant-${variant}`, className].filter(Boolean).join(' ');
14
15
  const ariaLive = variant === 'danger' || variant === 'warning' ? 'assertive' : 'polite';
15
- return (_jsxs("div", { className: classes, role: "alert", "aria-live": ariaLive, ...rest, children: [_jsxs("span", { className: "content", children: [_jsx("span", { className: "variant-icon", "aria-hidden": "true", children: VARIANT_ICONS[variant] }), children] }), dismissible && (_jsx("button", { className: "dismiss", type: "button", "aria-label": "Dismiss", onClick: onDismissed, children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }))] }));
16
+ return (_jsxs("div", { className: classes, role: "alert", "aria-live": ariaLive, ...rest, children: [_jsxs("span", { className: "content", children: [_jsx("span", { className: "variant-icon", "aria-hidden": "true", children: VARIANT_ICONS[variant] }), children] }), dismissible && (_jsx("button", { className: "dismiss", type: "button", "aria-label": "Dismiss", onClick: onDismissed, children: _jsx(AtlIcon, { name: "close", size: "sm" }) }))] }));
16
17
  }
17
18
  //# sourceMappingURL=atl-alert.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"atl-alert.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/alert/atl-alert.tsx"],"names":[],"mappings":";AAEA,OAAO,iBAAiB,CAAC;AAIzB,MAAM,aAAa,GAAoC;IACrD,IAAI,EAAE,GAAG;IACT,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,GAAG;IACZ,MAAM,EAAE,GAAG;CACZ,CAAC;AA0BF;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,EACvB,OAAO,GAAG,MAAM,EAChB,WAAW,GAAG,KAAK,EACnB,WAAW,EACX,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACO;IACd,MAAM,OAAO,GAAG,CAAC,WAAW,EAAE,WAAW,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzF,MAAM,QAAQ,GAAG,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;IAExF,OAAO,CACL,eAAK,SAAS,EAAE,OAAO,EAAE,IAAI,EAAC,OAAO,eAAY,QAAQ,KAAM,IAAI,aACjE,gBAAM,SAAS,EAAC,SAAS,aACvB,eAAM,SAAS,EAAC,cAAc,iBAAa,MAAM,YAAE,aAAa,CAAC,OAAO,CAAC,GAAQ,EAChF,QAAQ,IACJ,EACN,WAAW,IAAI,CACd,iBACE,SAAS,EAAC,SAAS,EACnB,IAAI,EAAC,QAAQ,gBACF,SAAS,EACpB,OAAO,EAAE,WAAW,YAEpB,eACE,KAAK,EAAC,4BAA4B,EAClC,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,iBACV,MAAM,aAElB,eAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,GAAG,EACtC,eAAM,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,GAAG,IAClC,GACC,CACV,IACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { HTMLAttributes, ReactNode } from 'react';\nimport type { AtlAlertSpec } from '../spec';\nimport './atl-alert.css';\n\ntype AtlAlertVariant = 'info' | 'success' | 'warning' | 'danger';\n\nconst VARIANT_ICONS: Record<AtlAlertVariant, string> = {\n info: 'ℹ',\n success: '✓',\n warning: '⚠',\n danger: '✕',\n};\n\n/**\n * Properties for the AtlAlert component.\n */\nexport interface AtlAlertProps\n extends HTMLAttributes<HTMLDivElement>,\n AtlAlertSpec {\n /**\n * The visual style variant of the alert.\n */\n variant?: AtlAlertVariant;\n /**\n * Whether the alert can be dismissed by the user.\n */\n dismissible?: boolean;\n /**\n * Callback triggered when the alert is dismissed.\n */\n onDismissed?: () => void;\n /**\n * The content to be rendered inside the alert.\n */\n children?: ReactNode;\n}\n\n/**\n * An alert component for displaying important messages.\n */\nexport function AtlAlert({\n variant = 'info',\n dismissible = false,\n onDismissed,\n children,\n className,\n ...rest\n}: AtlAlertProps) {\n const classes = ['atl-alert', `variant-${variant}`, className].filter(Boolean).join(' ');\n const ariaLive = variant === 'danger' || variant === 'warning' ? 'assertive' : 'polite';\n\n return (\n <div className={classes} role=\"alert\" aria-live={ariaLive} {...rest}>\n <span className=\"content\">\n <span className=\"variant-icon\" aria-hidden=\"true\">{VARIANT_ICONS[variant]}</span>\n {children}\n </span>\n {dismissible && (\n <button\n className=\"dismiss\"\n type=\"button\"\n aria-label=\"Dismiss\"\n onClick={onDismissed}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"atl-alert.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/alert/atl-alert.tsx"],"names":[],"mappings":";AAEA,OAAO,iBAAiB,CAAC;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAI3C,MAAM,aAAa,GAAoC;IACrD,IAAI,EAAE,GAAG;IACT,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,GAAG;IACZ,MAAM,EAAE,GAAG;CACZ,CAAC;AA0BF;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,EACvB,OAAO,GAAG,MAAM,EAChB,WAAW,GAAG,KAAK,EACnB,WAAW,EACX,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACO;IACd,MAAM,OAAO,GAAG,CAAC,WAAW,EAAE,WAAW,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzF,MAAM,QAAQ,GAAG,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;IAExF,OAAO,CACL,eAAK,SAAS,EAAE,OAAO,EAAE,IAAI,EAAC,OAAO,eAAY,QAAQ,KAAM,IAAI,aACjE,gBAAM,SAAS,EAAC,SAAS,aACvB,eAAM,SAAS,EAAC,cAAc,iBAAa,MAAM,YAAE,aAAa,CAAC,OAAO,CAAC,GAAQ,EAChF,QAAQ,IACJ,EACN,WAAW,IAAI,CACd,iBACE,SAAS,EAAC,SAAS,EACnB,IAAI,EAAC,QAAQ,gBACF,SAAS,EACpB,OAAO,EAAE,WAAW,YAEpB,KAAC,OAAO,IAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,GAAG,GAC3B,CACV,IACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { HTMLAttributes, ReactNode } from 'react';\nimport type { AtlAlertSpec } from '../spec';\nimport './atl-alert.css';\nimport { AtlIcon } from '../icon/atl-icon';\n\ntype AtlAlertVariant = 'info' | 'success' | 'warning' | 'danger';\n\nconst VARIANT_ICONS: Record<AtlAlertVariant, string> = {\n info: 'ℹ',\n success: '✓',\n warning: '⚠',\n danger: '✕',\n};\n\n/**\n * Properties for the AtlAlert component.\n */\nexport interface AtlAlertProps\n extends HTMLAttributes<HTMLDivElement>,\n AtlAlertSpec {\n /**\n * The visual style variant of the alert.\n */\n variant?: AtlAlertVariant;\n /**\n * Whether the alert can be dismissed by the user.\n */\n dismissible?: boolean;\n /**\n * Callback triggered when the alert is dismissed.\n */\n onDismissed?: () => void;\n /**\n * The content to be rendered inside the alert.\n */\n children?: ReactNode;\n}\n\n/**\n * An alert component for displaying important messages.\n */\nexport function AtlAlert({\n variant = 'info',\n dismissible = false,\n onDismissed,\n children,\n className,\n ...rest\n}: AtlAlertProps) {\n const classes = ['atl-alert', `variant-${variant}`, className].filter(Boolean).join(' ');\n const ariaLive = variant === 'danger' || variant === 'warning' ? 'assertive' : 'polite';\n\n return (\n <div className={classes} role=\"alert\" aria-live={ariaLive} {...rest}>\n <span className=\"content\">\n <span className=\"variant-icon\" aria-hidden=\"true\">{VARIANT_ICONS[variant]}</span>\n {children}\n </span>\n {dismissible && (\n <button\n className=\"dismiss\"\n type=\"button\"\n aria-label=\"Dismiss\"\n onClick={onDismissed}\n >\n <AtlIcon name=\"close\" size=\"sm\" />\n </button>\n )}\n </div>\n );\n}\n"]}
@@ -1,3 +1,19 @@
1
+ /* Geometry contract: every size this component states is a border-box size.
2
+ * Declared with the component rather than as a global reset, so it ships in the
3
+ * same file as the sizes it governs and no consuming app has to supply one.
4
+ * Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
5
+ * See ADR-0043. */
6
+ :is(
7
+ .atl-avatar,
8
+ .atl-avatar-group
9
+ ),
10
+ :is(
11
+ .atl-avatar,
12
+ .atl-avatar-group
13
+ ) * {
14
+ box-sizing: border-box;
15
+ }
16
+
1
17
  /* === AtlAvatar === */
2
18
 
3
19
  .atl-avatar {
@@ -40,7 +56,7 @@
40
56
  }
41
57
 
42
58
  /* Fallback icon */
43
- .atl-avatar .icon {
59
+ .atl-avatar .atl-icon.icon {
44
60
  width: 55%;
45
61
  height: 55%;
46
62
  opacity: 0.6;
@@ -58,7 +74,7 @@
58
74
  max-width: 14px;
59
75
  max-height: 14px;
60
76
  border-radius: var(--ui-radius-full);
61
- border: 2px solid var(--ui-color-surface);
77
+ border: var(--ui-border-width-thick) solid var(--ui-color-surface);
62
78
  box-sizing: content-box;
63
79
  }
64
80
 
@@ -91,7 +107,7 @@
91
107
  flex-shrink: 0;
92
108
  background-color: var(--ui-color-surface-sunken);
93
109
  color: var(--ui-color-text-muted);
94
- border: 1px solid var(--ui-color-border);
110
+ border: var(--ui-border-width) solid var(--ui-color-border);
95
111
  border-radius: var(--ui-radius-full);
96
112
  font-family: var(--ui-font-family);
97
113
  font-weight: var(--ui-font-weight-semibold);
@@ -1 +1 @@
1
- {"version":3,"file":"atl-avatar.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/avatar/atl-avatar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAsB,MAAM,OAAO,CAAC;AACtE,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EACnB,MAAM,SAAS,CAAC;AACjB,OAAO,kBAAkB,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,cACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EACpC,aAAa;IACf;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACxC;;OAEG;IACH,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B;;OAEG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC;CACtD;AAWD;;GAEG;AACH,wBAAgB,SAAS,CAAC,EACxB,GAAQ,EACR,GAAQ,EACR,IAAS,EACT,IAAW,EACX,KAAgB,EAChB,MAAW,EACX,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,+BA8BhB;AAED;;GAEG;AACH,MAAM,WAAW,mBACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EACpC,kBAAkB;IACpB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9B;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,GAAO,EACP,IAAW,EACX,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,mBAAmB,+BAoBrB"}
1
+ {"version":3,"file":"atl-avatar.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/avatar/atl-avatar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAsB,MAAM,OAAO,CAAC;AACtE,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EACnB,MAAM,SAAS,CAAC;AACjB,OAAO,kBAAkB,CAAC;AAG1B;;GAEG;AACH,MAAM,WAAW,cACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EACpC,aAAa;IACf;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACxC;;OAEG;IACH,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B;;OAEG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC;CACtD;AAWD;;GAEG;AACH,wBAAgB,SAAS,CAAC,EACxB,GAAQ,EACR,GAAQ,EACR,IAAS,EACT,IAAW,EACX,KAAgB,EAChB,MAAW,EACX,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,+BA4BhB;AAED;;GAEG;AACH,MAAM,WAAW,mBACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EACpC,kBAAkB;IACpB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9B;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,GAAO,EACP,IAAW,EACX,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,mBAAmB,+BAoBrB"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Children, useState } from 'react';
3
3
  import './atl-avatar.css';
4
+ import { AtlIcon } from '../icon/atl-icon';
4
5
  function getInitials(name) {
5
6
  return name
6
7
  .split(' ')
@@ -24,7 +25,7 @@ export function AtlAvatar({ src = '', alt = '', name = '', size = 'md', shape =
24
25
  .filter(Boolean).join(' ');
25
26
  const initials = name ? getInitials(name) : '';
26
27
  const ariaLabel = alt || name || 'Avatar';
27
- return (_jsxs("div", { className: classes, "aria-label": ariaLabel, role: "img", ...rest, children: [src && !imgError ? (_jsx("img", { src: src, alt: alt || name, onError: () => setImgError(true) })) : initials ? (_jsx("span", { className: "initials", "aria-hidden": "true", children: initials })) : (_jsx("svg", { className: "icon", "aria-hidden": "true", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M12 12c2.761 0 5-2.239 5-5s-2.239-5-5-5-5 2.239-5 5 2.239 5 5 5zm0 2c-3.314 0-10 1.343-10 4v2h20v-2c0-2.657-6.686-4-10-4z" }) })), status && _jsx("span", { className: `status-dot status-${status}`, "aria-hidden": "true" })] }));
28
+ return (_jsxs("div", { className: classes, "aria-label": ariaLabel, role: "img", ...rest, children: [src && !imgError ? (_jsx("img", { src: src, alt: alt || name, onError: () => setImgError(true) })) : initials ? (_jsx("span", { className: "initials", "aria-hidden": "true", children: initials })) : (_jsx(AtlIcon, { name: "person", size: "sm", className: "icon" })), status && _jsx("span", { className: `status-dot status-${status}`, "aria-hidden": "true" })] }));
28
29
  }
29
30
  /**
30
31
  * A container for grouping multiple avatars.
@@ -1 +1 @@
1
- {"version":3,"file":"atl-avatar.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/avatar/atl-avatar.tsx"],"names":[],"mappings":"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","sourcesContent":["import { HTMLAttributes, ReactNode, Children, useState } from 'react';\nimport type {\n AtlAvatarSpec,\n AtlAvatarGroupSpec,\n} from '../spec';\nimport './atl-avatar.css';\n\n/**\n * Properties for the AtlAvatar component.\n */\nexport interface AtlAvatarProps\n extends HTMLAttributes<HTMLDivElement>,\n AtlAvatarSpec {\n /**\n * The URL of the image to display.\n */\n src?: string;\n /**\n * Accessible text for the avatar image.\n */\n alt?: string;\n /**\n * The name of the person/entity, used for initials if no image is provided.\n */\n name?: string;\n /**\n * The size of the avatar.\n */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /**\n * The shape of the avatar.\n */\n shape?: 'circle' | 'square';\n /**\n * The status indicator to display on the avatar.\n */\n status?: 'online' | 'offline' | 'away' | 'busy' | '';\n}\n\nfunction getInitials(name: string): string {\n return name\n .split(' ')\n .filter(Boolean)\n .slice(0, 2)\n .map((w) => w[0].toUpperCase())\n .join('');\n}\n\n/**\n * An avatar component for displaying user profile pictures or initials.\n */\nexport function AtlAvatar({\n src = '',\n alt = '',\n name = '',\n size = 'md',\n shape = 'circle',\n status = '',\n className,\n ...rest\n}: AtlAvatarProps) {\n const [imgError, setImgError] = useState(false);\n const [prevSrc, setPrevSrc] = useState(src);\n\n // Reset imgError when src changes\n if (src !== prevSrc) {\n setPrevSrc(src);\n setImgError(false);\n }\n\n const classes = ['atl-avatar', `size-${size}`, `shape-${shape}`, className]\n .filter(Boolean).join(' ');\n\n const initials = name ? getInitials(name) : '';\n const ariaLabel = alt || name || 'Avatar';\n\n return (\n <div className={classes} aria-label={ariaLabel} role=\"img\" {...rest}>\n {src && !imgError ? (\n <img src={src} alt={alt || name} onError={() => setImgError(true)} />\n ) : initials ? (\n <span className=\"initials\" aria-hidden=\"true\">{initials}</span>\n ) : (\n <svg className=\"icon\" aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 12c2.761 0 5-2.239 5-5s-2.239-5-5-5-5 2.239-5 5 2.239 5 5 5zm0 2c-3.314 0-10 1.343-10 4v2h20v-2c0-2.657-6.686-4-10-4z\" />\n </svg>\n )}\n {status && <span className={`status-dot status-${status}`} aria-hidden=\"true\" />}\n </div>\n );\n}\n\n/**\n * Properties for the AtlAvatarGroup component.\n */\nexport interface AtlAvatarGroupProps\n extends HTMLAttributes<HTMLDivElement>,\n AtlAvatarGroupSpec {\n /**\n * The maximum number of avatars to show before displaying an overflow badge.\n */\n max?: number;\n /**\n * The size of the avatars in the group.\n */\n size?: AtlAvatarProps['size'];\n /**\n * The avatars to be rendered in the group.\n */\n children?: ReactNode;\n}\n\n/**\n * A container for grouping multiple avatars.\n */\nexport function AtlAvatarGroup({\n max = 5,\n size = 'md',\n children,\n className,\n ...rest\n}: AtlAvatarGroupProps) {\n const childArray = Children.toArray(children);\n const visible = childArray.slice(0, max);\n const overflow = childArray.length - max;\n\n const classes = ['atl-avatar-group', `size-${size}`, className].filter(Boolean).join(' ');\n\n return (\n <div className={classes} {...rest}>\n {visible}\n {overflow > 0 && (\n <div\n className={`overflow-badge size-${size}`}\n aria-label={`+${overflow} more`}\n >\n +{overflow}\n </div>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"atl-avatar.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/avatar/atl-avatar.tsx"],"names":[],"mappings":";AAAA,OAAO,EAA6B,QAAQ,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAKtE,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAkC3C,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI;SACR,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,OAAO,CAAC;SACf,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAC9B,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,GAAG,GAAG,EAAE,EACR,GAAG,GAAG,EAAE,EACR,IAAI,GAAG,EAAE,EACT,IAAI,GAAG,IAAI,EACX,KAAK,GAAG,QAAQ,EAChB,MAAM,GAAG,EAAE,EACX,SAAS,EACT,GAAG,IAAI,EACQ;IACf,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAE5C,kCAAkC;IAClC,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,UAAU,CAAC,GAAG,CAAC,CAAC;QAChB,WAAW,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,YAAY,EAAE,QAAQ,IAAI,EAAE,EAAE,SAAS,KAAK,EAAE,EAAE,SAAS,CAAC;SACxE,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE7B,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,IAAI,QAAQ,CAAC;IAE1C,OAAO,CACL,eAAK,SAAS,EAAE,OAAO,gBAAc,SAAS,EAAE,IAAI,EAAC,KAAK,KAAK,IAAI,aAChE,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAClB,cAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,GAAI,CACtE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CACb,eAAM,SAAS,EAAC,UAAU,iBAAa,MAAM,YAAE,QAAQ,GAAQ,CAChE,CAAC,CAAC,CAAC,CACF,KAAC,OAAO,IAAC,IAAI,EAAC,QAAQ,EAAC,IAAI,EAAC,IAAI,EAAC,SAAS,EAAC,MAAM,GAAG,CACrD,EACA,MAAM,IAAI,eAAM,SAAS,EAAE,qBAAqB,MAAM,EAAE,iBAAc,MAAM,GAAG,IAC5E,CACP,CAAC;AACJ,CAAC;AAsBD;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,GAAG,GAAG,CAAC,EACP,IAAI,GAAG,IAAI,EACX,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACa;IACpB,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC;IAEzC,MAAM,OAAO,GAAG,CAAC,kBAAkB,EAAE,QAAQ,IAAI,EAAE,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE1F,OAAO,CACL,eAAK,SAAS,EAAE,OAAO,KAAM,IAAI,aAC9B,OAAO,EACP,QAAQ,GAAG,CAAC,IAAI,CACf,eACE,SAAS,EAAE,uBAAuB,IAAI,EAAE,gBAC5B,IAAI,QAAQ,OAAO,kBAE7B,QAAQ,IACN,CACP,IACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { HTMLAttributes, ReactNode, Children, useState } from 'react';\nimport type {\n AtlAvatarSpec,\n AtlAvatarGroupSpec,\n} from '../spec';\nimport './atl-avatar.css';\nimport { AtlIcon } from '../icon/atl-icon';\n\n/**\n * Properties for the AtlAvatar component.\n */\nexport interface AtlAvatarProps\n extends HTMLAttributes<HTMLDivElement>,\n AtlAvatarSpec {\n /**\n * The URL of the image to display.\n */\n src?: string;\n /**\n * Accessible text for the avatar image.\n */\n alt?: string;\n /**\n * The name of the person/entity, used for initials if no image is provided.\n */\n name?: string;\n /**\n * The size of the avatar.\n */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /**\n * The shape of the avatar.\n */\n shape?: 'circle' | 'square';\n /**\n * The status indicator to display on the avatar.\n */\n status?: 'online' | 'offline' | 'away' | 'busy' | '';\n}\n\nfunction getInitials(name: string): string {\n return name\n .split(' ')\n .filter(Boolean)\n .slice(0, 2)\n .map((w) => w[0].toUpperCase())\n .join('');\n}\n\n/**\n * An avatar component for displaying user profile pictures or initials.\n */\nexport function AtlAvatar({\n src = '',\n alt = '',\n name = '',\n size = 'md',\n shape = 'circle',\n status = '',\n className,\n ...rest\n}: AtlAvatarProps) {\n const [imgError, setImgError] = useState(false);\n const [prevSrc, setPrevSrc] = useState(src);\n\n // Reset imgError when src changes\n if (src !== prevSrc) {\n setPrevSrc(src);\n setImgError(false);\n }\n\n const classes = ['atl-avatar', `size-${size}`, `shape-${shape}`, className]\n .filter(Boolean).join(' ');\n\n const initials = name ? getInitials(name) : '';\n const ariaLabel = alt || name || 'Avatar';\n\n return (\n <div className={classes} aria-label={ariaLabel} role=\"img\" {...rest}>\n {src && !imgError ? (\n <img src={src} alt={alt || name} onError={() => setImgError(true)} />\n ) : initials ? (\n <span className=\"initials\" aria-hidden=\"true\">{initials}</span>\n ) : (\n <AtlIcon name=\"person\" size=\"sm\" className=\"icon\" />\n )}\n {status && <span className={`status-dot status-${status}`} aria-hidden=\"true\" />}\n </div>\n );\n}\n\n/**\n * Properties for the AtlAvatarGroup component.\n */\nexport interface AtlAvatarGroupProps\n extends HTMLAttributes<HTMLDivElement>,\n AtlAvatarGroupSpec {\n /**\n * The maximum number of avatars to show before displaying an overflow badge.\n */\n max?: number;\n /**\n * The size of the avatars in the group.\n */\n size?: AtlAvatarProps['size'];\n /**\n * The avatars to be rendered in the group.\n */\n children?: ReactNode;\n}\n\n/**\n * A container for grouping multiple avatars.\n */\nexport function AtlAvatarGroup({\n max = 5,\n size = 'md',\n children,\n className,\n ...rest\n}: AtlAvatarGroupProps) {\n const childArray = Children.toArray(children);\n const visible = childArray.slice(0, max);\n const overflow = childArray.length - max;\n\n const classes = ['atl-avatar-group', `size-${size}`, className].filter(Boolean).join(' ');\n\n return (\n <div className={classes} {...rest}>\n {visible}\n {overflow > 0 && (\n <div\n className={`overflow-badge size-${size}`}\n aria-label={`+${overflow} more`}\n >\n +{overflow}\n </div>\n )}\n </div>\n );\n}\n"]}
@@ -1,3 +1,13 @@
1
+ /* Geometry contract: every size this component states is a border-box size.
2
+ * Declared with the component rather than as a global reset, so it ships in the
3
+ * same file as the sizes it governs and no consuming app has to supply one.
4
+ * Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
5
+ * See ADR-0043. */
6
+ .atl-badge,
7
+ .atl-badge * {
8
+ box-sizing: border-box;
9
+ }
10
+
1
11
  .atl-badge {
2
12
  display: inline-flex;
3
13
  align-items: center;
@@ -7,7 +17,7 @@
7
17
  font-weight: var(--ui-font-weight-semibold);
8
18
  line-height: var(--ui-line-height-tight);
9
19
  white-space: nowrap;
10
- letter-spacing: 0.01em;
20
+ letter-spacing: var(--ui-letter-spacing-wide);
11
21
  }
12
22
 
13
23
  /* Sizes */
@@ -25,31 +35,31 @@
25
35
  .atl-badge.variant-default {
26
36
  background-color: var(--ui-color-surface-sunken);
27
37
  color: var(--ui-color-text-muted);
28
- border: 1px solid var(--ui-color-border);
38
+ border: var(--ui-border-width) solid var(--ui-color-border);
29
39
  }
30
40
 
31
41
  .atl-badge.variant-success {
32
42
  background-color: var(--ui-color-success-bg);
33
43
  color: var(--ui-color-success-text);
34
- border: 1px solid color-mix(in srgb, var(--ui-color-success-text) 25%, transparent);
44
+ border: var(--ui-border-width) solid color-mix(in srgb, var(--ui-color-success-text) 25%, transparent);
35
45
  }
36
46
 
37
47
  .atl-badge.variant-warning {
38
48
  background-color: var(--ui-color-warning-bg);
39
49
  color: var(--ui-color-warning-text);
40
- border: 1px solid color-mix(in srgb, var(--ui-color-warning-text) 25%, transparent);
50
+ border: var(--ui-border-width) solid color-mix(in srgb, var(--ui-color-warning-text) 25%, transparent);
41
51
  }
42
52
 
43
53
  .atl-badge.variant-danger {
44
54
  background-color: var(--ui-color-danger-bg);
45
55
  color: var(--ui-color-danger-text);
46
- border: 1px solid color-mix(in srgb, var(--ui-color-danger-text) 25%, transparent);
56
+ border: var(--ui-border-width) solid color-mix(in srgb, var(--ui-color-danger-text) 25%, transparent);
47
57
  }
48
58
 
49
59
  .atl-badge.variant-info {
50
60
  background-color: var(--ui-color-info-bg);
51
61
  color: var(--ui-color-info-text);
52
- border: 1px solid color-mix(in srgb, var(--ui-color-info-text) 25%, transparent);
62
+ border: var(--ui-border-width) solid color-mix(in srgb, var(--ui-color-info-text) 25%, transparent);
53
63
  }
54
64
 
55
65
  /* Semantic indicator glyph — non-color differentiation (WCAG 1.4.1). */
@@ -1,3 +1,19 @@
1
+ /* Geometry contract: every size this component states is a border-box size.
2
+ * Declared with the component rather than as a global reset, so it ships in the
3
+ * same file as the sizes it governs and no consuming app has to supply one.
4
+ * Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
5
+ * See ADR-0043. */
6
+ :is(
7
+ .atl-breadcrumb-item,
8
+ .atl-breadcrumbs
9
+ ),
10
+ :is(
11
+ .atl-breadcrumb-item,
12
+ .atl-breadcrumbs
13
+ ) * {
14
+ box-sizing: border-box;
15
+ }
16
+
1
17
  /* AtlBreadcrumbs */
2
18
  .atl-breadcrumbs {
3
19
  display: block;
@@ -1,9 +1,19 @@
1
+ /* Geometry contract: every size this component states is a border-box size.
2
+ * Declared with the component rather than as a global reset, so it ships in the
3
+ * same file as the sizes it governs and no consuming app has to supply one.
4
+ * Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
5
+ * See ADR-0043. */
6
+ .atl-button,
7
+ .atl-button * {
8
+ box-sizing: border-box;
9
+ }
10
+
1
11
  .atl-button {
2
12
  display: inline-flex;
3
13
  align-items: center;
4
14
  justify-content: center;
5
15
  gap: var(--ui-spacing-2);
6
- border: 1px solid transparent;
16
+ border: var(--ui-border-width) solid transparent;
7
17
  border-radius: var(--ui-radius-md);
8
18
  font-family: var(--ui-font-family);
9
19
  font-size: var(--ui-font-size-md);
@@ -98,21 +108,33 @@
98
108
 
99
109
  /* Sizes — modern target heights (sm 32px / md 40px / lg 48px) */
100
110
  .atl-button.size-sm {
101
- padding: 0.375rem 0.875rem;
111
+ padding: calc(
112
+ (var(--ui-control-height-sm) - var(--ui-line-height-tight) * var(--ui-font-size-sm)) / 2 -
113
+ 1px
114
+ )
115
+ 0.875rem;
102
116
  font-size: var(--ui-font-size-sm);
103
- min-height: 2rem;
117
+ min-height: var(--ui-control-height-sm);
104
118
  }
105
119
 
106
120
  .atl-button.size-md {
107
- padding: 0.5625rem 1.125rem;
121
+ padding: calc(
122
+ (var(--ui-control-height-md) - var(--ui-line-height-tight) * var(--ui-font-size-md)) / 2 -
123
+ 1px
124
+ )
125
+ 1.125rem;
108
126
  font-size: var(--ui-font-size-md);
109
- min-height: 2.5rem;
127
+ min-height: var(--ui-control-height-md);
110
128
  }
111
129
 
112
130
  .atl-button.size-lg {
113
- padding: 0.75rem 1.5rem;
131
+ padding: calc(
132
+ (var(--ui-control-height-lg) - var(--ui-line-height-tight) * var(--ui-font-size-lg)) / 2 -
133
+ 1px
134
+ )
135
+ 1.5rem;
114
136
  font-size: var(--ui-font-size-lg);
115
- min-height: 3rem;
137
+ min-height: var(--ui-control-height-lg);
116
138
  }
117
139
 
118
140
  /* Disabled */
@@ -127,7 +149,7 @@
127
149
  display: inline-block;
128
150
  width: 1em;
129
151
  height: 1em;
130
- border: 1.5px solid currentColor;
152
+ border: var(--ui-border-width-thick) solid currentColor;
131
153
  border-top-color: transparent;
132
154
  border-radius: var(--ui-radius-full);
133
155
  animation: atl-spin 0.7s linear infinite;
@@ -1,3 +1,23 @@
1
+ /* Geometry contract: every size this component states is a border-box size.
2
+ * Declared with the component rather than as a global reset, so it ships in the
3
+ * same file as the sizes it governs and no consuming app has to supply one.
4
+ * Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
5
+ * See ADR-0043. */
6
+ :is(
7
+ .atl-card,
8
+ .atl-card-content,
9
+ .atl-card-footer,
10
+ .atl-card-header
11
+ ),
12
+ :is(
13
+ .atl-card,
14
+ .atl-card-content,
15
+ .atl-card-footer,
16
+ .atl-card-header
17
+ ) * {
18
+ box-sizing: border-box;
19
+ }
20
+
1
21
  .atl-card {
2
22
  display: block;
3
23
  border-radius: var(--ui-radius-xl);
@@ -9,11 +29,11 @@
9
29
  * outlined or flat. Cards rest on the page; they don't float off it. */
10
30
  .atl-card.variant-elevated {
11
31
  box-shadow: var(--ui-shadow-sm);
12
- border: 1px solid var(--ui-color-border);
32
+ border: var(--ui-border-width) solid var(--ui-color-border);
13
33
  }
14
34
 
15
35
  .atl-card.variant-outlined {
16
- border: 1px solid var(--ui-color-border);
36
+ border: var(--ui-border-width) solid var(--ui-color-border);
17
37
  background-color: var(--ui-color-surface-raised);
18
38
  }
19
39
 
@@ -52,7 +72,7 @@
52
72
  font-size: var(--ui-font-size-lg);
53
73
  font-weight: var(--ui-font-weight-semibold);
54
74
  color: var(--ui-color-text);
55
- border-bottom: 1px solid var(--ui-color-border);
75
+ border-bottom: var(--ui-border-width) solid var(--ui-color-border);
56
76
  letter-spacing: var(--ui-letter-spacing-tight);
57
77
  }
58
78
 
@@ -66,5 +86,5 @@
66
86
  display: flex;
67
87
  align-items: center;
68
88
  gap: var(--ui-spacing-3);
69
- border-top: 1px solid var(--ui-color-border);
89
+ border-top: var(--ui-border-width) solid var(--ui-color-border);
70
90
  }