@gtivr4/a1-design-system-react 0.1.0 → 0.2.3

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 (108) hide show
  1. package/package.json +1 -1
  2. package/src/color-scheme.css +586 -24
  3. package/src/components/accordion/Accordion.jsx +80 -0
  4. package/src/components/accordion/accordion.css +118 -0
  5. package/src/components/banner/Banner.jsx +66 -0
  6. package/src/components/banner/banner.css +205 -0
  7. package/src/components/bleed/Bleed.jsx +27 -0
  8. package/src/components/bleed/bleed.css +5 -0
  9. package/src/components/blockquote/Blockquote.jsx +40 -0
  10. package/src/components/blockquote/blockquote.css +166 -0
  11. package/src/components/breadcrumb/Breadcrumb.jsx +82 -0
  12. package/src/components/breadcrumb/breadcrumb.css +133 -0
  13. package/src/components/button/button.css +42 -12
  14. package/src/components/button-container/ButtonContainer.jsx +20 -1
  15. package/src/components/button-container/button-container.css +19 -1
  16. package/src/components/calendar/Calendar.jsx +383 -0
  17. package/src/components/calendar/calendar.css +225 -0
  18. package/src/components/card/Card.jsx +50 -12
  19. package/src/components/card/card.css +178 -14
  20. package/src/components/checkbox-group/CheckboxGroup.jsx +120 -0
  21. package/src/components/checkbox-group/checkbox-group.css +304 -0
  22. package/src/components/cluster/Cluster.jsx +52 -0
  23. package/src/components/cluster/cluster.css +9 -0
  24. package/src/components/code/Code.jsx +135 -0
  25. package/src/components/code/code.css +60 -0
  26. package/src/components/data-table/DataTable.jsx +721 -0
  27. package/src/components/data-table/DataTableFilters.jsx +339 -0
  28. package/src/components/data-table/data-table-filters.css +259 -0
  29. package/src/components/data-table/data-table.css +425 -0
  30. package/src/components/dialog/Dialog.jsx +45 -2
  31. package/src/components/dialog/dialog.css +13 -4
  32. package/src/components/divider/Divider.jsx +64 -0
  33. package/src/components/divider/divider.css +170 -0
  34. package/src/components/field/CreditCardField.jsx +131 -0
  35. package/src/components/field/DateField.jsx +11 -0
  36. package/src/components/field/NumberField.jsx +11 -0
  37. package/src/components/field/PhoneField.jsx +107 -0
  38. package/src/components/field/SelectField.jsx +86 -0
  39. package/src/components/field/TextField.jsx +83 -0
  40. package/src/components/field/TextareaField.jsx +147 -0
  41. package/src/components/field/TimeField.jsx +11 -0
  42. package/src/components/field/ZipField.jsx +114 -0
  43. package/src/components/field/credit-card.css +30 -0
  44. package/src/components/field/field.css +380 -0
  45. package/src/components/field/textarea-field.css +185 -0
  46. package/src/components/field-row/FieldRow.jsx +23 -0
  47. package/src/components/field-row/field-row.css +51 -0
  48. package/src/components/fieldset/Fieldset.jsx +49 -0
  49. package/src/components/fieldset/fieldset.css +75 -0
  50. package/src/components/figure/Figure.jsx +63 -0
  51. package/src/components/figure/figure.css +97 -0
  52. package/src/components/grid/Grid.jsx +36 -2
  53. package/src/components/grid/grid.css +129 -4
  54. package/src/components/heading/Heading.jsx +41 -1
  55. package/src/components/heading/heading.css +65 -4
  56. package/src/components/icon/icon.css +1 -0
  57. package/src/components/icon-button/icon-button.css +1 -0
  58. package/src/components/inline/inline.css +51 -0
  59. package/src/components/inline-editable/InlineEditable.jsx +77 -0
  60. package/src/components/inline-editable/inline-editable.css +47 -0
  61. package/src/components/inset/Inset.jsx +27 -0
  62. package/src/components/inset/inset.css +6 -0
  63. package/src/components/labels/Labels.jsx +5 -5
  64. package/src/components/link/Link.jsx +2 -3
  65. package/src/components/link/link.css +30 -1
  66. package/src/components/list/List.jsx +92 -0
  67. package/src/components/list/list.css +178 -0
  68. package/src/components/menu/Menu.jsx +243 -10
  69. package/src/components/menu/menu.css +157 -17
  70. package/src/components/message/Message.jsx +25 -50
  71. package/src/components/message/message.css +50 -33
  72. package/src/components/notification/Notification.jsx +1 -1
  73. package/src/components/page-layout/PageLayout.jsx +16 -1
  74. package/src/components/page-layout/page-layout.css +97 -4
  75. package/src/components/page-nav/PageNav.jsx +110 -0
  76. package/src/components/page-nav/page-nav.css +167 -0
  77. package/src/components/paragraph/Paragraph.jsx +35 -2
  78. package/src/components/paragraph/paragraph.css +38 -1
  79. package/src/components/radio-group/RadioGroup.jsx +121 -0
  80. package/src/components/radio-group/radio-group.css +268 -0
  81. package/src/components/section/Section.jsx +108 -0
  82. package/src/components/section/section.css +280 -0
  83. package/src/components/segmented-control/SegmentedControl.jsx +4 -0
  84. package/src/components/segmented-control/segmented.css +13 -0
  85. package/src/components/side-nav/SideNav.jsx +29 -9
  86. package/src/components/side-nav/scrim.css +1 -1
  87. package/src/components/side-nav/side-nav.css +70 -32
  88. package/src/components/snackbar/Snackbar.jsx +56 -0
  89. package/src/components/snackbar/snackbar.css +113 -0
  90. package/src/components/spacer/Spacer.jsx +36 -0
  91. package/src/components/spacer/spacer.css +44 -0
  92. package/src/components/stack/Stack.jsx +100 -0
  93. package/src/components/stack/stack.css +37 -0
  94. package/src/components/switch/Switch.jsx +114 -0
  95. package/src/components/switch/switch.css +276 -0
  96. package/src/components/system-banner/SystemBanner.jsx +57 -0
  97. package/src/components/system-banner/system-banner.css +118 -0
  98. package/src/components/tabs/Tabs.jsx +96 -28
  99. package/src/components/tabs/tabs.css +352 -15
  100. package/src/components/token-select/TokenSelect.jsx +159 -0
  101. package/src/components/token-select/token-select.css +110 -0
  102. package/src/components/top-header/TopHeader.jsx +641 -0
  103. package/src/components/top-header/top-header.css +337 -0
  104. package/src/illustrations/ComponentThumbnails.jsx +227 -0
  105. package/src/index.js +41 -5
  106. package/src/themes.css +256 -5
  107. package/src/utilities/spacing.css +8 -0
  108. package/src/utilities/sr-only.css +16 -0
