@judarn/ui 0.7.2 → 0.7.12

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @judarn/ui
1
+ # `@judarn/ui`
2
2
 
3
3
  React components and CSS tokens for the Judarn design system, with colors in OKLCh and a fixed 8 px spacing grid.
4
4
 
@@ -13,7 +13,7 @@ export interface TagProps extends React.HTMLAttributes<HTMLSpanElement> {
13
13
  }
14
14
 
15
15
  /**
16
- * Resolves the foreground ink ("#000000" or "#ffffff") for a fill from its relative luminance and the 0.50 perceptual crossover (ADR-0006).
16
+ * Resolves the foreground ink ("#000000" or "#ffffff") for a fill from its relative luminance and the 0.50 perceptual crossover.
17
17
  * Accepts #hex, rgb() and oklch(); throws a TypeError for any other format.
18
18
  */
19
19
  export function getContrastingInk(hexOrRgb: string): string;
@@ -3,7 +3,7 @@ import * as React from "react";
3
3
  export interface CardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
4
4
  /** Small accent label, set as a `t-label` (uppercase unless `eyebrowCasing` is "asWritten"). */
5
5
  eyebrow?: string;
6
- /** "asWritten" for an eyebrow holding a unit, a digit, or a mixed-case term (ADR-0009). @default "uppercase" */
6
+ /** "asWritten" for an eyebrow holding a unit, a digit, or a mixed-case term. @default "uppercase" */
7
7
  eyebrowCasing?: "uppercase" | "asWritten";
8
8
  title?: React.ReactNode;
9
9
  children?: React.ReactNode;
@@ -7,7 +7,7 @@ export interface MatrixColumn {
7
7
  numeric?: boolean;
8
8
  /** Fixed width in pixels (number) or CSS length (string). */
9
9
  width?: number | string;
10
- /** "asWritten" for a header holding a unit symbol or mixed-case term, such as kg or e1RM (ADR-0009). @default "uppercase" */
10
+ /** "asWritten" for a header holding a unit symbol or mixed-case term, such as kg or e1RM. @default "uppercase" */
11
11
  casing?: "uppercase" | "asWritten";
12
12
  }
13
13
 
@@ -5,7 +5,7 @@ export interface DataColumn {
5
5
  label: string;
6
6
  /** Right-align with tabular figures. @default false */
7
7
  numeric?: boolean;
8
- /** "asWritten" for a header holding a unit symbol or mixed-case term, such as kg or e1RM (ADR-0009). @default "uppercase" */
8
+ /** "asWritten" for a header holding a unit symbol or mixed-case term, such as kg or e1RM. @default "uppercase" */
9
9
  casing?: "uppercase" | "asWritten";
10
10
  }
11
11
 
@@ -12,7 +12,7 @@ export interface FooterProps extends React.HTMLAttributes<HTMLElement> {
12
12
  tagline?: string;
13
13
  /** Link columns. */
14
14
  columns?: FooterColumn[];
15
- /** "asWritten" for column heads holding mixed-case terms (ADR-0009). Heads render as `h2`. @default "uppercase" */
15
+ /** "asWritten" for column heads holding mixed-case terms. Heads render as `h2`. @default "uppercase" */
16
16
  headCasing?: "uppercase" | "asWritten";
17
17
  }
18
18
 
@@ -11,7 +11,7 @@ export interface LogoLockupProps {
11
11
  variant?: "horizontal" | "vertical" | "icon" | "reversed";
12
12
  /** Pixel size of the placeholder mark. */
13
13
  markSize?: number;
14
- /** "asWritten" keeps the tagline as written (ADR-0009). @default "uppercase" */
14
+ /** "asWritten" keeps the tagline as written. @default "uppercase" */
15
15
  taglineCasing?: "uppercase" | "asWritten";
16
16
  }
17
17
 
