@hattisar/design-tokens 0.3.22 → 0.3.23

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 +45 -61
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hattisar/design-tokens",
3
- "version": "0.3.22",
3
+ "version": "0.3.23",
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
@@ -261,6 +261,12 @@
261
261
  tight"). One token so the tiles and the toolbar can't drift apart. */
262
262
  --toolbar-row-height: 48px;
263
263
 
264
+ /* The picture picker (ImagePicker.tsx) behind an item image, the org
265
+ logo and both user photos. Named so those four can't drift apart. */
266
+ --image-picker-size: 96px;
267
+ --image-picker-border: 1px dashed var(--color-border);
268
+ --image-picker-overlay: color-mix(in srgb, var(--color-background-card) 55%, transparent);
269
+
264
270
  /* Depth, deliberately restrained. These were all `none`, which left
265
271
  every surface separated by border alone — correct, legible, and
266
272
  completely flat: a card, a dropdown and a modal all sat on the page
@@ -860,15 +866,11 @@ label {
860
866
  line-height: 1.4;
861
867
  }
862
868
 
863
- /* A required field says so once, here, rather than each form inventing
864
- its own asterisk-or-not. Marked on the label so it reads before the
865
- field rather than after it. */
866
- label[data-required]::after {
867
- content: "*";
868
- margin-left: 3px;
869
- color: var(--color-danger);
870
- font-weight: var(--font-weight-regular);
871
- }
869
+ /* No star. Asked for directly, 2026-09-25: "remove star and always
870
+ show red border for require field unless its typed out or
871
+ selected". The field's own border is the one and only required
872
+ signal now — see input:required:invalid below — and it needs no
873
+ asterisk to explain what it already shows. */
872
874
 
873
875
  /* Primary action — the call-to-action fill. Charcoal, the same ink as
874
876
  --color-brand (see --color-cta above): had a hue of its own for a
@@ -1083,6 +1085,16 @@ textarea::placeholder {
1083
1085
  a warehouse read as a plain text box beside fields that plainly
1084
1086
  opened.
1085
1087
  ------------------------------------------------------------------ */
1088
+ /* Combobox's real `required` validation lives on an invisible sibling
1089
+ input (see Combobox.tsx's own comment) — it has no border of its
1090
+ own to turn red, so the visible box reads its sibling's validity
1091
+ instead. Placed after :focus in the file so it wins while the field
1092
+ is focused too: empty-and-required should read as an error the
1093
+ whole time it stays empty, not just at rest. */
1094
+ .combobox-input:has(~ input:required:invalid) {
1095
+ border-color: var(--color-danger);
1096
+ }
1097
+
1086
1098
  select,
1087
1099
  .combobox-input {
1088
1100
  appearance: none;
@@ -1184,57 +1196,14 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover {
1184
1196
  * difference between one red label on a form and all of them.
1185
1197
  */
1186
1198
  /*
1187
- * And a star after the label text, the usual way to mark a required
1188
- * field.
1189
- *
1190
- * Harder than it looks, because the label's text is a bare text node:
1191
- * `<label>First Name<input required></label>`. A plain `label::after`
1192
- * renders after *everything* in the label — under the input, not
1193
- * beside the words — and the only way to attach it to the text
1194
- * directly would be to wrap that text in a span on every field of
1195
- * every form.
1196
- *
1197
- * So the label becomes a wrapping flex row for required fields only,
1198
- * and the three items are ordered explicitly: the text (order 0, an
1199
- * anonymous flex item), the star (order 1), then the control, forced
1200
- * onto the next line by a full-width basis. The result is the text and
1201
- * its star on one line and the field under them — which is what the
1202
- * label already looked like, with a star added and no markup touched.
1203
- */
1204
- label:has(:required) {
1205
- /*
1206
- * !important because 212 labels in this app carry an inline
1207
- * `style={{ display: "block" }}`, and an inline declaration beats
1208
- * any stylesheet rule regardless of specificity. This is the case
1209
- * the keyword exists for: overriding markup a stylesheet cannot
1210
- * reach. Without it the star renders after the control on every one
1211
- * of those labels instead of beside the words.
1212
- */
1213
- display: flex !important;
1214
- flex-wrap: wrap;
1215
- align-items: baseline;
1216
- }
1217
-
1218
- label:has(:required) > * {
1219
- order: 2;
1220
- flex-basis: 100%;
1221
- }
1222
-
1223
- label:has(:required)::after {
1224
- content: "*";
1225
- order: 1;
1226
- margin-left: 2px;
1227
- color: var(--color-danger);
1228
- }
1229
-
1230
- label:has(:required) {
1231
- color: var(--color-danger);
1232
- }
1233
-
1234
- /*
1235
- * The controls inside go back to the normal ink. Colour inherits, so
1236
- * without this a red label means red typing in the box under it — and
1237
- * on a Combobox, red text in the dropdown as well.
1199
+ * No star, and no flex-row layout to hold one — the star this used to
1200
+ * draw beside the text is gone (2026-09-25), so the label goes back
1201
+ * to its own ordinary flow, inline `display: block` and all. The
1202
+ * label's own colour was never touched by this rule either way (see
1203
+ * label[data-required]'s own comment above), so the override just
1204
+ * below — forcing the control's typed text back to normal ink — is
1205
+ * dead weight now and kept only because removing it is out of scope
1206
+ * for this pass.
1238
1207
  */
1239
1208
  label:has(:required) input,
1240
1209
  label:has(:required) select,
@@ -1274,12 +1243,27 @@ textarea:user-invalid {
1274
1243
  border-color: var(--color-danger);
1275
1244
  }
1276
1245
 
1246
+ /* Required and currently empty — on from the moment the form opens,
1247
+ not waiting for a touch. Off the instant a value exists: typed text
1248
+ satisfies :invalid on a plain input/textarea directly; a picked
1249
+ option satisfies it on a select or Combobox's own hidden required
1250
+ input (see .combobox-input's own rule, and .tags-input's, both
1251
+ further down) the same way. */
1252
+ input:required:invalid,
1253
+ select:required:invalid,
1254
+ textarea:required:invalid {
1255
+ border-color: var(--color-danger);
1256
+ }
1257
+
1277
1258
  input[aria-invalid="true"]:focus-visible,
1278
1259
  select[aria-invalid="true"]:focus-visible,
1279
1260
  textarea[aria-invalid="true"]:focus-visible,
1280
1261
  input:user-invalid:focus-visible,
1281
1262
  select:user-invalid:focus-visible,
1282
- textarea:user-invalid:focus-visible {
1263
+ textarea:user-invalid:focus-visible,
1264
+ input:required:invalid:focus-visible,
1265
+ select:required:invalid:focus-visible,
1266
+ textarea:required:invalid:focus-visible {
1283
1267
  border-color: var(--color-danger);
1284
1268
  box-shadow: 0 0 0 3px var(--color-focus-ring-danger);
1285
1269
  }