@brightweblabs/theme 0.2.1 → 0.4.0
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 +96 -0
- package/package.json +1 -1
- package/src/base.css +26 -1
- package/src/surfaces.css +72 -76
- package/src/theme.css +40 -0
- package/src/tokens.css +349 -4
- package/src/typography.css +70 -62
- package/themes/mq-aliases.css +105 -40
- package/themes/mq.css +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# `@brightweblabs/theme` token contract
|
|
2
|
+
|
|
3
|
+
BrightWeb themes follow one cascade: L0 brand primitives feed L1 shadcn semantics, L2 describes brand-agnostic states, and L3 exposes component and experience controls. Package components consume L1-L3 tokens only; theme files such as `themes/mq.css` override values without changing component code.
|
|
4
|
+
|
|
5
|
+
## Typography and font loading
|
|
6
|
+
|
|
7
|
+
Geist is the offline-safe platform default. Applications load `GeistSans` and `GeistMono` from the `geist/font` package and attach their variables to the app root (the platform layout uses `<body>`):
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { GeistMono } from "geist/font/mono";
|
|
11
|
+
import { GeistSans } from "geist/font/sans";
|
|
12
|
+
|
|
13
|
+
<body className={`${GeistSans.variable} ${GeistMono.variable}`}>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The family contract starts at `--font-body`, `--font-heading`, and `--font-code`; Tailwind-facing `--font-sans`, `--font-display`, and `--font-mono` aliases resolve through those tokens. Raw sizes live only in the `--text-ui-*`, `--type-*`, weight, leading, and tracking scales in `src/tokens.css`. Components consume semantic utilities such as `text-ui-body`, `portal-title`, and `heading-2`, so changing a family or scale does not require component edits.
|
|
17
|
+
|
|
18
|
+
Client themes can override the family without forking recipes. The MQ path is:
|
|
19
|
+
|
|
20
|
+
```css
|
|
21
|
+
@import "@brightweblabs/theme/css";
|
|
22
|
+
@import "@brightweblabs/theme/themes/mq";
|
|
23
|
+
@import "@brightweblabs/theme/themes/mq-aliases";
|
|
24
|
+
|
|
25
|
+
:root {
|
|
26
|
+
--font-client-body: "Mulish", sans-serif;
|
|
27
|
+
--font-body: var(--font-client-body);
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`themes/mq.css` supplies MQ color and surface values, while `themes/mq-aliases.css` maps legacy MQ typography names onto the same tokenized scale. Import the MQ stylesheet after the base theme. Keep font loading at the app root; theme packages only select variables and never fetch fonts.
|
|
32
|
+
|
|
33
|
+
## Runtime theme switching
|
|
34
|
+
|
|
35
|
+
Theme tokens respond to both `html.dark` and `html[data-theme="dark"]`. Platform apps should use the shell-owned controller so those selectors never drift:
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { ThemeProvider, ThemeScript } from "@brightweblabs/app-shell";
|
|
39
|
+
|
|
40
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
41
|
+
return (
|
|
42
|
+
<html lang="en" suppressHydrationWarning>
|
|
43
|
+
<head>
|
|
44
|
+
<ThemeScript defaultTheme="light" />
|
|
45
|
+
</head>
|
|
46
|
+
<body>
|
|
47
|
+
<ThemeProvider defaultTheme="light">{children}</ThemeProvider>
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`ThemeScript` applies the stored `bw-theme` mode before hydration to prevent a light-theme flash. `ThemeProvider` keeps the root class, `data-theme`, and `color-scheme` synchronized, persists `"light" | "dark" | "system"`, and follows `prefers-color-scheme` while system mode is selected. Account menus rendered below the provider use this controller automatically.
|
|
55
|
+
|
|
56
|
+
## L3 visual tokens
|
|
57
|
+
|
|
58
|
+
| Tokens | Purpose |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| `--font-body`, `--font-heading`, `--font-code`; `--font-sans`, `--font-display`, `--font-mono` | Root font families and their Tailwind-facing aliases. |
|
|
61
|
+
| `--type-weight-*`, `--type-leading-*`, `--type-tracking-*` | Shared typography weight, rhythm, and tracking primitives. |
|
|
62
|
+
| `--text-ui-*`, `--type-paragraph*`, `--type-heading-2`, `--type-label` | Tokenized platform and compatibility type scales. |
|
|
63
|
+
| `--foreground-muted-accessible`, `--foreground-inverse-muted`, `--foreground-inverse-subtle` | Contrast-safe secondary and inverse text roles. |
|
|
64
|
+
| `--text-ui-chip`, `--text-ui-action`, `--text-ui-calendar` | Compact control and calendar type sizes. |
|
|
65
|
+
| `--text-ui-shell-title`, `--text-ui-report-title`, `--text-ui-report-title-lg`, `--text-ui-report-metric` | Shell and CRM report display type sizes. |
|
|
66
|
+
| `--surface-overlay`, `--surface-overlay-strong`, `--surface-tooltip`, `--surface-badge-tint` | Overlay, tooltip, and tint surfaces. |
|
|
67
|
+
| `--surface-button-soft`, `--surface-button-soft-hover`, `--border-button-soft-hover` | Soft button surface states. |
|
|
68
|
+
| `--surface-selection`, `--border-selection`, `--surface-pagination-active`, `--border-pagination-active` | Selected control and active pagination states. |
|
|
69
|
+
| `--surface-danger-subtle` | Subtle destructive-state background. |
|
|
70
|
+
| `--surface-account-team`, `--surface-account-client`, `--surface-account`, `--surface-account-hover`, `--account-presence` | Account rail identity, presence, and interaction surfaces. |
|
|
71
|
+
| `--account-presence-size`, `--radius-swatch`, `--radius-pill`, `--radius-scrollbar` | Presence, swatch, pill, avatar, and scrollbar geometry. |
|
|
72
|
+
| `--row-hover-sweep`, `--surface-status-success`, `--surface-status-warning`, `--surface-status-danger` | Shared row and status surfaces. |
|
|
73
|
+
| `--dashboard-*` | Aggregate dashboard glows, shadows, task groups, milestone states, and local shell contrast recipes. |
|
|
74
|
+
| `--tint-soft-border`, `--tint-soft-bg`, `--tint-soft-hover`, `--tint-hero-border`, `--tint-hero-bg`, `--tint-hero-fg`, `--tint-hero-hover` | Dynamic tint recipes resolved where a component supplies `--tint`. |
|
|
75
|
+
| `--scrollbar-thumb`, `--scrollbar-thumb-hover`, `--scrollbar-size` | Shared scrollbar colour and geometry. |
|
|
76
|
+
| `--toast-success-bg`, `--toast-success-border`, `--toast-warning-bg`, `--toast-warning-text`, `--toast-warning-border`, `--toast-error-bg`, `--toast-error-border`, `--toast-info-bg`, `--toast-info-text`, `--toast-info-border` | Sonner semantic toast palette. |
|
|
77
|
+
| `--shadow-accent-control`, `--shadow-toolbar-control`, `--shadow-toolbar-popover`, `--shadow-tooltip`, `--shadow-dialog`, `--shadow-phone-dropdown` | Component elevation recipes. |
|
|
78
|
+
| `--report-hero-glow`, `--report-hero-rule` | CRM report decorative surfaces. |
|
|
79
|
+
| `--shell-frame-offset`, `--shell-sidebar-width`, `--shell-sidebar-collapsed-width`, `--shell-sidebar-toggle-offset`, `--shell-sidebar-toggle-size`, `--shell-sidebar-toggle-inset`, `--shell-brand-height` | Shell frame and sidebar geometry. |
|
|
80
|
+
| `--shell-nav-item-height`, `--shell-nav-item-collapsed-size`, `--shell-nav-icon-well-size`, `--shell-nav-icon-radius`, `--shell-nav-icon-size`, `--shell-nav-divider-width`, `--shell-nav-child-height`, `--shell-nav-child-enter-offset` | Shell navigation sizing and entry geometry. |
|
|
81
|
+
| `--shell-nav-active-indicator-inset`, `--shell-nav-active-indicator-collapsed-inset`, `--shell-nav-active-indicator-width`, `--shell-nav-active-indicator-offset`, `--shell-nav-context-dot-size`, `--shell-nav-context-dot-offset`, `--shell-nav-context-dot-border` | Shell navigation active markers. |
|
|
82
|
+
| `--shell-header-divider-height`, `--shell-account-gap`, `--shell-account-padding-y` | Header and account-control anatomy. |
|
|
83
|
+
| `--shell-surface-border`, `--shell-surface-hover`, `--shell-surface-active`, `--shell-hairline`, `--shell-icon-bg`, `--shell-group-open`, `--shell-shadow`, `--shell-background`, `--shell-sidebar-background` | Shell surfaces and elevation. |
|
|
84
|
+
| `--shell-control-muted`, `--shell-nav-foreground`, `--shell-nav-active-border`, `--shell-nav-active-icon-bg`, `--shell-nav-active-icon-fg`, `--shell-nav-context-icon-bg`, `--shell-nav-context-icon-fg` | Shell control and navigation colours. |
|
|
85
|
+
| `--shell-nav-child-fg`, `--shell-nav-child-icon-fg`, `--shell-nav-child-active-bg`, `--shell-nav-child-active-border`, `--shell-navbar-fg`, `--shell-navbar-muted`, `--shell-navbar-hairline` | Child-navigation and header colours. |
|
|
86
|
+
| `--toolbar-popover-width`, `--toolbar-chip-height`, `--toolbar-search-min-width`, `--toolbar-icon-size`, `--radius-toolbar-popover` | Shared CRM toolbar geometry. |
|
|
87
|
+
| `--crm-sidebar-gap`, `--crm-report-copy-max-width`, `--crm-report-metric-min-width`, `--report-stat-min-width` | CRM dashboard and report layout. |
|
|
88
|
+
| `--timeline-list-inset`, `--timeline-line-offset`, `--timeline-marker-offset` | Timeline anatomy. |
|
|
89
|
+
| `--table-header-height`, `--table-cell-padding-x`, `--table-cell-padding-y`, `--crm-table-viewport-offset`, `--crm-table-min-height`, `--crm-table-empty-min-height` | Table row anatomy and CRM viewport sizing. |
|
|
90
|
+
| `--dialog-width`, `--sheet-width`, `--crm-sheet-width`, `--menu-min-width`, `--chart-tooltip-min-width` | Overlay and floating-surface geometry. |
|
|
91
|
+
| `--skeleton-line-height`, `--skeleton-line-height-lg`, `--skeleton-line-height-compact`, `--skeleton-line-height-xs` | Skeleton text-line anatomy. |
|
|
92
|
+
| `--section-icon-size`, `--surface-enter-offset`, `--space-eyebrow-y` | Shared surface icon, entrance, and eyebrow geometry. |
|
|
93
|
+
|
|
94
|
+
All tokens above have neutral defaults in `src/tokens.css`. Values that are derived from semantic tokens automatically follow `themes/mq.css`; a direct MQ declaration is needed only when MQ intentionally differs from the neutral default. `themes/mq-aliases.css` remains the compatibility layer for legacy MQ primitive and typography names.
|
|
95
|
+
|
|
96
|
+
The base stylesheet also provides the global `prefers-reduced-motion: reduce` contract. It disables smooth scrolling and collapses animation and transition timing; skeleton and package styles add static fallbacks where their animated state would otherwise remain off-screen or transparent.
|
package/package.json
CHANGED
package/src/base.css
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
::before,
|
|
6
6
|
::after {
|
|
7
7
|
box-sizing: border-box;
|
|
8
|
+
border-color: var(--border);
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
html,
|
|
@@ -13,7 +14,7 @@
|
|
|
13
14
|
padding: 0;
|
|
14
15
|
background: var(--page-background);
|
|
15
16
|
color: var(--foreground);
|
|
16
|
-
font-family: var(--font-sans)
|
|
17
|
+
font-family: var(--font-sans);
|
|
17
18
|
-webkit-font-smoothing: antialiased;
|
|
18
19
|
-moz-osx-font-smoothing: grayscale;
|
|
19
20
|
text-rendering: optimizeLegibility;
|
|
@@ -30,4 +31,28 @@
|
|
|
30
31
|
input {
|
|
31
32
|
font: inherit;
|
|
32
33
|
}
|
|
34
|
+
|
|
35
|
+
/* Hand-rolled controls keep a visible keyboard state. Component utilities
|
|
36
|
+
can replace this fallback with their own focus-visible treatment. */
|
|
37
|
+
:where(button, a[href], [role="button"]):focus-visible {
|
|
38
|
+
outline: 2px solid currentColor;
|
|
39
|
+
outline-offset: 2px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@media (prefers-reduced-motion: reduce) {
|
|
43
|
+
html {
|
|
44
|
+
scroll-behavior: auto !important;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
*,
|
|
48
|
+
::before,
|
|
49
|
+
::after {
|
|
50
|
+
animation-delay: 0ms !important;
|
|
51
|
+
animation-duration: 0ms !important;
|
|
52
|
+
animation-iteration-count: 1 !important;
|
|
53
|
+
scroll-behavior: auto !important;
|
|
54
|
+
transition-delay: 0ms !important;
|
|
55
|
+
transition-duration: 0ms !important;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
33
58
|
}
|
package/src/surfaces.css
CHANGED
|
@@ -1,93 +1,95 @@
|
|
|
1
1
|
/* ── Shared structural surfaces ───────────────────────────────────────── */
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
/* Layered so Tailwind utilities (p-0, bg-*, …) can override per-instance.
|
|
3
|
+
Unlayered, these beat @layer utilities and e.g. p-0 on the CRM table card
|
|
4
|
+
silently loses to the default card padding. */
|
|
5
|
+
@layer components {
|
|
6
|
+
.surface-card {
|
|
7
|
+
border-radius: var(--radius-card);
|
|
8
|
+
border: 1px solid var(--border-hairline);
|
|
9
|
+
background: var(--surface-card);
|
|
10
|
+
padding: var(--surface-card-padding);
|
|
11
|
+
animation: surface-fade-in 640ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
|
|
12
|
+
}
|
|
9
13
|
|
|
10
|
-
.surface-card.is-light {
|
|
11
|
-
|
|
12
|
-
}
|
|
14
|
+
.surface-card.is-light {
|
|
15
|
+
background: var(--surface-card-light);
|
|
16
|
+
}
|
|
13
17
|
|
|
14
|
-
/* A near-black panel has strong figure/ground in light mode. In dark mode it
|
|
15
|
-
|
|
16
|
-
.brand-panel {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
18
|
+
/* A near-black panel has strong figure/ground in light mode. In dark mode it
|
|
19
|
+
elevates above the page through a lighter accent mix, border, and shadow. */
|
|
20
|
+
.brand-panel {
|
|
21
|
+
--row-sweep-tint: var(--brand-panel-foreground);
|
|
22
|
+
background: var(--brand-panel-surface);
|
|
23
|
+
}
|
|
20
24
|
|
|
21
|
-
.dark .brand-panel,
|
|
22
|
-
.theme-dark .brand-panel {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
25
|
+
.dark .brand-panel,
|
|
26
|
+
.theme-dark .brand-panel {
|
|
27
|
+
border: 1px solid var(--brand-panel-border);
|
|
28
|
+
box-shadow: var(--brand-shadow-lift);
|
|
29
|
+
}
|
|
26
30
|
|
|
27
|
-
.row-hover-sweep {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
transparent,
|
|
37
|
-
color-mix(in srgb, var(--row-sweep-tint, var(--foreground)) 9%, transparent) 50%,
|
|
38
|
-
transparent
|
|
39
|
-
);
|
|
40
|
-
}
|
|
31
|
+
.row-hover-sweep {
|
|
32
|
+
pointer-events: none;
|
|
33
|
+
position: absolute;
|
|
34
|
+
inset: 0;
|
|
35
|
+
border-radius: var(--radius-card);
|
|
36
|
+
opacity: 0;
|
|
37
|
+
transition: opacity 300ms ease;
|
|
38
|
+
background: var(--row-hover-sweep);
|
|
39
|
+
}
|
|
41
40
|
|
|
42
|
-
.group:hover > .row-hover-sweep,
|
|
43
|
-
.group:focus-visible > .row-hover-sweep {
|
|
44
|
-
|
|
41
|
+
.group:hover > .row-hover-sweep,
|
|
42
|
+
.group:focus-visible > .row-hover-sweep {
|
|
43
|
+
opacity: 1;
|
|
44
|
+
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/* ── Canonical tinted-pill recipes ────────────────────────────────────── */
|
|
48
48
|
@layer components {
|
|
49
49
|
.tint-soft {
|
|
50
|
-
border-color:
|
|
51
|
-
background-color:
|
|
50
|
+
border-color: var(--tint-soft-border);
|
|
51
|
+
background-color: var(--tint-soft-bg);
|
|
52
52
|
color: var(--tint-strong);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
.tint-soft:hover {
|
|
56
|
-
background-color:
|
|
56
|
+
background-color: var(--tint-soft-hover);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
.tint-hero {
|
|
60
|
-
border-color:
|
|
61
|
-
background-color:
|
|
62
|
-
color:
|
|
60
|
+
border-color: var(--tint-hero-border);
|
|
61
|
+
background-color: var(--tint-hero-bg);
|
|
62
|
+
color: var(--tint-hero-fg);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
.tint-hero:hover {
|
|
66
|
-
background-color:
|
|
66
|
+
background-color: var(--tint-hero-hover);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
@layer components {
|
|
71
|
+
.section-icon {
|
|
71
72
|
display: flex;
|
|
72
|
-
width:
|
|
73
|
-
height:
|
|
73
|
+
width: var(--section-icon-size);
|
|
74
|
+
height: var(--section-icon-size);
|
|
74
75
|
flex-shrink: 0;
|
|
75
76
|
align-items: center;
|
|
76
77
|
justify-content: center;
|
|
77
|
-
border-radius:
|
|
78
|
+
border-radius: var(--radius-pill);
|
|
78
79
|
background: var(--muted);
|
|
79
80
|
color: var(--muted-foreground);
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
.stat-cell {
|
|
83
|
-
|
|
83
|
+
.stat-cell {
|
|
84
|
+
padding: var(--stat-cell-padding);
|
|
85
|
+
}
|
|
84
86
|
}
|
|
85
87
|
|
|
86
|
-
/* Skeleton shimmer
|
|
88
|
+
/* Skeleton shimmer becomes a static surface under reduced motion. */
|
|
87
89
|
@keyframes surface-fade-in {
|
|
88
90
|
from {
|
|
89
91
|
opacity: 0;
|
|
90
|
-
transform: translateY(
|
|
92
|
+
transform: translateY(var(--surface-enter-offset));
|
|
91
93
|
}
|
|
92
94
|
to {
|
|
93
95
|
opacity: 1;
|
|
@@ -101,17 +103,8 @@
|
|
|
101
103
|
}
|
|
102
104
|
}
|
|
103
105
|
|
|
104
|
-
@
|
|
105
|
-
|
|
106
|
-
100% {
|
|
107
|
-
opacity: 1;
|
|
108
|
-
}
|
|
109
|
-
50% {
|
|
110
|
-
opacity: 0.6;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.skeleton-ghost {
|
|
106
|
+
@layer components {
|
|
107
|
+
.skeleton-ghost {
|
|
115
108
|
position: relative;
|
|
116
109
|
overflow: hidden;
|
|
117
110
|
background: var(--skeleton);
|
|
@@ -132,44 +125,47 @@
|
|
|
132
125
|
}
|
|
133
126
|
|
|
134
127
|
.skeleton-ghost {
|
|
135
|
-
animation:
|
|
128
|
+
animation: none;
|
|
129
|
+
opacity: 1;
|
|
130
|
+
transform: none;
|
|
136
131
|
}
|
|
137
132
|
}
|
|
138
133
|
|
|
139
134
|
.eyebrow {
|
|
140
135
|
display: inline-flex;
|
|
141
136
|
width: fit-content;
|
|
142
|
-
padding:
|
|
143
|
-
border-radius:
|
|
137
|
+
padding: var(--space-eyebrow-y) var(--radius-control);
|
|
138
|
+
border-radius: var(--radius-pill);
|
|
144
139
|
background: var(--brand-surface-tint);
|
|
145
140
|
color: var(--brand-accent);
|
|
146
141
|
font-size: var(--text-ui-label);
|
|
147
142
|
font-weight: var(--font-weight-bold);
|
|
148
|
-
letter-spacing:
|
|
143
|
+
letter-spacing: var(--type-tracking-040);
|
|
149
144
|
text-transform: uppercase;
|
|
150
145
|
}
|
|
151
146
|
|
|
152
147
|
.status {
|
|
153
148
|
display: inline-flex;
|
|
154
149
|
align-items: center;
|
|
155
|
-
gap:
|
|
156
|
-
padding:
|
|
157
|
-
border-radius:
|
|
150
|
+
gap: var(--space-xs);
|
|
151
|
+
padding: var(--space-xs) var(--space-sm);
|
|
152
|
+
border-radius: var(--radius-pill);
|
|
158
153
|
font-size: var(--text-ui-meta);
|
|
159
154
|
font-weight: var(--font-weight-bold);
|
|
160
155
|
}
|
|
161
156
|
|
|
162
157
|
.status.ok {
|
|
163
|
-
background:
|
|
158
|
+
background: var(--surface-status-success);
|
|
164
159
|
color: var(--semantic-success-strong);
|
|
165
160
|
}
|
|
166
161
|
|
|
167
162
|
.status.warn {
|
|
168
|
-
background:
|
|
163
|
+
background: var(--surface-status-warning);
|
|
169
164
|
color: var(--semantic-warning-strong);
|
|
170
165
|
}
|
|
171
166
|
|
|
172
|
-
.status.error {
|
|
173
|
-
|
|
174
|
-
|
|
167
|
+
.status.error {
|
|
168
|
+
background: var(--surface-status-danger);
|
|
169
|
+
color: var(--semantic-danger-strong);
|
|
170
|
+
}
|
|
175
171
|
}
|
package/src/theme.css
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
--color-secondary-foreground: var(--secondary-foreground);
|
|
13
13
|
--color-muted: var(--muted);
|
|
14
14
|
--color-muted-foreground: var(--muted-foreground);
|
|
15
|
+
--color-foreground-muted-accessible: var(--foreground-muted-accessible);
|
|
15
16
|
--color-accent: var(--accent);
|
|
16
17
|
--color-accent-foreground: var(--accent-foreground);
|
|
17
18
|
--color-destructive: var(--destructive);
|
|
@@ -83,6 +84,45 @@
|
|
|
83
84
|
--radius-2xl: var(--radius-panel);
|
|
84
85
|
--radius-3xl: var(--radius-panel);
|
|
85
86
|
|
|
87
|
+
/* Tailwind typography utilities resolve through the same token contract. */
|
|
88
|
+
--font-sans: var(--font-body);
|
|
89
|
+
--font-display: var(--font-heading);
|
|
90
|
+
--font-mono: var(--font-code);
|
|
91
|
+
--font-weight-regular: var(--type-weight-regular);
|
|
92
|
+
--font-weight-normal: var(--type-weight-regular);
|
|
93
|
+
--font-weight-medium: var(--type-weight-medium);
|
|
94
|
+
--font-weight-semibold: var(--type-weight-medium);
|
|
95
|
+
--font-weight-bold: var(--type-weight-bold);
|
|
96
|
+
--font-weight-heavy: var(--type-weight-heavy);
|
|
97
|
+
--font-weight-extrabold: var(--type-weight-heavy);
|
|
98
|
+
--font-weight-black: var(--type-weight-black);
|
|
99
|
+
--text-xs: var(--text-ui-meta);
|
|
100
|
+
--text-xs--line-height: var(--type-leading-133);
|
|
101
|
+
--text-sm: var(--text-ui-body);
|
|
102
|
+
--text-sm--line-height: var(--type-leading-143);
|
|
103
|
+
--text-base: var(--type-paragraph);
|
|
104
|
+
--text-base--line-height: var(--type-leading-normal);
|
|
105
|
+
--text-lg: var(--text-ui-subhead);
|
|
106
|
+
--text-lg--line-height: var(--type-leading-156);
|
|
107
|
+
--text-xl: var(--text-ui-panel-title);
|
|
108
|
+
--text-xl--line-height: var(--type-leading-140);
|
|
109
|
+
--text-2xl: var(--text-ui-heading);
|
|
110
|
+
--text-2xl--line-height: var(--type-leading-133);
|
|
111
|
+
--text-3xl: var(--text-ui-title-sm);
|
|
112
|
+
--text-3xl--line-height: var(--type-leading-120);
|
|
113
|
+
--leading-none: var(--type-leading-none);
|
|
114
|
+
--leading-tight: var(--type-leading-tight);
|
|
115
|
+
--leading-snug: var(--type-leading-snug);
|
|
116
|
+
--leading-normal: var(--type-leading-normal);
|
|
117
|
+
--leading-relaxed: var(--type-leading-relaxed);
|
|
118
|
+
--leading-loose: var(--type-leading-loose);
|
|
119
|
+
--tracking-tighter: var(--type-tracking-n050);
|
|
120
|
+
--tracking-tight: var(--type-tracking-tight);
|
|
121
|
+
--tracking-normal: var(--type-tracking-normal);
|
|
122
|
+
--tracking-wide: var(--type-tracking-wide);
|
|
123
|
+
--tracking-wider: var(--type-tracking-wider);
|
|
124
|
+
--tracking-widest: var(--type-tracking-widest);
|
|
125
|
+
|
|
86
126
|
/* Named spacing keys sit alongside Tailwind's numeric scale. */
|
|
87
127
|
--spacing-2xs: var(--space-2xs);
|
|
88
128
|
--spacing-xs: var(--space-xs);
|