@@ -10,7 +10,7 @@ type FieldControlProps = Omit<
10
10
  export interface TextFieldProps extends FieldControlProps {
11
11
  /** Label above the control, uppercase unless labelCasing is "asWritten". */
12
12
  label?: string;
13
- /** "asWritten" for a label longer than two words or holding a digit, unit, or mixed-case term (ADR-0009). @default "uppercase" */
13
+ /** "asWritten" for a label longer than two words or holding a digit, unit, or mixed-case term. @default "uppercase" */
14
14
  labelCasing?: "uppercase" | "asWritten";
15
15
  /** Helper text below the control, linked with `aria-describedby`. */
16
16
  hint?: string;
@@ -26,6 +26,9 @@ export interface TextFieldProps extends FieldControlProps {
26
26
  disabled?: boolean;
27
27
  }
28
28
 
29
- /** Labelled field – input / textarea / select with Judarn styling. */
29
+ /**
30
+ * Labelled field – input / textarea / select with Judarn styling. A well set apart by fill alone:
31
+ * surfaceRecessed on the page, substrate inside a card, and no outline except in high-contrast modes.
32
+ */
30
33
  export function TextField(props: TextFieldProps): React.JSX.Element;
31
34
  export default TextField;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@judarn/ui",
3
- "version": "0.7.2",
3
+ "version": "0.7.12",
4
4
  "description": "Judarn design foundation tokens and React components for the web",
5
5
  "author": "Ruben Luthman",
6
6
  "license": "MIT",
package/src/tailwind.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Generated from tokens/judarn-tokens.json – do not edit directly.
4
4
  */
5
5
  module.exports = function judarnTailwindPlugin({ addBase, theme }) {
6
- // Do not override global border radius to 0px; adhere to ADR-0002
6
+ // Do not override global border radius to 0px; adhere to the shape rules in docs/DESIGN.md
7
7
  };
8
8
 
9
9
  module.exports.theme = {
@@ -106,7 +106,7 @@
106
106
  The resolved --accent, --accent-fg, --accent-ink and --accent-2 are declared in every theme
107
107
  scope so a nested scope resolves its own default; a hook set on :root survives nesting.
108
108
  --accent defaults to ink-100 and --accent-fg to --accent. --accent-ink is static ink on an
109
- accent fill (ADR-0006); a project that sets --jd-accent sets --jd-accent-ink too. */
109
+ accent fill; a project that sets --jd-accent sets --jd-accent-ink too. */
110
110
  --accent: var(--jd-accent, var(--jd-ink-100));
111
111
  --accent-fg: var(--jd-accent-fg, var(--accent));
112
112
  --accent-ink: var(--jd-accent-ink, #ffffff);
@@ -325,13 +325,26 @@
325
325
  font-variant-ligatures: none;
326
326
  color: var(--jd-ink-100);
327
327
  }
328
- /* As-written casing for the uppercase label styles: statuses, counts, values, units, messages, controls (ADR-0009). */
328
+ /* As-written casing for the uppercase label styles: statuses, counts, values, units, messages, controls. */
329
329
  .t-label.t-as-written,
330
330
  .t-micro.t-as-written {
331
331
  text-transform: none;
332
332
  letter-spacing: var(--jd-track-body);
333
333
  font-feature-settings: normal;
334
334
  }
335
+ /* Flow: space between the direct children of a container, from the space tokens. A heading belongs to the text below it. Never combine with gap. */
336
+ .flow {
337
+ display: flow-root;
338
+ }
339
+ .flow > * + * {
340
+ margin-block-start: var(--jd-space-2);
341
+ }
342
+ .flow > * + :is(h1, h2, h3, h4, h5, h6, .t-display, .t-h1, .t-h2, .t-h3, .t-h4) {
343
+ margin-block-start: var(--jd-space-4);
344
+ }
345
+ .flow > :is(h1, h2, h3, h4, h5, h6, .t-display, .t-h1, .t-h2, .t-h3, .t-h4) + * {
346
+ margin-block-start: var(--jd-space-1);
347
+ }
335
348
  .t-editorial-nums {
336
349
  font-variant-numeric: oldstyle-nums proportional-nums;
337
350
  font-feature-settings: "onum" 1, "pnum" 1;
@@ -67,21 +67,29 @@
67
67
  text-transform: uppercase;
68
68
  color: var(--black);
69
69
  }
70
+ /* A field is a well set apart by fill alone (DESIGN.md, Surface Hierarchy): surfaceRecessed on the
71
+ page, substrate inside a card. The resting border is transparent: it keeps the field's size, and
72
+ Windows high-contrast mode still draws it. High-contrast modes turn it into an ink-100 outline. */
70
73
  .field__input {
71
74
  font-family: var(--font-sans);
72
75
  font-size: var(--size-body);
73
76
  color: var(--black);
74
- background: var(--white);
75
- border: var(--rule) solid var(--black);
77
+ background: var(--jd-surface-recessed);
78
+ border: var(--rule) solid transparent;
76
79
  border-radius: var(--radius-control);
77
80
  padding: var(--space-2);
78
81
  width: 100%;
79
82
  transition: border-color 120ms linear, box-shadow 120ms linear;
80
83
  }
84
+ .card .field__input { background: var(--paper); }
85
+ @media (prefers-contrast: more) {
86
+ :where(:root:not([data-contrast="normal"])) .field__input { border-color: var(--ink-100); }
87
+ }
88
+ :where([data-contrast="high"]) .field__input { border-color: var(--ink-100); }
81
89
  .field__input::placeholder { color: var(--ink-60); }
82
90
  .field__input:focus { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
83
91
  .field__input:focus-visible { outline: var(--rule-bold) solid var(--accent); outline-offset: 2px; }
84
- .field__input:disabled { color: var(--ink-30); border-color: var(--ink-30); background: var(--jd-surface-recessed); cursor: not-allowed; }
92
+ .field__input:disabled { color: var(--ink-30); cursor: not-allowed; }
85
93
  .field__input[aria-invalid="true"], .field__input.is-invalid { border-color: var(--signal-error); box-shadow: 0 0 0 1px var(--signal-error); }
86
94
  .field__hint { font-size: var(--size-small); color: var(--ink-60); }
87
95
  .field__hint.is-error, .field__hint--error { color: var(--signal-error); font-weight: var(--weight-medium); }
@@ -101,7 +109,7 @@ select.field__input { cursor: pointer; } /* native appearance keeps the platform
101
109
  .card--flat { border: none; padding: 0; border-radius: 0; }
102
110
  .card--compact { padding: var(--space-2); }
103
111
  .card--field { background: var(--bg2); border: none; }
104
- .card__eyebrow { color: var(--accent); } /* type comes from t-label (ADR-0009) */
112
+ .card__eyebrow { color: var(--accent); } /* type comes from t-label */
105
113
  .card__title { font-size: var(--size-h4); font-weight: var(--weight-bold); letter-spacing: var(--track-head); }
106
114
  .card__body { font-size: var(--size-body); line-height: var(--lh-body); }
107
115
  .card__media { aspect-ratio: 3 / 2; background: var(--jd-surface-recessed); border-radius: var(--radius-control); overflow: hidden; }
@@ -151,7 +159,7 @@ select.field__input { cursor: pointer; } /* native appearance keeps the platform
151
159
  display: grid; grid-template-columns: 2fr 1fr 1fr; gap: var(--space-4);
152
160
  }
153
161
  .footer__col { display: flex; flex-direction: column; gap: var(--gap-tight); }
154
- .footer__head { margin: 0 0 var(--space-1); color: var(--black); } /* type comes from t-label (ADR-0009) */
162
+ .footer__head { margin: 0 0 var(--space-1); color: var(--black); } /* type comes from t-label */
155
163
  .footer__link { font-size: var(--size-small); color: var(--fg2); }
156
164
  .footer__link:hover { color: var(--black); text-decoration: underline; text-underline-offset: 3px; }
157
165
 
@@ -167,7 +175,7 @@ select.field__input { cursor: pointer; } /* native appearance keeps the platform
167
175
  .table .num { text-align: right; font-variant-numeric: tabular-nums; }
168
176
 
169
177
  /* As-written casing for a field label or column header that holds a unit, a mixed-case term,
170
- or more than two words (ADR-0009). */
178
+ or more than two words. */
171
179
  .field__label.t-as-written,
172
180
  .table th.t-as-written,
173
181
  .matrix th.t-as-written { text-transform: none; letter-spacing: var(--track-body); }
@@ -179,7 +187,7 @@ select.field__input { cursor: pointer; } /* native appearance keeps the platform
179
187
  .lockup__mark { display: block; flex: none; }
180
188
  .lockup__words { display: flex; flex-direction: column; }
181
189
  .lockup__name { font-weight: var(--weight-bold); font-size: var(--size-h4); line-height: 1; letter-spacing: var(--track-head); }
182
- .lockup__tag { color: var(--fg2); margin-top: 4px; } /* type comes from t-label (ADR-0009) */
190
+ .lockup__tag { color: var(--fg2); margin-top: 4px; } /* type comes from t-label */
183
191
  .lockup--reversed .lockup__tag { color: var(--ink-30); }
184
192
 
185
193
  /* ---- DATA MATRIX ------------------------------------------------------- */
@@ -45,7 +45,7 @@
45
45
  --border-width-rule-bold: var(--jd-rule-bold);
46
46
  --border-width-rule-heavy: var(--jd-rule-heavy);
47
47
 
48
- /* Platform Authority Radii (ADR-0002) */
48
+ /* Platform Authority Radii */
49
49
  --radius-subtle: var(--jd-radius-subtle, 6px);
50
50
  --radius-control: var(--jd-radius-control, 10px);
51
51
  --radius-card: var(--jd-radius-card, 16px);