@hattisar/design-tokens 0.3.9 → 0.3.11
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.
- package/package.json +1 -1
- package/tokens.css +119 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hattisar/design-tokens",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.11",
|
|
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
|
@@ -109,6 +109,25 @@
|
|
|
109
109
|
--color-brand-active: color-mix(in srgb, var(--color-brand) 70%, black);
|
|
110
110
|
--color-brand-text: #ffffff;
|
|
111
111
|
|
|
112
|
+
/* The main call to action.
|
|
113
|
+
Asked for by hex: "main CTA color #4285f4". It is the one place in
|
|
114
|
+
this palette with a hue — greys carry structure, colour carries
|
|
115
|
+
status, and now one blue carries "this is the button you press".
|
|
116
|
+
--color-brand stays charcoal ink: it is the focus ring, the active
|
|
117
|
+
tab marker and the checkbox tick, and turning all of those blue is
|
|
118
|
+
a bigger change than a call-to-action colour.
|
|
119
|
+
|
|
120
|
+
White on #4285f4 measures 3.56:1, below the 4.5:1 this file
|
|
121
|
+
promises everywhere else. It is recorded as a deliberate exception
|
|
122
|
+
in check-contrast.mjs rather than quietly left out of it — the
|
|
123
|
+
nearest shade that passes is #1a73e8 at 4.51:1, visually the same
|
|
124
|
+
blue, if the ratio matters more than the exact hex. */
|
|
125
|
+
--color-cta: #4285f4;
|
|
126
|
+
--color-cta-hover: color-mix(in srgb, var(--color-cta) 88%, black);
|
|
127
|
+
--color-cta-active: color-mix(in srgb, var(--color-cta) 76%, black);
|
|
128
|
+
--color-cta-text: #ffffff;
|
|
129
|
+
|
|
130
|
+
|
|
112
131
|
/* Secondary button — bordered light-gray fill. Reuses
|
|
113
132
|
--color-surface-tint/--color-border-strong/--color-text-primary
|
|
114
133
|
rather than their own literal hex, so the secondary button always
|
|
@@ -404,6 +423,10 @@
|
|
|
404
423
|
--color-brand-hover: color-mix(in srgb, var(--color-brand) 90%, black);
|
|
405
424
|
--color-brand-active: color-mix(in srgb, var(--color-brand) 75%, black);
|
|
406
425
|
--color-brand-text: #09090b;
|
|
426
|
+
--color-cta: #4285f4;
|
|
427
|
+
--color-cta-hover: color-mix(in srgb, var(--color-cta) 88%, black);
|
|
428
|
+
--color-cta-active: color-mix(in srgb, var(--color-cta) 76%, black);
|
|
429
|
+
--color-cta-text: #ffffff;
|
|
407
430
|
|
|
408
431
|
--shadow-btn-primary: 0 1px 2px rgba(9, 9, 11, 0.12);
|
|
409
432
|
--shadow-btn-secondary: 0 1px 2px rgba(9, 9, 11, 0.05);
|
|
@@ -508,6 +531,10 @@
|
|
|
508
531
|
--color-brand-hover: color-mix(in srgb, var(--color-brand) 85%, black);
|
|
509
532
|
--color-brand-active: color-mix(in srgb, var(--color-brand) 70%, black);
|
|
510
533
|
--color-brand-text: #ffffff;
|
|
534
|
+
--color-cta: #4285f4;
|
|
535
|
+
--color-cta-hover: color-mix(in srgb, var(--color-cta) 88%, black);
|
|
536
|
+
--color-cta-active: color-mix(in srgb, var(--color-cta) 76%, black);
|
|
537
|
+
--color-cta-text: #ffffff;
|
|
511
538
|
|
|
512
539
|
--shadow-btn-primary: 0 1px 2px rgba(0, 0, 0, 0.4);
|
|
513
540
|
--shadow-btn-secondary: 0 1px 2px rgba(0, 0, 0, 0.3);
|
|
@@ -710,8 +737,10 @@ label[data-required]::after {
|
|
|
710
737
|
font-weight: var(--font-weight-regular);
|
|
711
738
|
}
|
|
712
739
|
|
|
713
|
-
/* Primary action —
|
|
714
|
-
|
|
740
|
+
/* Primary action — the call-to-action fill. Charcoal until it was
|
|
741
|
+
given a colour of its own; --color-brand still carries structure
|
|
742
|
+
(focus ring, active tab, checkbox tick) and is deliberately not
|
|
743
|
+
this. */
|
|
715
744
|
button {
|
|
716
745
|
font: inherit;
|
|
717
746
|
cursor: pointer;
|
|
@@ -720,8 +749,8 @@ button {
|
|
|
720
749
|
padding: 5px 10px;
|
|
721
750
|
font-size: var(--text-base);
|
|
722
751
|
font-weight: 400;
|
|
723
|
-
background: var(--color-
|
|
724
|
-
color: var(--color-
|
|
752
|
+
background: var(--color-cta);
|
|
753
|
+
color: var(--color-cta-text);
|
|
725
754
|
box-shadow: var(--shadow-btn-primary);
|
|
726
755
|
transition:
|
|
727
756
|
transform 0.05s ease,
|
|
@@ -730,11 +759,11 @@ button {
|
|
|
730
759
|
}
|
|
731
760
|
|
|
732
761
|
button:hover {
|
|
733
|
-
background: var(--color-
|
|
762
|
+
background: var(--color-cta-hover);
|
|
734
763
|
}
|
|
735
764
|
|
|
736
765
|
button:active {
|
|
737
|
-
background: var(--color-
|
|
766
|
+
background: var(--color-cta-active);
|
|
738
767
|
transform: scale(0.97);
|
|
739
768
|
}
|
|
740
769
|
|
|
@@ -979,6 +1008,90 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover {
|
|
|
979
1008
|
box-shadow spread follows the border-radius exactly, so it reads as
|
|
980
1009
|
one thickened edge — which fixes the original complaint without
|
|
981
1010
|
leaving keyboard users hunting for which field they are in. */
|
|
1011
|
+
/* A required field says so on its label, in the red this app already
|
|
1012
|
+
uses for things that are wrong or missing.
|
|
1013
|
+
Asked for: "use our existing red for required field title" — the
|
|
1014
|
+
same convention Zoho uses, where a required label is red and the
|
|
1015
|
+
optional ones are not.
|
|
1016
|
+
|
|
1017
|
+
Written as `:has()` rather than a prop on forty forms: the label
|
|
1018
|
+
already wraps its control, so the markup that says "required" is
|
|
1019
|
+
already there and nothing needs to be repeated. A field that becomes
|
|
1020
|
+
optional stops being red on its own, which a hand-maintained flag
|
|
1021
|
+
would not.
|
|
1022
|
+
|
|
1023
|
+
The control inside is put back to the normal ink — colour is
|
|
1024
|
+
inherited, and a red label would otherwise mean red typing in the
|
|
1025
|
+
box under it. */
|
|
1026
|
+
/*
|
|
1027
|
+
* Descendant, not direct child. A Combobox already renders a hidden
|
|
1028
|
+
* `<input required>` so that native form validation still works the
|
|
1029
|
+
* way the `<select required>` it replaced did — but it is nested
|
|
1030
|
+
* inside the container div, so `> :required` could not see it and only
|
|
1031
|
+
* the handful of plain `<input required>` fields turned red. Every
|
|
1032
|
+
* picker in the app is a Combobox underneath, so this is the
|
|
1033
|
+
* difference between one red label on a form and all of them.
|
|
1034
|
+
*/
|
|
1035
|
+
/*
|
|
1036
|
+
* And a star after the label text, the way Zoho marks a required
|
|
1037
|
+
* field.
|
|
1038
|
+
*
|
|
1039
|
+
* Harder than it looks, because the label's text is a bare text node:
|
|
1040
|
+
* `<label>First Name<input required></label>`. A plain `label::after`
|
|
1041
|
+
* renders after *everything* in the label — under the input, not
|
|
1042
|
+
* beside the words — and the only way to attach it to the text
|
|
1043
|
+
* directly would be to wrap that text in a span on every field of
|
|
1044
|
+
* every form.
|
|
1045
|
+
*
|
|
1046
|
+
* So the label becomes a wrapping flex row for required fields only,
|
|
1047
|
+
* and the three items are ordered explicitly: the text (order 0, an
|
|
1048
|
+
* anonymous flex item), the star (order 1), then the control, forced
|
|
1049
|
+
* onto the next line by a full-width basis. The result is the text and
|
|
1050
|
+
* its star on one line and the field under them — which is what the
|
|
1051
|
+
* label already looked like, with a star added and no markup touched.
|
|
1052
|
+
*/
|
|
1053
|
+
label:has(:required) {
|
|
1054
|
+
/*
|
|
1055
|
+
* !important because 212 labels in this app carry an inline
|
|
1056
|
+
* `style={{ display: "block" }}`, and an inline declaration beats
|
|
1057
|
+
* any stylesheet rule regardless of specificity. This is the case
|
|
1058
|
+
* the keyword exists for: overriding markup a stylesheet cannot
|
|
1059
|
+
* reach. Without it the star renders after the control on every one
|
|
1060
|
+
* of those labels instead of beside the words.
|
|
1061
|
+
*/
|
|
1062
|
+
display: flex !important;
|
|
1063
|
+
flex-wrap: wrap;
|
|
1064
|
+
align-items: baseline;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
label:has(:required) > * {
|
|
1068
|
+
order: 2;
|
|
1069
|
+
flex-basis: 100%;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
label:has(:required)::after {
|
|
1073
|
+
content: "*";
|
|
1074
|
+
order: 1;
|
|
1075
|
+
margin-left: 2px;
|
|
1076
|
+
color: var(--color-danger);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
label:has(:required) {
|
|
1080
|
+
color: var(--color-danger);
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
/*
|
|
1084
|
+
* The controls inside go back to the normal ink. Colour inherits, so
|
|
1085
|
+
* without this a red label means red typing in the box under it — and
|
|
1086
|
+
* on a Combobox, red text in the dropdown as well.
|
|
1087
|
+
*/
|
|
1088
|
+
label:has(:required) input,
|
|
1089
|
+
label:has(:required) select,
|
|
1090
|
+
label:has(:required) textarea,
|
|
1091
|
+
label:has(:required) .combobox-input {
|
|
1092
|
+
color: var(--color-text-primary);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
982
1095
|
input:focus-visible,
|
|
983
1096
|
select:focus-visible,
|
|
984
1097
|
textarea:focus-visible {
|