@hattisar/design-tokens 0.3.26 → 0.3.28

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 (2) hide show
  1. package/package.json +1 -1
  2. package/tokens.css +183 -26
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hattisar/design-tokens",
3
- "version": "0.3.26",
3
+ "version": "0.3.28",
4
4
  "description": "Shared design tokens (colors, type, radius, spacing, motion) and base primitives (reset, buttons, inputs, cards, modals, auth shell) for every Hattisar frontend.",
5
5
  "main": "tokens.css",
6
6
  "files": [
package/tokens.css CHANGED
@@ -138,8 +138,8 @@
138
138
  --color-secondary-fill: var(--color-background-card);
139
139
  --color-secondary-border: var(--color-border-strong);
140
140
  --color-secondary-text: var(--color-text-primary);
141
- --color-secondary-hover: color-mix(in srgb, var(--color-text-primary) 6%, var(--color-secondary-fill));
142
- --color-secondary-active: color-mix(in srgb, var(--color-text-primary) 12%, var(--color-secondary-fill));
141
+ --color-secondary-hover: color-mix(in srgb, var(--color-text-primary) 3%, var(--color-secondary-fill));
142
+ --color-secondary-active: color-mix(in srgb, var(--color-text-primary) 6%, var(--color-secondary-fill));
143
143
 
144
144
  /* Destructive button — irreversible actions only (delete, void). */
145
145
  --color-destructive-fill: #c70a24;
@@ -193,6 +193,24 @@
193
193
  --status-overdue-text: var(--color-danger);
194
194
  --status-overdue-bg: #feebec;
195
195
 
196
+ /* The badge palette: what a status pill is painted with, kept apart from
197
+ the --status-* accents above (those colour dashboard accents and row
198
+ bars). Quiet gray for anything healthy or finished, so a long column
199
+ of them stays calm; colour only where something is in progress or
200
+ needs a look. */
201
+ --badge-neutral-bg: rgba(0, 0, 0, 0.05);
202
+ --badge-neutral-text: #4a4a4a;
203
+ --badge-progress-bg: #8ce1f8;
204
+ --badge-progress-text: #01596f;
205
+ --badge-attention-bg: #ffe45c;
206
+ --badge-attention-text: #574100;
207
+ --badge-caution-bg: #ffc58a;
208
+ --badge-caution-text: #5c2f00;
209
+ --badge-critical-bg: #fed3d1;
210
+ --badge-critical-text: #8e0b21;
211
+ --badge-success-bg: #dcf5c9;
212
+ --badge-success-text: #214b03;
213
+
196
214
  /* Page-level warning/danger/success banners — distinct from the row
197
215
  badges above: a border plus a matching soft fill, no separate text
198
216
  color (banner text uses --color-text-primary as usual). Warning/
@@ -249,6 +267,28 @@
249
267
  --card-header-height: 36px;
250
268
  --card-header-control-height: 24px;
251
269
 
270
+ /* The signature widget card: a filled frame, a header band that shows the
271
+ frame's own fill, and a white body set into it. WidgetCard, the line-items
272
+ card, the form sections and the settings cards all read these, so the look
273
+ is changed here once and never restated per card. They are built from the
274
+ colour and radius tokens, so they follow the theme without a block of
275
+ their own. */
276
+ --widget-bg: var(--color-table-header);
277
+ --widget-border-width: 1px;
278
+ --widget-border-color: var(--color-border-strong);
279
+ --widget-radius: var(--radius-sm);
280
+ --widget-shadow: var(--shadow-sm);
281
+ --widget-header-height: var(--card-header-height);
282
+ --widget-header-padding: 6px var(--space-3);
283
+ --widget-title-size: var(--text-sm);
284
+ --widget-title-weight: var(--font-weight-medium);
285
+ --widget-body-bg: var(--color-background-card);
286
+ --widget-body-padding: var(--space-3) var(--space-4);
287
+ --widget-divider: var(--color-border);
288
+ /* The surface a sheet or label sits on in a preview: a shade off the card. */
289
+ --widget-canvas-bg: color-mix(in srgb, var(--color-text-primary) 5%, var(--color-background-card));
290
+ --widget-row-padding: var(--space-3) var(--space-4);
291
+
252
292
  /* Colours that must not follow the theme, named instead of repeated as
253
293
  hex. White on a saturated fill (an org tile, an integration logo)
254
294
  stays white in dark mode; the scrim dims the page behind a modal or
@@ -261,13 +301,13 @@
261
301
  --print-paper: #ffffff;
262
302
  --print-ink: #0f172a;
263
303
 
264
- /* The row a list page's summary tiles and search/filter toolbar share.
265
- 48px, not the 36px table-header/tab-strip row: those are dense
266
- header bands; this one holds a text field and a view switcher you
267
- click into, and at 36px the icon and text sat against the card edge
268
- and the gray column-header band right below ("search area look very
269
- tight"). One token so the tiles and the toolbar can't drift apart. */
270
- --toolbar-row-height: 48px;
304
+ /* The row a list page's search/filter toolbar sits in: the same 36px as
305
+ the table-header and tab-strip rows. It was 48px, once, after the
306
+ icon and text sat against the card edge at 36px ("search area look
307
+ very tight"); the bar has its own border and a margin below it now,
308
+ which is what that was missing, so the shorter row is back — asked
309
+ for directly, to match a compact admin search field. */
310
+ --toolbar-row-height: 36px;
271
311
  /* The pinned page header on a list page (title + actions), and what the
272
312
  table's column headers stick beneath. */
273
313
  --page-heading-height: 52px;
@@ -278,12 +318,21 @@
278
318
  --button-height: 28px;
279
319
  --button-radius: var(--radius-full);
280
320
  --button-padding-x: var(--space-3);
321
+ /* Not equal on purpose: the label's cap-height centre sits 0.75px above the
322
+ box's centre with equal padding, which reads as text riding high in the
323
+ pill. Three-quarters of a pixel off each side puts the ink in the middle. */
324
+ --button-padding-top: calc(var(--space-1) + 0.75px);
325
+ --button-padding-bottom: calc(var(--space-1) - 0.75px);
281
326
  --button-font-size: var(--text-sm);
282
327
  --button-font-weight: var(--font-weight-medium);
283
328
 
284
329
  /* The big rounded containers on a list page, after Shopify's Orders
285
330
  page: the KPI strip, the search bar and the table card all share it. */
286
331
  --list-card-radius: var(--radius-xl);
332
+ /* The outline of a list page's three containers (summary tiles, search
333
+ bar, table): the quiet row-divider grey, not the strong one, so the
334
+ frames read as surfaces rather than drawn boxes. */
335
+ --list-frame-border: var(--color-border);
287
336
  /* A table row under the cursor: a faint veil of the ink, deliberately
288
337
  lighter than the header band (--color-surface-tint) so the two never
289
338
  read as the same grey. */
@@ -295,7 +344,30 @@
295
344
  hairline of its own to read against the page. Primary is simply the
296
345
  bare `button` rule (--color-cta). */
297
346
  --button-secondary-bg: var(--color-secondary-fill);
298
- --button-secondary-shadow: var(--shadow-btn-secondary), 0 0 0 1px var(--color-border);
347
+ /* The press and hover motion every button shares: a long ease-out, which
348
+ reads as snappy because most of the change lands in the first moments. */
349
+ --ease-button: cubic-bezier(0.2, 0.8, 0, 1);
350
+ /* An icon-only button with no fill at rest (the edit pencil): a round tint of
351
+ the ink on hover, 8% like the reference's. */
352
+ --button-tertiary-hover-bg: color-mix(in srgb, var(--color-text-primary) 8%, transparent);
353
+ --duration-button: 0.4s;
354
+ --shadow-btn-primary:
355
+ 0 1px 0.5px -0.5px rgba(0, 0, 0, 0.13),
356
+ 0 1px 2px -0.5px rgba(0, 0, 0, 0.13),
357
+ 0 4px 6px -2px rgba(0, 0, 0, 0.13),
358
+ 0 2px 3px -1.5px rgba(0, 0, 0, 0.13),
359
+ inset 0 0 4px 1px var(--color-cta),
360
+ inset 0 0 4px 2px rgba(255, 255, 255, 0.1),
361
+ inset 0 0 12px -6px rgba(255, 255, 255, 0.75);
362
+ --shadow-btn-secondary: 0 1px 2px rgba(9, 9, 11, 0.05);
363
+ --button-primary-sheen:
364
+ radial-gradient(50% 50% at 50% 0%, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%),
365
+ radial-gradient(49.59% 37.11% at 50.41% 101.56%, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 66.46%);
366
+ --button-secondary-shadow:
367
+ 0 0 0 1px rgba(0, 0, 0, 0.07),
368
+ 0 2px 20px 0 rgba(0, 0, 0, 0.03),
369
+ 0 5px 20px 0 rgba(0, 0, 0, 0.03),
370
+ 0 8px 60px 0 rgba(0, 0, 0, 0.03);
299
371
 
300
372
  /* The picture picker (ImagePicker.tsx) behind an item image, the org
301
373
  logo and both user photos. Named so those four can't drift apart. */
@@ -483,7 +555,30 @@
483
555
  --sidebar-icon-size: 20px;
484
556
  --sidebar-control-height: 36px;
485
557
  --sidebar-item-height: 30px;
558
+ /* The sidebar's search field: a short, rounder pill on a lighter fill,
559
+ lifted by a faint inner highlight and a hairline edge so it reads as a
560
+ raised control on the dark rail rather than a flat patch. */
561
+ --sidebar-search-height: 30px;
562
+ --sidebar-search-radius: var(--radius-lg);
563
+ --sidebar-search-shadow:
564
+ inset 0 0 0 1px color-mix(in srgb, var(--sidebar-active-text) 2%, transparent),
565
+ inset 0 1px 1px 0 color-mix(in srgb, var(--sidebar-active-text) 6%, transparent),
566
+ inset 0 0 12px 1px color-mix(in srgb, var(--sidebar-active-text) 6%, transparent),
567
+ 0 1px 2px 0 rgba(0, 0, 0, 0.1),
568
+ 0 0 0 1px rgba(0, 0, 0, 0.1);
486
569
  --sidebar-item-weight: 450;
570
+ /* One row for all three rails (the main sidebar, Settings, Reports): the
571
+ same padding, icon-to-label gap, weight and active weight, so the same
572
+ row looks the same wherever it sits. A sub-item's text starts under its
573
+ parent's text: left padding + the icon + the gap. */
574
+ --sidebar-icon-inset: 6px;
575
+ --sidebar-row-padding: 5px 8px 5px var(--sidebar-icon-inset);
576
+ --sidebar-row-gap: var(--space-2);
577
+ /* The space between one row and the next, at every level, so a top-level
578
+ row and a sub-item sit the same distance from their neighbours. */
579
+ --sidebar-row-spacing: 6px;
580
+ --sidebar-sub-indent: calc(var(--sidebar-icon-inset) + var(--sidebar-icon-size) + var(--sidebar-row-gap));
581
+ --sidebar-active-weight: var(--font-weight-medium);
487
582
  --sidebar-badge-size: 22px;
488
583
  --sidebar-avatar-size: 28px;
489
584
  --popout-min-width: 180px;
@@ -496,7 +591,11 @@
496
591
  layout's own sidebar width, the same reason --header-height above
497
592
  moved too. */
498
593
  --sidebar-width: 220px;
499
- --sidebar-width-collapsed: 56px;
594
+ /* The collapsed rail is exactly the width of its icon column: the row's
595
+ icon inset, the icon, and the same inset again, inside the rail's own
596
+ padding — so an icon is in the same place whether the rail is open or
597
+ closed. */
598
+ --sidebar-width-collapsed: calc(2 * var(--space-2) + 2 * var(--sidebar-icon-inset) + var(--sidebar-icon-size));
500
599
  --sidebar-height: calc(100vh - var(--header-height));
501
600
 
502
601
  /* Two widths, because a page is one of two things.
@@ -612,8 +711,10 @@
612
711
  --color-cta-active: var(--color-brand-active);
613
712
  --color-cta-text: var(--color-brand-text);
614
713
 
615
- --shadow-btn-primary: 0 1px 2px rgba(9, 9, 11, 0.12);
616
- --shadow-btn-secondary: 0 1px 2px rgba(9, 9, 11, 0.05);
714
+ --shadow-btn-primary: 0 1px 2px rgba(0, 0, 0, 0.4);
715
+ --shadow-btn-secondary: 0 1px 2px rgba(0, 0, 0, 0.3);
716
+ --button-primary-sheen: none;
717
+ --button-secondary-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), 0 1px 2px rgba(0, 0, 0, 0.3);
617
718
 
618
719
  --color-secondary-fill: var(--color-surface-tint);
619
720
  --color-secondary-border: var(--color-border-strong);
@@ -653,6 +754,19 @@
653
754
  --status-overdue-text: var(--color-danger);
654
755
  --status-overdue-bg: #401d21;
655
756
 
757
+ --badge-neutral-bg: rgba(255, 255, 255, 0.08);
758
+ --badge-neutral-text: #d4d4d8;
759
+ --badge-progress-bg: #0f3341;
760
+ --badge-progress-text: #8ce1f8;
761
+ --badge-attention-bg: #4a3b00;
762
+ --badge-attention-text: #ffe45c;
763
+ --badge-caution-bg: #4d2c0a;
764
+ --badge-caution-text: #ffc58a;
765
+ --badge-critical-bg: #4d1218;
766
+ --badge-critical-text: #fda4a8;
767
+ --badge-success-bg: #1f3a0f;
768
+ --badge-success-text: #b3f782;
769
+
656
770
  --banner-warning-bg: #3a2907;
657
771
  --banner-warning-border: var(--color-warning);
658
772
  --banner-danger-bg: #4a1119;
@@ -721,14 +835,29 @@
721
835
  --color-cta-active: var(--color-brand-active);
722
836
  --color-cta-text: var(--color-brand-text);
723
837
 
724
- --shadow-btn-primary: 0 1px 2px rgba(0, 0, 0, 0.4);
725
- --shadow-btn-secondary: 0 1px 2px rgba(0, 0, 0, 0.3);
838
+ --shadow-btn-primary:
839
+ 0 1px 0.5px -0.5px rgba(0, 0, 0, 0.13),
840
+ 0 1px 2px -0.5px rgba(0, 0, 0, 0.13),
841
+ 0 4px 6px -2px rgba(0, 0, 0, 0.13),
842
+ 0 2px 3px -1.5px rgba(0, 0, 0, 0.13),
843
+ inset 0 0 4px 1px var(--color-cta),
844
+ inset 0 0 4px 2px rgba(255, 255, 255, 0.1),
845
+ inset 0 0 12px -6px rgba(255, 255, 255, 0.75);
846
+ --shadow-btn-secondary: 0 1px 2px rgba(9, 9, 11, 0.05);
847
+ --button-primary-sheen:
848
+ radial-gradient(50% 50% at 50% 0%, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%),
849
+ radial-gradient(49.59% 37.11% at 50.41% 101.56%, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 66.46%);
850
+ --button-secondary-shadow:
851
+ 0 0 0 1px rgba(0, 0, 0, 0.07),
852
+ 0 2px 20px 0 rgba(0, 0, 0, 0.03),
853
+ 0 5px 20px 0 rgba(0, 0, 0, 0.03),
854
+ 0 8px 60px 0 rgba(0, 0, 0, 0.03);
726
855
 
727
856
  --color-secondary-fill: var(--color-background-card);
728
857
  --color-secondary-border: var(--color-border-strong);
729
858
  --color-secondary-text: var(--color-text-primary);
730
- --color-secondary-hover: color-mix(in srgb, var(--color-text-primary) 6%, var(--color-secondary-fill));
731
- --color-secondary-active: color-mix(in srgb, var(--color-text-primary) 12%, var(--color-secondary-fill));
859
+ --color-secondary-hover: color-mix(in srgb, var(--color-text-primary) 3%, var(--color-secondary-fill));
860
+ --color-secondary-active: color-mix(in srgb, var(--color-text-primary) 6%, var(--color-secondary-fill));
732
861
 
733
862
  --color-destructive-fill: #c70a24;
734
863
  --color-destructive-hover: #a30a24;
@@ -761,6 +890,24 @@
761
890
  --status-overdue-text: var(--color-danger);
762
891
  --status-overdue-bg: #feebec;
763
892
 
893
+ /* The badge palette: what a status pill is painted with, kept apart from
894
+ the --status-* accents above (those colour dashboard accents and row
895
+ bars). Quiet gray for anything healthy or finished, so a long column
896
+ of them stays calm; colour only where something is in progress or
897
+ needs a look. */
898
+ --badge-neutral-bg: rgba(0, 0, 0, 0.05);
899
+ --badge-neutral-text: #4a4a4a;
900
+ --badge-progress-bg: #8ce1f8;
901
+ --badge-progress-text: #01596f;
902
+ --badge-attention-bg: #ffe45c;
903
+ --badge-attention-text: #574100;
904
+ --badge-caution-bg: #ffc58a;
905
+ --badge-caution-text: #5c2f00;
906
+ --badge-critical-bg: #fed3d1;
907
+ --badge-critical-text: #8e0b21;
908
+ --badge-success-bg: #dcf5c9;
909
+ --badge-success-text: #214b03;
910
+
764
911
  --banner-warning-bg: #fff3e6;
765
912
  --banner-warning-border: var(--color-warning);
766
913
  --banner-danger-bg: #fdeaed;
@@ -928,25 +1075,33 @@ button {
928
1075
  border: none;
929
1076
  border-radius: var(--button-radius);
930
1077
  min-height: var(--button-height);
931
- padding: var(--space-1) var(--button-padding-x);
1078
+ padding: var(--button-padding-top) var(--button-padding-x) var(--button-padding-bottom);
932
1079
  font-size: var(--button-font-size);
933
1080
  font-weight: var(--button-font-weight);
934
1081
  background: var(--color-cta);
1082
+ /* A soft light at the top edge and a fainter one at the bottom, the way
1083
+ the reference admin lifts its primary button off the page. Anything that
1084
+ sets its own `background:` shorthand clears this along with the colour. */
1085
+ background-image: var(--button-primary-sheen);
935
1086
  color: var(--color-cta-text);
936
1087
  box-shadow: var(--shadow-btn-primary);
937
1088
  transition:
938
- transform 0.05s ease,
939
- background 0.15s ease,
940
- box-shadow 0.15s ease;
1089
+ background-color var(--duration-button) var(--ease-button),
1090
+ box-shadow var(--duration-button) var(--ease-button),
1091
+ transform var(--duration-button) var(--ease-button);
941
1092
  }
942
1093
 
943
1094
  button:hover {
944
1095
  background: var(--color-cta-hover);
1096
+ background-image: var(--button-primary-sheen);
945
1097
  }
946
1098
 
1099
+ /* Pressed is a darker fill, not a shrink: the button stays the size it is,
1100
+ which is what made the old one feel busy. */
947
1101
  button:active {
948
1102
  background: var(--color-cta-active);
949
- transform: scale(0.97);
1103
+ background-image: var(--button-primary-sheen);
1104
+ transform: none;
950
1105
  }
951
1106
 
952
1107
  button:disabled {
@@ -991,7 +1146,7 @@ button:focus-visible {
991
1146
  border: none;
992
1147
  border-radius: var(--button-radius);
993
1148
  min-height: var(--button-height);
994
- padding: var(--space-1) var(--button-padding-x);
1149
+ padding: var(--button-padding-top) var(--button-padding-x) var(--button-padding-bottom);
995
1150
  font-size: var(--button-font-size);
996
1151
  font-weight: var(--button-font-weight);
997
1152
  background: var(--button-secondary-bg);
@@ -1028,7 +1183,7 @@ button:focus-visible {
1028
1183
  border: none;
1029
1184
  border-radius: var(--button-radius);
1030
1185
  min-height: var(--button-height);
1031
- padding: var(--space-1) var(--button-padding-x);
1186
+ padding: var(--button-padding-top) var(--button-padding-x) var(--button-padding-bottom);
1032
1187
  font-size: var(--button-font-size);
1033
1188
  font-weight: var(--button-font-weight);
1034
1189
  background: var(--color-destructive-fill);
@@ -1341,6 +1496,10 @@ select:disabled {
1341
1496
  input[type="checkbox"],
1342
1497
  input[type="radio"] {
1343
1498
  width: auto;
1499
+ /* No vertical margin: the field rule above gives every input a top margin,
1500
+ which on a checkbox or radio set beside its label pushes it below the
1501
+ text's centre. The sides keep the browser's own spacing. */
1502
+ margin-block: 0;
1344
1503
  accent-color: var(--color-brand);
1345
1504
  }
1346
1505
 
@@ -1466,8 +1625,6 @@ input[type="radio"] {
1466
1625
  display: block;
1467
1626
  font-size: var(--text-xs);
1468
1627
  font-weight: 400;
1469
- letter-spacing: 0.06em;
1470
- text-transform: uppercase;
1471
1628
  color: var(--color-text-muted);
1472
1629
  margin-bottom: 6px;
1473
1630
  }