@textmode/design-system 0.3.4
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 +102 -0
- package/foundations.css +93 -0
- package/package.json +31 -0
- package/primitives.css +81 -0
- package/styles.css +3 -0
- package/tokens.css +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# @textmode/design-system
|
|
2
|
+
|
|
3
|
+
Shared, React-free visual foundations for textmode.art products. This package is a
|
|
4
|
+
deep CSS module: callers learn four stable stylesheet entry points while palette,
|
|
5
|
+
typography, accessibility, and small reusable primitives stay local to one
|
|
6
|
+
implementation. Product layout, content, motion choreography, and canvas
|
|
7
|
+
lifecycle remain app-owned.
|
|
8
|
+
|
|
9
|
+
```css
|
|
10
|
+
@import '@textmode/design-system/styles.css';
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Applications self-host Monogram Extended and must declare an `@font-face` named
|
|
14
|
+
`Monogram Extended`. The package never references font assets. Crimson
|
|
15
|
+
(`--tm-signal`) is reserved for live/active state, meaningful emphasis, and
|
|
16
|
+
errors; it is never a decorative wash.
|
|
17
|
+
|
|
18
|
+
## Public CSS entry points
|
|
19
|
+
|
|
20
|
+
- `styles.css` — deterministic aggregate entry point: tokens, foundations, then primitives
|
|
21
|
+
- `tokens.css` — primitive and semantic custom properties
|
|
22
|
+
- `foundations.css` — reset, focus, selection, forced-colors, reduced motion
|
|
23
|
+
- `primitives.css` — commands, ruled panels, ledger rows, and status signals
|
|
24
|
+
|
|
25
|
+
Import `styles.css` once per document. Lower-level entry points are only for
|
|
26
|
+
deliberate composition; applications must not import package-internal files or
|
|
27
|
+
recreate aggregate ordering. The package deliberately does not opt pages into
|
|
28
|
+
scroll snapping, prescribe a layout, or provide React modules. Those behaviors
|
|
29
|
+
remain product-owned so dense workspaces are unaffected.
|
|
30
|
+
|
|
31
|
+
## Token inventory
|
|
32
|
+
|
|
33
|
+
### Primitive palette
|
|
34
|
+
|
|
35
|
+
`--tm-color-black`, `--tm-color-black-raised`, `--tm-color-black-elevated`,
|
|
36
|
+
`--tm-color-white`, `--tm-color-white-muted`, `--tm-color-gray`,
|
|
37
|
+
`--tm-color-gray-dark`, `--tm-color-line`, `--tm-color-line-muted`,
|
|
38
|
+
`--tm-color-crimson`, `--tm-color-crimson-readable`, `--tm-color-danger`.
|
|
39
|
+
|
|
40
|
+
### Semantic roles
|
|
41
|
+
|
|
42
|
+
`--tm-ink`, `--tm-surface`, `--tm-surface-raised`, `--tm-paper`,
|
|
43
|
+
`--tm-paper-muted`, `--tm-text-muted`, `--tm-rule`, `--tm-rule-muted`,
|
|
44
|
+
`--tm-signal`, `--tm-signal-text`, `--tm-error`, `--tm-focus`.
|
|
45
|
+
|
|
46
|
+
### Typography
|
|
47
|
+
|
|
48
|
+
`--tm-font-display`, `--tm-font-interface`, `--tm-font-copy`,
|
|
49
|
+
`--tm-font-code`, `--tm-type-meta`, `--tm-type-control`, `--tm-type-copy`,
|
|
50
|
+
`--tm-type-copy-large`, `--tm-type-title`, `--tm-leading-tight`,
|
|
51
|
+
`--tm-leading-copy`, `--tm-tracking-display`.
|
|
52
|
+
|
|
53
|
+
### Geometry and layout
|
|
54
|
+
|
|
55
|
+
`--tm-space-1`, `--tm-space-2`, `--tm-space-3`, `--tm-space-4`,
|
|
56
|
+
`--tm-space-5`, `--tm-space-6`, `--tm-space-7`, `--tm-space-8`,
|
|
57
|
+
`--tm-page-pad`, `--tm-header-height`, `--tm-control-height`,
|
|
58
|
+
`--tm-section-height`, `--tm-section-rail-width`, `--tm-section-pager-height`,
|
|
59
|
+
`--tm-rule-width`, `--tm-touch-target`.
|
|
60
|
+
|
|
61
|
+
### Motion and stacking
|
|
62
|
+
|
|
63
|
+
`--tm-duration-fast`, `--tm-duration-state`, `--tm-duration-section`,
|
|
64
|
+
`--tm-ease-out`, `--tm-z-dropdown`, `--tm-z-sticky`, `--tm-z-rail`,
|
|
65
|
+
`--tm-z-modal-backdrop`, `--tm-z-modal`, `--tm-z-toast`, `--tm-z-tooltip`.
|
|
66
|
+
|
|
67
|
+
Section-based brand surfaces may consume `--tm-section-rail-width`,
|
|
68
|
+
`--tm-section-pager-height`, and `--tm-duration-section`, but navigation and
|
|
69
|
+
responsive behavior remain local to their product.
|
|
70
|
+
|
|
71
|
+
## Primitive inventory
|
|
72
|
+
|
|
73
|
+
- `.tm-command` and `.tm-command--signal` — 44 px command links or buttons with
|
|
74
|
+
inverse and signal states.
|
|
75
|
+
- `.tm-rule-panel` — product-neutral ruled surface.
|
|
76
|
+
- `.tm-ledger-row` — tabular metadata row.
|
|
77
|
+
- `.tm-status-signal` — live or active state marker.
|
|
78
|
+
- `.tm-sr-only` — visually hidden accessible text.
|
|
79
|
+
|
|
80
|
+
The foundation contract includes `:focus-visible`, disabled and
|
|
81
|
+
`[aria-disabled='true']` states, selection, reduced-motion behavior, and
|
|
82
|
+
forced-colors treatment for `aria-current` and `aria-pressed` state.
|
|
83
|
+
|
|
84
|
+
## Consumer migration
|
|
85
|
+
|
|
86
|
+
1. Import `@textmode/design-system/styles.css` before product-owned stylesheet
|
|
87
|
+
imports.
|
|
88
|
+
2. Keep product-local aliases while moving rules to `--tm-*` tokens; do not
|
|
89
|
+
rename markup classes or change selector ordering as part of token adoption.
|
|
90
|
+
3. Remove aliases only after every consumer style has moved, visual baselines
|
|
91
|
+
pass unchanged, and no supported integration reads the alias.
|
|
92
|
+
4. To roll back, remove the aggregate import and restore the prior local token
|
|
93
|
+
declarations in one change. Do not update visual baselines to accept an
|
|
94
|
+
unintended difference.
|
|
95
|
+
|
|
96
|
+
The package has no JavaScript runtime or peer dependencies. Publish releases with
|
|
97
|
+
semantic versioning: patch for value corrections, minor for additive tokens or
|
|
98
|
+
classes, and major for removals or semantic changes. Version 0.3.4 adds
|
|
99
|
+
`--tm-font-copy`, `--tm-section-height`, and package contract verification
|
|
100
|
+
without changing the existing public token values; it also keeps reduced-motion
|
|
101
|
+
rules limited to scroll and transition behavior so product-owned animation state
|
|
102
|
+
remains overrideable.
|
package/foundations.css
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
@layer textmode-foundations {
|
|
2
|
+
*,
|
|
3
|
+
*::before,
|
|
4
|
+
*::after {
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
html {
|
|
9
|
+
background: var(--tm-ink);
|
|
10
|
+
color-scheme: dark;
|
|
11
|
+
font-synthesis: none;
|
|
12
|
+
-moz-osx-font-smoothing: grayscale;
|
|
13
|
+
-webkit-font-smoothing: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
background: var(--tm-ink);
|
|
18
|
+
color: var(--tm-paper);
|
|
19
|
+
font-family: var(--tm-font-interface);
|
|
20
|
+
text-rendering: geometricPrecision;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
button,
|
|
24
|
+
input,
|
|
25
|
+
select,
|
|
26
|
+
textarea {
|
|
27
|
+
font: inherit;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
button,
|
|
31
|
+
input,
|
|
32
|
+
select,
|
|
33
|
+
summary,
|
|
34
|
+
a {
|
|
35
|
+
touch-action: manipulation;
|
|
36
|
+
-webkit-tap-highlight-color: rgb(242 242 236 / 18%);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
h1,
|
|
40
|
+
h2,
|
|
41
|
+
h3 {
|
|
42
|
+
text-wrap: balance;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
p,
|
|
46
|
+
dd,
|
|
47
|
+
figcaption {
|
|
48
|
+
text-wrap: pretty;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
::selection {
|
|
52
|
+
background: var(--tm-paper);
|
|
53
|
+
color: var(--tm-ink);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
:focus-visible {
|
|
57
|
+
outline: 2px solid var(--tm-focus);
|
|
58
|
+
outline-offset: 3px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
[aria-disabled='true'],
|
|
62
|
+
:disabled {
|
|
63
|
+
cursor: not-allowed;
|
|
64
|
+
opacity: 0.5;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@media (forced-colors: active) {
|
|
68
|
+
:focus-visible {
|
|
69
|
+
outline-color: Highlight;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
[aria-current='page'],
|
|
73
|
+
[aria-current='location'],
|
|
74
|
+
[aria-current='true'],
|
|
75
|
+
[aria-pressed='true'] {
|
|
76
|
+
outline: 2px solid Highlight;
|
|
77
|
+
outline-offset: -2px;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@media (prefers-reduced-motion: reduce) {
|
|
82
|
+
html {
|
|
83
|
+
scroll-behavior: auto;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
*,
|
|
87
|
+
*::before,
|
|
88
|
+
*::after {
|
|
89
|
+
scroll-behavior: auto;
|
|
90
|
+
transition-duration: 0.01ms;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@textmode/design-system",
|
|
3
|
+
"version": "0.3.4",
|
|
4
|
+
"description": "Shared visual foundations and CSS primitives for textmode.art interfaces",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": [
|
|
8
|
+
"*.css"
|
|
9
|
+
],
|
|
10
|
+
"files": [
|
|
11
|
+
"*.css",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
"./styles.css": "./styles.css",
|
|
16
|
+
"./tokens.css": "./tokens.css",
|
|
17
|
+
"./foundations.css": "./foundations.css",
|
|
18
|
+
"./primitives.css": "./primitives.css"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "npm run check",
|
|
22
|
+
"check": "npm run check:format && npm run check:package && npm test",
|
|
23
|
+
"check:format": "prettier --check .",
|
|
24
|
+
"check:package": "node scripts/check-package.mjs",
|
|
25
|
+
"test": "node --test tests/*.test.mjs",
|
|
26
|
+
"format": "prettier --write ."
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
}
|
|
31
|
+
}
|
package/primitives.css
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
@layer textmode-primitives {
|
|
2
|
+
.tm-command {
|
|
3
|
+
display: inline-flex;
|
|
4
|
+
min-height: var(--tm-touch-target);
|
|
5
|
+
align-items: center;
|
|
6
|
+
justify-content: center;
|
|
7
|
+
gap: var(--tm-space-2);
|
|
8
|
+
border: var(--tm-rule-width) solid var(--tm-rule);
|
|
9
|
+
padding: var(--tm-space-3) var(--tm-space-4);
|
|
10
|
+
background: transparent;
|
|
11
|
+
color: var(--tm-paper);
|
|
12
|
+
font-family: var(--tm-font-interface);
|
|
13
|
+
font-size: var(--tm-type-control);
|
|
14
|
+
line-height: 1;
|
|
15
|
+
text-decoration: none;
|
|
16
|
+
transition:
|
|
17
|
+
background-color var(--tm-duration-state) var(--tm-ease-out),
|
|
18
|
+
border-color var(--tm-duration-state) var(--tm-ease-out),
|
|
19
|
+
color var(--tm-duration-state) var(--tm-ease-out);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.tm-command:hover,
|
|
23
|
+
.tm-command:active,
|
|
24
|
+
.tm-command[aria-pressed='true'] {
|
|
25
|
+
border-color: var(--tm-paper);
|
|
26
|
+
background: var(--tm-paper);
|
|
27
|
+
color: var(--tm-ink);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.tm-command--signal {
|
|
31
|
+
border-color: var(--tm-signal);
|
|
32
|
+
background: var(--tm-signal);
|
|
33
|
+
color: var(--tm-paper);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.tm-command--signal:hover,
|
|
37
|
+
.tm-command--signal:active {
|
|
38
|
+
border-color: var(--tm-paper);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.tm-rule-panel {
|
|
42
|
+
border-block: var(--tm-rule-width) solid var(--tm-rule);
|
|
43
|
+
background: var(--tm-ink);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.tm-ledger-row {
|
|
47
|
+
display: flex;
|
|
48
|
+
min-height: var(--tm-touch-target);
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: space-between;
|
|
51
|
+
gap: var(--tm-space-4);
|
|
52
|
+
border-bottom: var(--tm-rule-width) solid var(--tm-rule-muted);
|
|
53
|
+
font-variant-numeric: tabular-nums;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.tm-status-signal {
|
|
57
|
+
display: inline-flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
gap: var(--tm-space-2);
|
|
60
|
+
color: var(--tm-paper-muted);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.tm-status-signal::before {
|
|
64
|
+
width: 0.55em;
|
|
65
|
+
height: 0.55em;
|
|
66
|
+
background: var(--tm-signal);
|
|
67
|
+
content: '';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.tm-sr-only {
|
|
71
|
+
position: absolute;
|
|
72
|
+
width: 1px;
|
|
73
|
+
height: 1px;
|
|
74
|
+
padding: 0;
|
|
75
|
+
border: 0;
|
|
76
|
+
margin: -1px;
|
|
77
|
+
clip: rect(0, 0, 0, 0);
|
|
78
|
+
overflow: hidden;
|
|
79
|
+
white-space: nowrap;
|
|
80
|
+
}
|
|
81
|
+
}
|
package/styles.css
ADDED
package/tokens.css
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
@layer tokens {
|
|
2
|
+
:root {
|
|
3
|
+
color-scheme: dark;
|
|
4
|
+
|
|
5
|
+
/* Primitive palette */
|
|
6
|
+
--tm-color-black: #0a0a0a;
|
|
7
|
+
--tm-color-black-raised: #101010;
|
|
8
|
+
--tm-color-black-elevated: #171717;
|
|
9
|
+
--tm-color-white: #f2f2ec;
|
|
10
|
+
--tm-color-white-muted: #d8d8d2;
|
|
11
|
+
--tm-color-gray: #9a9a95;
|
|
12
|
+
--tm-color-gray-dark: #343432;
|
|
13
|
+
--tm-color-line: #5a5a56;
|
|
14
|
+
--tm-color-line-muted: #292927;
|
|
15
|
+
--tm-color-crimson: #b11226;
|
|
16
|
+
--tm-color-crimson-readable: #ef4960;
|
|
17
|
+
--tm-color-danger: #ff7e8c;
|
|
18
|
+
|
|
19
|
+
/* Semantic color roles */
|
|
20
|
+
--tm-ink: var(--tm-color-black);
|
|
21
|
+
--tm-surface: var(--tm-color-black-raised);
|
|
22
|
+
--tm-surface-raised: var(--tm-color-black-elevated);
|
|
23
|
+
--tm-paper: var(--tm-color-white);
|
|
24
|
+
--tm-paper-muted: var(--tm-color-white-muted);
|
|
25
|
+
--tm-text-muted: var(--tm-color-gray);
|
|
26
|
+
--tm-rule: var(--tm-color-line);
|
|
27
|
+
--tm-rule-muted: var(--tm-color-line-muted);
|
|
28
|
+
--tm-signal: var(--tm-color-crimson);
|
|
29
|
+
--tm-signal-text: var(--tm-color-crimson-readable);
|
|
30
|
+
--tm-error: var(--tm-color-danger);
|
|
31
|
+
--tm-focus: var(--tm-color-white);
|
|
32
|
+
|
|
33
|
+
/* Typography */
|
|
34
|
+
--tm-font-display: 'Monogram Extended';
|
|
35
|
+
--tm-font-interface: 'Monogram Extended';
|
|
36
|
+
--tm-font-copy: 'Monogram Extended';
|
|
37
|
+
--tm-font-code: 'SFMono-Regular', Consolas, 'Liberation Mono', monospace;
|
|
38
|
+
--tm-type-meta: 1rem;
|
|
39
|
+
--tm-type-control: 1.25rem;
|
|
40
|
+
--tm-type-copy: 1.25rem;
|
|
41
|
+
--tm-type-copy-large: 1.5rem;
|
|
42
|
+
--tm-type-title: clamp(3.5rem, 8vw, 6rem);
|
|
43
|
+
--tm-leading-tight: 0.82;
|
|
44
|
+
--tm-leading-copy: 1.18;
|
|
45
|
+
--tm-tracking-display: -0.02em;
|
|
46
|
+
|
|
47
|
+
/* Geometry and layout */
|
|
48
|
+
--tm-space-1: 0.25rem;
|
|
49
|
+
--tm-space-2: 0.5rem;
|
|
50
|
+
--tm-space-3: 0.75rem;
|
|
51
|
+
--tm-space-4: 1rem;
|
|
52
|
+
--tm-space-5: 1.5rem;
|
|
53
|
+
--tm-space-6: 2rem;
|
|
54
|
+
--tm-space-7: 3rem;
|
|
55
|
+
--tm-space-8: 4rem;
|
|
56
|
+
--tm-page-pad: clamp(0.75rem, 1.8vw, 1.75rem);
|
|
57
|
+
--tm-header-height: 3.75rem;
|
|
58
|
+
--tm-control-height: 2.75rem;
|
|
59
|
+
--tm-section-height: calc(100svh - var(--tm-header-height));
|
|
60
|
+
--tm-section-rail-width: 3rem;
|
|
61
|
+
--tm-section-pager-height: 3rem;
|
|
62
|
+
--tm-rule-width: 1px;
|
|
63
|
+
--tm-touch-target: 2.75rem;
|
|
64
|
+
|
|
65
|
+
/* Motion and stacking */
|
|
66
|
+
--tm-duration-fast: 120ms;
|
|
67
|
+
--tm-duration-state: 180ms;
|
|
68
|
+
--tm-duration-section: 280ms;
|
|
69
|
+
--tm-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
|
70
|
+
--tm-z-dropdown: 20;
|
|
71
|
+
--tm-z-sticky: 30;
|
|
72
|
+
--tm-z-rail: 35;
|
|
73
|
+
--tm-z-modal-backdrop: 40;
|
|
74
|
+
--tm-z-modal: 50;
|
|
75
|
+
--tm-z-toast: 60;
|
|
76
|
+
--tm-z-tooltip: 70;
|
|
77
|
+
}
|
|
78
|
+
}
|