@@ -3,6 +3,16 @@
3
3
  grid-template-columns: repeat(var(--a1-grid-cols, 1), minmax(0, 1fr));
4
4
  }
5
5
 
6
+ .a1-grid--bento {
7
+ grid-auto-flow: dense;
8
+ grid-auto-rows: var(--a1-grid-auto-rows, minmax(120px, auto));
9
+ align-items: stretch;
10
+ }
11
+
12
+ .a1-grid--bento > .a1-grid-item {
13
+ min-height: 0;
14
+ }
15
+
6
16
  /* ── Static column-count modifiers ─────────────────────────────────────────── */
7
17
 
8
18
  .a1-grid--cols-1 { --a1-grid-cols: 1; }
@@ -26,7 +36,7 @@
26
36
  .a1-grid--xs-6 { --a1-grid-cols: 6; }
27
37
  .a1-grid--xs-12 { --a1-grid-cols: 12; }
28
38
 
29
- @media (min-width: 481px) {
39
+ @media (--bp-sm-up) {
30
40
  .a1-grid--sm-1 { --a1-grid-cols: 1; }
31
41
  .a1-grid--sm-2 { --a1-grid-cols: 2; }
32
42
  .a1-grid--sm-3 { --a1-grid-cols: 3; }
@@ -35,7 +45,7 @@
35
45
  .a1-grid--sm-12 { --a1-grid-cols: 12; }
36
46
  }
37
47
 
38
- @media (min-width: 641px) {
48
+ @media (--bp-md-up) {
39
49
  .a1-grid--md-1 { --a1-grid-cols: 1; }
40
50
  .a1-grid--md-2 { --a1-grid-cols: 2; }
41
51
  .a1-grid--md-3 { --a1-grid-cols: 3; }
@@ -44,7 +54,7 @@
44
54
  .a1-grid--md-12 { --a1-grid-cols: 12; }
45
55
  }
46
56
 
47
- @media (min-width: 1025px) {
57
+ @media (--bp-lg-up) {
48
58
  .a1-grid--lg-1 { --a1-grid-cols: 1; }
49
59
  .a1-grid--lg-2 { --a1-grid-cols: 2; }
50
60
  .a1-grid--lg-3 { --a1-grid-cols: 3; }
@@ -53,7 +63,7 @@
53
63
  .a1-grid--lg-12 { --a1-grid-cols: 12; }
54
64
  }
55
65
 
56
- @media (min-width: 1441px) {
66
+ @media (--bp-xl) {
57
67
  .a1-grid--xl-1 { --a1-grid-cols: 1; }
58
68
  .a1-grid--xl-2 { --a1-grid-cols: 2; }
59
69
  .a1-grid--xl-3 { --a1-grid-cols: 3; }
@@ -84,3 +94,118 @@
84
94
  .a1-grid-item--row-span-4 { grid-row: span 4; }
85
95
  .a1-grid-item--row-span-5 { grid-row: span 5; }
86
96
  .a1-grid-item--row-span-6 { grid-row: span 6; }
97
+
98
+ /* ── Responsive GridItem span classes ─────────────────────────────────────── */
99
+
100
+ .a1-grid-item--xs-span-1 { grid-column: span 1; }
101
+ .a1-grid-item--xs-span-2 { grid-column: span 2; }
102
+ .a1-grid-item--xs-span-3 { grid-column: span 3; }
103
+ .a1-grid-item--xs-span-4 { grid-column: span 4; }
104
+ .a1-grid-item--xs-span-5 { grid-column: span 5; }
105
+ .a1-grid-item--xs-span-6 { grid-column: span 6; }
106
+ .a1-grid-item--xs-span-7 { grid-column: span 7; }
107
+ .a1-grid-item--xs-span-8 { grid-column: span 8; }
108
+ .a1-grid-item--xs-span-9 { grid-column: span 9; }
109
+ .a1-grid-item--xs-span-10 { grid-column: span 10; }
110
+ .a1-grid-item--xs-span-11 { grid-column: span 11; }
111
+ .a1-grid-item--xs-span-12 { grid-column: span 12; }
112
+ .a1-grid-item--xs-span-full { grid-column: 1 / -1; }
113
+
114
+ .a1-grid-item--xs-row-span-1 { grid-row: span 1; }
115
+ .a1-grid-item--xs-row-span-2 { grid-row: span 2; }
116
+ .a1-grid-item--xs-row-span-3 { grid-row: span 3; }
117
+ .a1-grid-item--xs-row-span-4 { grid-row: span 4; }
118
+ .a1-grid-item--xs-row-span-5 { grid-row: span 5; }
119
+ .a1-grid-item--xs-row-span-6 { grid-row: span 6; }
120
+
121
+ @media (--bp-sm-up) {
122
+ .a1-grid-item--sm-span-1 { grid-column: span 1; }
123
+ .a1-grid-item--sm-span-2 { grid-column: span 2; }
124
+ .a1-grid-item--sm-span-3 { grid-column: span 3; }
125
+ .a1-grid-item--sm-span-4 { grid-column: span 4; }
126
+ .a1-grid-item--sm-span-5 { grid-column: span 5; }
127
+ .a1-grid-item--sm-span-6 { grid-column: span 6; }
128
+ .a1-grid-item--sm-span-7 { grid-column: span 7; }
129
+ .a1-grid-item--sm-span-8 { grid-column: span 8; }
130
+ .a1-grid-item--sm-span-9 { grid-column: span 9; }
131
+ .a1-grid-item--sm-span-10 { grid-column: span 10; }
132
+ .a1-grid-item--sm-span-11 { grid-column: span 11; }
133
+ .a1-grid-item--sm-span-12 { grid-column: span 12; }
134
+ .a1-grid-item--sm-span-full { grid-column: 1 / -1; }
135
+
136
+ .a1-grid-item--sm-row-span-1 { grid-row: span 1; }
137
+ .a1-grid-item--sm-row-span-2 { grid-row: span 2; }
138
+ .a1-grid-item--sm-row-span-3 { grid-row: span 3; }
139
+ .a1-grid-item--sm-row-span-4 { grid-row: span 4; }
140
+ .a1-grid-item--sm-row-span-5 { grid-row: span 5; }
141
+ .a1-grid-item--sm-row-span-6 { grid-row: span 6; }
142
+ }
143
+
144
+ @media (--bp-md-up) {
145
+ .a1-grid-item--md-span-1 { grid-column: span 1; }
146
+ .a1-grid-item--md-span-2 { grid-column: span 2; }
147
+ .a1-grid-item--md-span-3 { grid-column: span 3; }
148
+ .a1-grid-item--md-span-4 { grid-column: span 4; }
149
+ .a1-grid-item--md-span-5 { grid-column: span 5; }
150
+ .a1-grid-item--md-span-6 { grid-column: span 6; }
151
+ .a1-grid-item--md-span-7 { grid-column: span 7; }
152
+ .a1-grid-item--md-span-8 { grid-column: span 8; }
153
+ .a1-grid-item--md-span-9 { grid-column: span 9; }
154
+ .a1-grid-item--md-span-10 { grid-column: span 10; }
155
+ .a1-grid-item--md-span-11 { grid-column: span 11; }
156
+ .a1-grid-item--md-span-12 { grid-column: span 12; }
157
+ .a1-grid-item--md-span-full { grid-column: 1 / -1; }
158
+
159
+ .a1-grid-item--md-row-span-1 { grid-row: span 1; }
160
+ .a1-grid-item--md-row-span-2 { grid-row: span 2; }
161
+ .a1-grid-item--md-row-span-3 { grid-row: span 3; }
162
+ .a1-grid-item--md-row-span-4 { grid-row: span 4; }
163
+ .a1-grid-item--md-row-span-5 { grid-row: span 5; }
164
+ .a1-grid-item--md-row-span-6 { grid-row: span 6; }
165
+ }
166
+
167
+ @media (--bp-lg-up) {
168
+ .a1-grid-item--lg-span-1 { grid-column: span 1; }
169
+ .a1-grid-item--lg-span-2 { grid-column: span 2; }
170
+ .a1-grid-item--lg-span-3 { grid-column: span 3; }
171
+ .a1-grid-item--lg-span-4 { grid-column: span 4; }
172
+ .a1-grid-item--lg-span-5 { grid-column: span 5; }
173
+ .a1-grid-item--lg-span-6 { grid-column: span 6; }
174
+ .a1-grid-item--lg-span-7 { grid-column: span 7; }
175
+ .a1-grid-item--lg-span-8 { grid-column: span 8; }
176
+ .a1-grid-item--lg-span-9 { grid-column: span 9; }
177
+ .a1-grid-item--lg-span-10 { grid-column: span 10; }
178
+ .a1-grid-item--lg-span-11 { grid-column: span 11; }
179
+ .a1-grid-item--lg-span-12 { grid-column: span 12; }
180
+ .a1-grid-item--lg-span-full { grid-column: 1 / -1; }
181
+
182
+ .a1-grid-item--lg-row-span-1 { grid-row: span 1; }
183
+ .a1-grid-item--lg-row-span-2 { grid-row: span 2; }
184
+ .a1-grid-item--lg-row-span-3 { grid-row: span 3; }
185
+ .a1-grid-item--lg-row-span-4 { grid-row: span 4; }
186
+ .a1-grid-item--lg-row-span-5 { grid-row: span 5; }
187
+ .a1-grid-item--lg-row-span-6 { grid-row: span 6; }
188
+ }
189
+
190
+ @media (--bp-xl) {
191
+ .a1-grid-item--xl-span-1 { grid-column: span 1; }
192
+ .a1-grid-item--xl-span-2 { grid-column: span 2; }
193
+ .a1-grid-item--xl-span-3 { grid-column: span 3; }
194
+ .a1-grid-item--xl-span-4 { grid-column: span 4; }
195
+ .a1-grid-item--xl-span-5 { grid-column: span 5; }
196
+ .a1-grid-item--xl-span-6 { grid-column: span 6; }
197
+ .a1-grid-item--xl-span-7 { grid-column: span 7; }
198
+ .a1-grid-item--xl-span-8 { grid-column: span 8; }
199
+ .a1-grid-item--xl-span-9 { grid-column: span 9; }
200
+ .a1-grid-item--xl-span-10 { grid-column: span 10; }
201
+ .a1-grid-item--xl-span-11 { grid-column: span 11; }
202
+ .a1-grid-item--xl-span-12 { grid-column: span 12; }
203
+ .a1-grid-item--xl-span-full { grid-column: 1 / -1; }
204
+
205
+ .a1-grid-item--xl-row-span-1 { grid-row: span 1; }
206
+ .a1-grid-item--xl-row-span-2 { grid-row: span 2; }
207
+ .a1-grid-item--xl-row-span-3 { grid-row: span 3; }
208
+ .a1-grid-item--xl-row-span-4 { grid-row: span 4; }
209
+ .a1-grid-item--xl-row-span-5 { grid-row: span 5; }
210
+ .a1-grid-item--xl-row-span-6 { grid-row: span 6; }
211
+ }
@@ -1,10 +1,13 @@
1
1
  import "./heading.css";
2
2
 
3
- const headingSizes = ["xl", "lg", "md", "sm", "xs"];
3
+ const headingSizes = ["xxl", "xl", "lg", "md", "sm", "xs"];
4
4
  const displaySizes = ["sm", "md", "lg", "xl", "xxl", "jumbo", "xJumbo"];
5
5
  const colors = ["default", "muted", "accent"];
6
+ const margins = ["sm", "md", "lg"];
6
7
  const levels = ["h1", "h2", "h3", "h4", "h5", "h6"];
7
8
  const breakpoints = ["xs", "sm", "md", "lg", "xl"];
9
+ const textWraps = ["balance"];
10
+ const aligns = ["left", "center", "right"];
8
11
 
9
12
  const levelDefaults = { h1: "xl", h2: "lg", h3: "md", h4: "sm", h5: "xs", h6: "xs" };
10
13
 
@@ -40,6 +43,9 @@ export function Heading({
40
43
  type = "heading",
41
44
  size,
42
45
  color = "default",
46
+ margin,
47
+ textWrap,
48
+ align,
43
49
  className = "",
44
50
  style,
45
51
  ...props
@@ -50,6 +56,9 @@ export function Heading({
50
56
  const defaultSize = isDisplay ? "md" : (levelDefaults[resolvedAs] ?? "md");
51
57
  const resolvedSize = resolveSize(size, validSizes, defaultSize);
52
58
  const resolvedColor = colors.includes(color) ? color : "default";
59
+ const resolvedMargin = margins.includes(margin) ? margin : null;
60
+ const resolvedTextWrap = textWraps.includes(textWrap) ? textWrap : null;
61
+ const resolvedAlign = aligns.includes(align) ? align : null;
53
62
  const responsiveSizeStyle = getResponsiveSizeStyle(size, type, validSizes);
54
63
  const resolvedStyle = Object.keys(responsiveSizeStyle).length
55
64
  ? { ...responsiveSizeStyle, ...style }
@@ -60,6 +69,9 @@ export function Heading({
60
69
  `a1-heading--${type}`,
61
70
  `a1-heading--${type}-${resolvedSize}`,
62
71
  resolvedColor !== "default" && `a1-heading--${resolvedColor}`,
72
+ resolvedMargin && `a1-heading--margin-${resolvedMargin}`,
73
+ resolvedTextWrap && `a1-heading--wrap-${resolvedTextWrap}`,
74
+ resolvedAlign && `a1-heading--align-${resolvedAlign}`,
63
75
  className
64
76
  ]
65
77
  .filter(Boolean)
@@ -67,3 +79,31 @@ export function Heading({
67
79
 
68
80
  return <Component className={classes} style={resolvedStyle} {...props} />;
69
81
  }
82
+
83
+ export function HeadingMark({
84
+ children,
85
+ variant = "highlight",
86
+ underlineStyle = "swoop",
87
+ className = "",
88
+ ...props
89
+ }) {
90
+ const resolvedVariant = variant === "underline" ? "underline" : "highlight";
91
+ const resolvedUnderlineStyle = ["swoop", "wave", "sketch"].includes(underlineStyle)
92
+ ? underlineStyle
93
+ : "swoop";
94
+
95
+ const classes = [
96
+ "a1-heading-mark",
97
+ `a1-heading-mark--${resolvedVariant}`,
98
+ resolvedVariant === "underline" && `a1-heading-mark--underline-${resolvedUnderlineStyle}`,
99
+ className,
100
+ ]
101
+ .filter(Boolean)
102
+ .join(" ");
103
+
104
+ return (
105
+ <span className={classes} {...props}>
106
+ {children}
107
+ </span>
108
+ );
109
+ }
@@ -7,13 +7,13 @@
7
7
  color: var(--a1-heading-color, var(--semantic-color-text-default));
8
8
  }
9
9
 
10
- @media (min-width: 481px) {
10
+ @media (--bp-sm-up) {
11
11
  .a1-heading {
12
12
  --a1-heading-responsive-size: var(--a1-heading-size-sm, var(--a1-heading-size));
13
13
  }
14
14
  }
15
15
 
16
- @media (min-width: 641px) {
16
+ @media (--bp-md-up) {
17
17
  .a1-heading {
18
18
  --a1-heading-responsive-size: var(
19
19
  --a1-heading-size-md,
@@ -22,7 +22,7 @@
22
22
  }
23
23
  }
24
24
 
25
- @media (min-width: 1025px) {
25
+ @media (--bp-lg-up) {
26
26
  .a1-heading {
27
27
  --a1-heading-responsive-size: var(
28
28
  --a1-heading-size-lg,
@@ -31,7 +31,7 @@
31
31
  }
32
32
  }
33
33
 
34
- @media (min-width: 1441px) {
34
+ @media (--bp-xl) {
35
35
  .a1-heading {
36
36
  --a1-heading-responsive-size: var(
37
37
  --a1-heading-size-xl,
@@ -56,6 +56,7 @@
56
56
  }
57
57
 
58
58
  /* Heading sizes */
59
+ .a1-heading--heading-xxl { --a1-heading-size: var(--semantic-font-size-heading-xxl); }
59
60
  .a1-heading--heading-xl { --a1-heading-size: var(--semantic-font-size-heading-xl); }
60
61
  .a1-heading--heading-lg { --a1-heading-size: var(--semantic-font-size-heading-lg); }
61
62
  .a1-heading--heading-md { --a1-heading-size: var(--semantic-font-size-heading-md); }
@@ -74,3 +75,63 @@
74
75
  /* Color modifiers */
75
76
  .a1-heading--muted { --a1-heading-color: var(--semantic-color-text-muted); }
76
77
  .a1-heading--accent { --a1-heading-color: var(--semantic-color-text-accent); }
78
+
79
+ /* Margin modifiers — em units scale with the heading's own font size */
80
+ .a1-heading--margin-sm { margin-bottom: 0.25em; }
81
+ .a1-heading--margin-md { margin-bottom: 0.5em; }
82
+ .a1-heading--margin-lg { margin-bottom: 1em; }
83
+
84
+ /* Text wrap */
85
+ .a1-heading--wrap-balance { text-wrap: balance; }
86
+
87
+ /* Alignment */
88
+ .a1-heading--align-left { text-align: start; }
89
+ .a1-heading--align-center { text-align: center; }
90
+ .a1-heading--align-right { text-align: end; }
91
+
92
+ /* Expressive marks */
93
+ .a1-heading-mark {
94
+ display: inline;
95
+ position: relative;
96
+ color: inherit;
97
+ box-decoration-break: clone;
98
+ -webkit-box-decoration-break: clone;
99
+ }
100
+
101
+ .a1-heading-mark--highlight {
102
+ padding: var(--component-heading-mark-highlight-padding-block) var(--component-heading-mark-highlight-padding-inline);
103
+ color: var(--component-heading-mark-highlight-foreground-color);
104
+ font-weight: var(--component-heading-mark-highlight-font-weight);
105
+ background: var(--component-heading-mark-highlight-background-color);
106
+ box-shadow: var(--component-heading-mark-highlight-shadow);
107
+ }
108
+
109
+ .a1-heading-mark--underline {
110
+ --a1-heading-mark-underline-mask: url("data:image/svg+xml,%3Csvg width='480' height='72' viewBox='0 0 480 72' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 44C68 33 127 39 188 38C272 36 349 23 472 34' stroke='black' stroke-width='40' stroke-linecap='round'/%3E%3C/svg%3E");
111
+ z-index: 0;
112
+ }
113
+
114
+ .a1-heading-mark--underline::after {
115
+ content: "";
116
+ position: absolute;
117
+ left: -0.03em;
118
+ right: -0.03em;
119
+ bottom: var(--component-heading-mark-underline-offset);
120
+ z-index: -1;
121
+ height: var(--component-heading-mark-underline-height);
122
+ background: var(--component-heading-mark-underline-color);
123
+ mask-image: var(--a1-heading-mark-underline-mask);
124
+ mask-repeat: no-repeat;
125
+ mask-size: 100% 100%;
126
+ -webkit-mask-image: var(--a1-heading-mark-underline-mask);
127
+ -webkit-mask-repeat: no-repeat;
128
+ -webkit-mask-size: 100% 100%;
129
+ }
130
+
131
+ .a1-heading-mark--underline-wave {
132
+ --a1-heading-mark-underline-mask: url("data:image/svg+xml,%3Csvg width='480' height='72' viewBox='0 0 480 72' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 40C38 19 64 58 94 38C124 18 150 57 180 38C211 18 237 58 268 38C299 18 325 57 356 38C387 19 416 56 472 36' stroke='black' stroke-width='32' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
133
+ }
134
+
135
+ .a1-heading-mark--underline-sketch {
136
+ --a1-heading-mark-underline-mask: url("data:image/svg+xml,%3Csvg width='480' height='72' viewBox='0 0 480 72' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 43C72 38 134 31 194 36C273 43 351 31 472 39' stroke='black' stroke-width='28' stroke-linecap='round'/%3E%3Cpath d='M15 52C85 43 137 48 213 44C293 40 372 46 463 31' stroke='black' stroke-width='16' stroke-linecap='round' opacity='.76'/%3E%3C/svg%3E");
137
+ }
@@ -2,6 +2,7 @@
2
2
  font-size: inherit;
3
3
  line-height: 1;
4
4
  user-select: none;
5
+ font-family: var(--a1-icon-font-family, 'Material Symbols Outlined');
5
6
  font-variation-settings:
6
7
  "FILL" var(--a1-icon-fill, 0),
7
8
  "wght" var(--a1-icon-weight, var(--base-font-weight-regular)),
@@ -3,6 +3,7 @@
3
3
  ═══════════════════════════════════════════════════════════════════════════ */
4
4
 
5
5
  .a1-icon-button {
6
+ --a1-icon-weight: 500;
6
7
  display: inline-flex;
7
8
  align-items: center;
8
9
  justify-content: center;
@@ -0,0 +1,51 @@
1
+ del {
2
+ color: var(--semantic-color-text-muted);
3
+ }
4
+
5
+ cite {
6
+ background: var(--semantic-color-surface-raised);
7
+ padding: var(--component-inline-padding-block) var(--component-inline-padding-inline);
8
+ border-radius: var(--component-inline-border-radius);
9
+ font-style: italic;
10
+ }
11
+
12
+ code {
13
+ font-family: var(--component-inline-font-family-mono);
14
+ background: var(--semantic-color-surface-raised);
15
+ padding: var(--component-inline-padding-block) var(--component-inline-padding-inline);
16
+ border-radius: var(--component-inline-border-radius);
17
+ font-size: var(--component-inline-code-font-size);
18
+ }
19
+
20
+ kbd {
21
+ font-family: var(--component-inline-font-family-mono);
22
+ background: var(--semantic-color-surface-raised);
23
+ padding: var(--component-inline-padding-block) var(--component-inline-kbd-padding-inline);
24
+ border-radius: var(--component-inline-border-radius);
25
+ border: var(--base-spacing-1) solid var(--semantic-color-border-subtle);
26
+ font-size: var(--component-inline-code-font-size);
27
+ }
28
+
29
+ var {
30
+ font-style: italic;
31
+ font-weight: bold;
32
+ }
33
+
34
+ time {
35
+ font-weight: var(--component-inline-emphasis-font-weight);
36
+ }
37
+
38
+ q {
39
+ font-style: italic;
40
+ font-weight: var(--component-inline-emphasis-font-weight);
41
+ }
42
+
43
+ /* ── Custom inline utilities ─────────────────────────────────────────────────── */
44
+
45
+ .a1-muted {
46
+ color: var(--semantic-color-text-muted);
47
+ }
48
+
49
+ .a1-accent {
50
+ color: var(--semantic-color-text-accent);
51
+ }
@@ -0,0 +1,77 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import "./inline-editable.css";
3
+
4
+ export function InlineEditable({
5
+ value,
6
+ onChange,
7
+ multiline = false,
8
+ disabled = false,
9
+ placeholder,
10
+ className = "",
11
+ inputClassName = "",
12
+ children,
13
+ ...props
14
+ }) {
15
+ const [editing, setEditing] = useState(false);
16
+ const ref = useRef(null);
17
+
18
+ useEffect(() => {
19
+ if (editing && ref.current) {
20
+ ref.current.focus();
21
+ ref.current.select?.();
22
+ }
23
+ }, [editing]);
24
+
25
+ function activate() {
26
+ if (!disabled) setEditing(true);
27
+ }
28
+
29
+ function deactivate() {
30
+ setEditing(false);
31
+ }
32
+
33
+ const inputClasses = ["a1-inline-editable__input", inputClassName].filter(Boolean).join(" ");
34
+
35
+ if (editing) {
36
+ return multiline ? (
37
+ <textarea
38
+ ref={ref}
39
+ className={inputClasses}
40
+ value={value}
41
+ onChange={(e) => onChange(e.target.value)}
42
+ onBlur={deactivate}
43
+ onKeyDown={(e) => { if (e.key === "Escape") deactivate(); }}
44
+ />
45
+ ) : (
46
+ <input
47
+ ref={ref}
48
+ type="text"
49
+ className={inputClasses}
50
+ value={value}
51
+ onChange={(e) => onChange(e.target.value)}
52
+ onBlur={deactivate}
53
+ onKeyDown={(e) => { if (e.key === "Enter" || e.key === "Escape") deactivate(); }}
54
+ />
55
+ );
56
+ }
57
+
58
+ const wrapperClasses = [
59
+ "a1-inline-editable",
60
+ disabled && "a1-inline-editable--disabled",
61
+ className,
62
+ ].filter(Boolean).join(" ");
63
+
64
+ return (
65
+ <div
66
+ className={wrapperClasses}
67
+ onClick={activate}
68
+ onKeyDown={(e) => { if (e.key === "Enter") activate(); }}
69
+ tabIndex={disabled ? undefined : 0}
70
+ role={disabled ? undefined : "button"}
71
+ aria-label={props["aria-label"] ?? "Click to edit"}
72
+ {...props}
73
+ >
74
+ {children ?? (placeholder && <span className="a1-inline-editable__placeholder">{placeholder}</span>)}
75
+ </div>
76
+ );
77
+ }
@@ -0,0 +1,47 @@
1
+ .a1-inline-editable {
2
+ cursor: text;
3
+ display: block;
4
+ border-radius: var(--base-border-radius-sm);
5
+ outline: 1px dashed transparent;
6
+ outline-offset: 2px;
7
+ transition: outline-color 0.15s;
8
+ }
9
+
10
+ .a1-inline-editable:hover {
11
+ outline-color: var(--semantic-color-border-default);
12
+ }
13
+
14
+ .a1-inline-editable:focus-visible {
15
+ outline: 2px solid var(--semantic-color-border-strong);
16
+ outline-offset: 2px;
17
+ }
18
+
19
+ .a1-inline-editable--disabled {
20
+ cursor: default;
21
+ }
22
+
23
+ .a1-inline-editable__placeholder {
24
+ color: var(--semantic-color-text-muted);
25
+ opacity: 0.7;
26
+ }
27
+
28
+ .a1-inline-editable__input {
29
+ display: block;
30
+ width: 100%;
31
+ min-height: 2em;
32
+ background: var(--semantic-color-surface-page);
33
+ border: 1px solid var(--semantic-color-border-strong);
34
+ border-radius: var(--base-border-radius-sm);
35
+ padding: var(--base-spacing-4) var(--base-spacing-8);
36
+ font: inherit;
37
+ color: var(--semantic-color-text-default);
38
+ resize: vertical;
39
+ outline: none;
40
+ box-sizing: border-box;
41
+ }
42
+
43
+ .a1-inline-editable__input:focus {
44
+ border-color: var(--semantic-color-interactive-default);
45
+ outline: 2px solid var(--semantic-color-interactive-default);
46
+ outline-offset: -1px;
47
+ }
@@ -0,0 +1,27 @@
1
+ import "./inset.css";
2
+ import { resolveSpacing } from "../structure-utils.js";
3
+
4
+ export function Inset({
5
+ as: Component = "div",
6
+ space = 16,
7
+ block,
8
+ inline,
9
+ className = "",
10
+ children,
11
+ ...props
12
+ }) {
13
+ const blockValue = resolveSpacing(block) ?? resolveSpacing(space);
14
+ const inlineValue = resolveSpacing(inline) ?? resolveSpacing(space);
15
+
16
+ const style = {
17
+ "--a1-inset-block": blockValue,
18
+ "--a1-inset-inline": inlineValue,
19
+ ...props.style,
20
+ };
21
+
22
+ return (
23
+ <Component className={["a1-inset", className].filter(Boolean).join(" ")} style={style} {...props}>
24
+ {children}
25
+ </Component>
26
+ );
27
+ }
@@ -0,0 +1,6 @@
1
+ .a1-inset {
2
+ box-sizing: border-box;
3
+ padding-block: var(--a1-inset-block, var(--base-spacing-16));
4
+ padding-inline: var(--a1-inset-inline, var(--base-spacing-16));
5
+ min-width: 0;
6
+ }
@@ -10,20 +10,20 @@ export function LabelsProvider({ locale = null, brand = null, labels, children }
10
10
  );
11
11
  }
12
12
 
13
- export function useLabel(key) {
13
+ export function useLabel(key, defaultValue) {
14
14
  const { locale, brand, labels } = useContext(LabelsContext);
15
- if (!labels) return key;
15
+ if (!labels) return defaultValue ?? key;
16
16
 
17
17
  const parts = key.split(".");
18
18
  let node = labels?.label;
19
19
  for (const part of parts) {
20
- if (node == null || typeof node !== "object") return key;
20
+ if (node == null || typeof node !== "object") return defaultValue ?? key;
21
21
  node = node[part];
22
22
  }
23
- if (node == null) return key;
23
+ if (node == null) return defaultValue ?? key;
24
24
 
25
25
  // Resolution order: locale > brand > default
26
26
  if (locale && node.locale?.[locale] != null) return node.locale[locale];
27
27
  if (brand && node.brand?.[brand] != null) return node.brand[brand];
28
- return node.$value ?? key;
28
+ return node.$value ?? defaultValue ?? key;
29
29
  }
@@ -6,7 +6,6 @@ const weights = ["normal", "medium", "semibold", "bold"];
6
6
  const iconPositions = ["start", "end"];
7
7
 
8
8
  export function Link({
9
- as: Component = "a",
10
9
  size,
11
10
  weight,
12
11
  icon,
@@ -32,10 +31,10 @@ export function Link({
32
31
  const iconEl = icon ? <Icon name={icon} className="a1-link__icon" /> : null;
33
32
 
34
33
  return (
35
- <Component className={classes} {...props}>
34
+ <a className={classes} {...props}>
36
35
  {resolvedPosition === "start" && iconEl}
37
36
  <span className="a1-link__text">{children}</span>
38
37
  {resolvedPosition === "end" && iconEl}
39
- </Component>
38
+ </a>
40
39
  );
41
40
  }
@@ -10,11 +10,40 @@
10
10
  .a1-link:active { color: var(--component-link-color-pressed); }
11
11
 
12
12
  .a1-link:focus-visible {
13
- outline: var(--component-link-focus-ring-width) solid var(--component-link-color);
13
+ outline: var(--component-link-focus-ring-width) solid currentColor;
14
14
  outline-offset: var(--component-link-focus-ring-offset);
15
15
  border-radius: var(--component-link-focus-ring-radius);
16
16
  }
17
17
 
18
+ /* Dark mode and inverse — bright light blue for contrast on dark backgrounds */
19
+ .a1-theme-dark .a1-link,
20
+ .a1-inverse .a1-link {
21
+ color: var(--base-color-info-100);
22
+ }
23
+
24
+ .a1-theme-dark .a1-link:hover,
25
+ .a1-inverse .a1-link:hover {
26
+ color: var(--base-color-info-50);
27
+ }
28
+
29
+ .a1-theme-dark .a1-link:active,
30
+ .a1-inverse .a1-link:active {
31
+ color: var(--base-color-info-200);
32
+ }
33
+
34
+ /* Dark on inverse restores light-mode values */
35
+ .a1-theme-dark .a1-inverse .a1-link {
36
+ color: var(--component-link-color);
37
+ }
38
+
39
+ .a1-theme-dark .a1-inverse .a1-link:hover {
40
+ color: var(--component-link-color-hover);
41
+ }
42
+
43
+ .a1-theme-dark .a1-inverse .a1-link:active {
44
+ color: var(--component-link-color-pressed);
45
+ }
46
+
18
47
  .a1-link__text {
19
48
  text-decoration: underline;
20
49
  text-decoration-color: currentColor;