@pantheon-systems/pds-toolkit-react 2.0.0-alpha.6 → 2.0.0-alpha.8

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.
@@ -0,0 +1,457 @@
1
+ # Tailwind Configuration — Testing Plan
2
+
3
+ Test the v3 preset and v4 theme against real Next.js projects before shipping.
4
+ Create one project per Tailwind version.
5
+
6
+ ---
7
+
8
+ ## Setup: Install PDS Locally
9
+
10
+ Before creating test projects, pack the local PDS package into a tarball.
11
+ This is more reliable than `npm link` and tests exactly what would be published.
12
+
13
+ ```bash
14
+ # In the pds-toolkit-react repo root — run build:lib first so dist/ exists
15
+ npm run build:lib
16
+
17
+ # Pack into a tarball (creates e.g. pantheon-systems-pds-toolkit-react-2.0.0-alpha.7.tgz)
18
+ npm pack
19
+ ```
20
+
21
+ You'll reference this tarball when installing into each test project.
22
+
23
+ ---
24
+
25
+ ## Project A — Tailwind v3
26
+
27
+ ### 1. Create the project
28
+
29
+ ```bash
30
+ npx create-next-app@latest pds-tw-test-v3 \
31
+ --typescript --no-tailwind --no-eslint --no-src-dir --app
32
+ cd pds-tw-test-v3
33
+ npm install tailwindcss@3 postcss autoprefixer
34
+ npx tailwindcss init -p
35
+ ```
36
+
37
+ ### 2. Install PDS locally
38
+
39
+ ```bash
40
+ npm install /path/to/pds-toolkit-react/pantheon-systems-pds-toolkit-react-*.tgz
41
+ ```
42
+
43
+ ### 3. Configure Tailwind
44
+
45
+ Replace `tailwind.config.js` contents:
46
+
47
+ ```js
48
+ /** @type {import('tailwindcss').Config} */
49
+ module.exports = {
50
+ presets: [require('@pantheon-systems/pds-toolkit-react/tailwind/v3/preset')],
51
+ content: ['./app/**/*.{js,ts,jsx,tsx}'],
52
+ };
53
+ ```
54
+
55
+ ### 4. Configure global CSS
56
+
57
+ Add to the top of `app/layout.tsx` (before `./globals.css`):
58
+
59
+ ```tsx
60
+ import '@pantheon-systems/pds-toolkit-react/css/pds-core.css';
61
+ import './globals.css';
62
+ ```
63
+
64
+ Replace `app/globals.css` contents:
65
+
66
+ ```css
67
+ @tailwind base;
68
+ @tailwind components;
69
+ @tailwind utilities;
70
+ ```
71
+
72
+ > **Note:** Import pds-core.css as a JS import in layout.tsx rather than a CSS
73
+ > `@import` in globals.css. Next.js module resolution handles package `exports`
74
+ > maps correctly for JS imports; CSS `@import` resolution is less reliable.
75
+ > The path is `css/pds-core.css` (not `dist/css/`) — the package exports map
76
+ > handles the `dist/` prefix automatically.
77
+
78
+ ### 5. Run the project
79
+
80
+ ```bash
81
+ npm run dev
82
+ ```
83
+
84
+ ---
85
+
86
+ ## Project B — Tailwind v4
87
+
88
+ ### 1. Create the project
89
+
90
+ ```bash
91
+ npx create-next-app@latest pds-tw-test-v4 \
92
+ --typescript --no-tailwind --no-eslint --no-src-dir --app
93
+ cd pds-tw-test-v4
94
+ npm install tailwindcss@latest
95
+ ```
96
+
97
+ ### 2. Install PDS locally
98
+
99
+ ```bash
100
+ npm install /path/to/pds-toolkit-react/pantheon-systems-pds-toolkit-react-*.tgz
101
+ ```
102
+
103
+ ### 3. Configure global CSS
104
+
105
+ Add to the top of `app/layout.tsx` (before `./globals.css`):
106
+
107
+ ```tsx
108
+ import '@pantheon-systems/pds-toolkit-react/css/pds-core.css';
109
+ import './globals.css';
110
+ ```
111
+
112
+ Replace `app/globals.css` contents:
113
+
114
+ ```css
115
+ @import 'tailwindcss/theme' layer(theme);
116
+ @import 'tailwindcss/utilities' layer(utilities);
117
+
118
+ @import '@pantheon-systems/pds-toolkit-react/tailwind/v4/theme.css';
119
+ ```
120
+
121
+ No `tailwind.config.js` needed.
122
+
123
+ ### 4. Run the project
124
+
125
+ ```bash
126
+ npm run dev
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Test Page
132
+
133
+ Replace `app/page.tsx` in both projects with the following. It exercises every
134
+ token category and gives you a single visual reference to review.
135
+
136
+ ```tsx
137
+ export default function Page() {
138
+ return (
139
+ <div className='p-xl font-sans'>
140
+ <h1 className='text-2xl font-semibold leading-s tracking-s mb-xl text-text-default'>
141
+ PDS Tailwind Test Page
142
+ </h1>
143
+
144
+ {/* ── Colors ──────────────────────────────────────────────── */}
145
+ <section className='mb-2xl'>
146
+ <h2 className='text-l font-semibold mb-m text-text-default'>Colors</h2>
147
+
148
+ <div className='flex gap-m flex-wrap mb-m'>
149
+ <div className='p-m rounded-container bg-bg-default border border-border-default'>
150
+ <span className='text-text-default text-s'>bg-default</span>
151
+ </div>
152
+ <div className='p-m rounded-container bg-bg-secondary border border-border-default'>
153
+ <span className='text-text-default text-s'>bg-secondary</span>
154
+ </div>
155
+ <div className='p-m rounded-container bg-bg-reverse'>
156
+ <span className='text-text-reverse text-s'>bg-reverse</span>
157
+ </div>
158
+ </div>
159
+
160
+ <div className='flex gap-m flex-wrap mb-m'>
161
+ <div className='p-m rounded-container bg-status-info-background'>
162
+ <span className='text-status-info-foreground text-s'>info</span>
163
+ </div>
164
+ <div className='p-m rounded-container bg-status-success-background'>
165
+ <span className='text-status-success-foreground text-s'>
166
+ success
167
+ </span>
168
+ </div>
169
+ <div className='p-m rounded-container bg-status-warning-background'>
170
+ <span className='text-status-warning-foreground text-s'>
171
+ warning
172
+ </span>
173
+ </div>
174
+ <div className='p-m rounded-container bg-status-critical-background'>
175
+ <span className='text-status-critical-foreground text-s'>
176
+ critical
177
+ </span>
178
+ </div>
179
+ <div className='p-m rounded-container bg-status-discovery-background'>
180
+ <span className='text-status-discovery-foreground text-s'>
181
+ discovery
182
+ </span>
183
+ </div>
184
+ </div>
185
+
186
+ <div className='flex gap-m flex-wrap'>
187
+ <div className='p-m rounded-container bg-brand-primary'>
188
+ <span className='text-white text-s'>brand-primary</span>
189
+ </div>
190
+ <div className='p-m rounded-container bg-brand-primary-200'>
191
+ <span className='text-text-default text-s'>brand-primary-200</span>
192
+ </div>
193
+ <div className='p-m rounded-container bg-brand-secondary'>
194
+ <span className='text-text-default text-s'>brand-secondary</span>
195
+ </div>
196
+ <div className='p-m rounded-container bg-brand-accent'>
197
+ <span className='text-white text-s'>brand-accent</span>
198
+ </div>
199
+ </div>
200
+ </section>
201
+
202
+ {/* ── Interactive / Links ──────────────────────────────────── */}
203
+ <section className='mb-2xl'>
204
+ <h2 className='text-l font-semibold mb-m text-text-default'>
205
+ Interactive
206
+ </h2>
207
+ <a
208
+ href='#'
209
+ className='text-interactive-link hover:text-interactive-link-hover text-m'
210
+ >
211
+ Interactive link
212
+ </a>
213
+ </section>
214
+
215
+ {/* ── Spacing ─────────────────────────────────────────────── */}
216
+ <section className='mb-2xl'>
217
+ <h2 className='text-l font-semibold mb-m text-text-default'>Spacing</h2>
218
+ <div className='flex gap-xs items-end'>
219
+ {[
220
+ '6xs',
221
+ '5xs',
222
+ '4xs',
223
+ '3xs',
224
+ '2xs',
225
+ 'xs',
226
+ 's',
227
+ 'm',
228
+ 'l',
229
+ 'xl',
230
+ '2xl',
231
+ ].map((size) => (
232
+ <div
233
+ key={size}
234
+ className={`bg-brand-primary-200 w-m`}
235
+ style={{ height: `var(--pds-spacing-${size})` }}
236
+ />
237
+ ))}
238
+ </div>
239
+ <p className='text-s text-text-secondary mt-s'>
240
+ Spacing scale 6xs → 2xl (heights driven by CSS vars, gap uses Tailwind
241
+ spacing)
242
+ </p>
243
+ </section>
244
+
245
+ {/* ── Typography ──────────────────────────────────────────── */}
246
+ <section className='mb-2xl'>
247
+ <h2 className='text-l font-semibold mb-m text-text-default'>
248
+ Typography
249
+ </h2>
250
+ <p className='font-sans text-xs mb-xs text-text-default'>
251
+ font-sans / text-xs — Inter
252
+ </p>
253
+ <p className='font-sans text-m mb-xs text-text-default'>
254
+ font-sans / text-m
255
+ </p>
256
+ <p className='font-sans text-xl font-semibold mb-xs text-text-default'>
257
+ font-sans / text-xl / font-semibold
258
+ </p>
259
+ <p className='font-compact text-xl mb-xs text-text-default'>
260
+ font-compact / text-xl — Inter Tight
261
+ </p>
262
+ <p className='font-serif text-xl mb-xs text-text-default'>
263
+ font-serif / text-xl — IBM Plex Serif
264
+ </p>
265
+ <p className='font-mono text-m text-text-default'>
266
+ font-mono / text-m — Source Code Pro
267
+ </p>
268
+ </section>
269
+
270
+ {/* ── Border Radius ───────────────────────────────────────── */}
271
+ <section className='mb-2xl'>
272
+ <h2 className='text-l font-semibold mb-m text-text-default'>
273
+ Border Radius
274
+ </h2>
275
+ <div className='flex gap-m flex-wrap'>
276
+ {[
277
+ 'rounded',
278
+ 'rounded-button',
279
+ 'rounded-input',
280
+ 'rounded-container',
281
+ 'rounded-bar',
282
+ 'rounded-full',
283
+ ].map((cls) => (
284
+ <div
285
+ key={cls}
286
+ className={`${cls} bg-brand-primary-200 p-m text-s text-text-default`}
287
+ >
288
+ {cls}
289
+ </div>
290
+ ))}
291
+ </div>
292
+ </section>
293
+
294
+ {/* ── Z-index ─────────────────────────────────────────────── */}
295
+ <section className='mb-2xl'>
296
+ <h2 className='text-l font-semibold mb-m text-text-default'>Z-index</h2>
297
+ <div className='relative h-xl'>
298
+ <div className='absolute z-navigation bg-brand-primary-200 p-xs rounded text-xs text-text-default'>
299
+ z-navigation (100)
300
+ </div>
301
+ </div>
302
+ <p className='text-s text-text-secondary mt-xs'>
303
+ Inspect computed style to confirm z-index values resolve correctly.
304
+ </p>
305
+ </section>
306
+
307
+ {/* ── Max Width ───────────────────────────────────────────── */}
308
+ <section className='mb-2xl'>
309
+ <h2 className='text-l font-semibold mb-m text-text-default'>
310
+ Max Width
311
+ </h2>
312
+ <div className='max-w-narrow bg-bg-secondary p-m rounded-container mb-s border border-border-default'>
313
+ <span className='text-s text-text-default'>
314
+ max-w-narrow (1024px)
315
+ </span>
316
+ </div>
317
+ <div className='max-w-standard bg-bg-secondary p-m rounded-container border border-border-default'>
318
+ <span className='text-s text-text-default'>
319
+ max-w-standard (1200px)
320
+ </span>
321
+ </div>
322
+ </section>
323
+
324
+ {/* ── Dark Mode ───────────────────────────────────────────── */}
325
+ <section className='mb-2xl'>
326
+ <h2 className='text-l font-semibold mb-m text-text-default'>
327
+ Dark Mode
328
+ </h2>
329
+ <p className='text-s text-text-secondary mb-m'>
330
+ The box below manually applies the PDS dark theme attribute. Colors
331
+ inside should switch — no Tailwind dark: prefix needed.
332
+ </p>
333
+ <div data-theme='dark' className='p-xl rounded-container'>
334
+ <div className='bg-bg-default p-m rounded-container'>
335
+ <p className='text-text-default text-m font-semibold'>
336
+ Dark bg-default
337
+ </p>
338
+ <p className='text-text-secondary text-s'>Dark text-secondary</p>
339
+ <div className='mt-m p-m rounded-container bg-status-info-background'>
340
+ <span className='text-status-info-foreground text-s'>
341
+ Dark status-info
342
+ </span>
343
+ </div>
344
+ </div>
345
+ </div>
346
+ </section>
347
+ </div>
348
+ );
349
+ }
350
+ ```
351
+
352
+ ---
353
+
354
+ ## Checklist
355
+
356
+ Work through both projects and check each item. Open browser DevTools to
357
+ inspect computed styles when you need to verify a value resolves correctly.
358
+
359
+ ### Preflight
360
+
361
+ - [ ] Browser default margins on `<h1>`, `<p>`, `<ul>` are **not** reset (preflight is disabled — headings should still have default browser size/weight until you explicitly set them)
362
+ - [ ] PDS base styles from `pds-core.css` are applied (e.g. correct font on `body`)
363
+ - [ ] Borders only appear on elements that explicitly include `border-solid` — no global border bleed (preflight normally sets `border-style: solid` globally; without it you must add `border-solid` per element)
364
+
365
+ ### Colors — backgrounds and foregrounds
366
+
367
+ - [ ] `bg-bg-default` renders white (light mode)
368
+ - [ ] `bg-bg-secondary` renders light gray
369
+ - [ ] `bg-bg-reverse` renders dark
370
+ - [ ] `text-fg-reverse` is visible on `bg-bg-reverse`
371
+ - [ ] `text-fg-default` and `text-fg-secondary` are both visible on light surfaces
372
+
373
+ ### Colors — status
374
+
375
+ - [ ] All five status backgrounds render distinct colors (info, success, warning, critical, discovery)
376
+ - [ ] Status foreground text is readable on its status background
377
+ - [ ] Status border color is visible when `border border-solid border-status-info-border` is applied
378
+ - [ ] Status dot colors render as small circles
379
+
380
+ ### Colors — data visualization
381
+
382
+ - [ ] `bg-datavis-1` through `bg-datavis-5` each render a distinct color
383
+
384
+ ### Dark mode
385
+
386
+ - [ ] Inside `data-theme="dark"`, `bg-bg-default` renders dark (not white)
387
+ - [ ] `text-fg-default` is light-colored inside the dark section
388
+ - [ ] Status colors shift appropriately in dark mode
389
+ - [ ] No Tailwind `dark:` prefix was needed — color changes happen via CSS vars
390
+
391
+ ### Interactive
392
+
393
+ - [ ] `text-interactive-link` renders the PDS link color
394
+ - [ ] `:hover` changes to `text-interactive-link-hover` (test in browser)
395
+
396
+ ### Spacing
397
+
398
+ - [ ] `gap-m`, `p-xl`, `mb-2xl` all produce visible spacing
399
+ - [ ] Inspect computed style on a `p-m` element — should show the rem value from `--pds-spacing-m`
400
+ - [ ] `gap-xs` in the spacing row produces tighter gaps than `gap-m`
401
+
402
+ ### Typography
403
+
404
+ - [ ] `text-xs` is noticeably smaller than `text-xl`
405
+ - [ ] `font-semibold` is visually heavier than `font-normal`
406
+ - [ ] PDS body font (Inter) is applied globally via `pds-core.css` — no Tailwind font-family utility needed
407
+
408
+ ### Border radius
409
+
410
+ - [ ] `rounded` (DEFAULT) is slightly rounded
411
+ - [ ] `rounded-input` is slightly more rounded than `rounded`
412
+ - [ ] `rounded-container` is more rounded than `rounded-input`
413
+ - [ ] `rounded-button` and `rounded-bar` are pill-shaped (both map to `--pds-border-radius-button` / `--pds-border-radius-bar`)
414
+
415
+ ### Z-index
416
+
417
+ - [ ] Inspect computed `z-index` on `z-navigation` element — should be `100`
418
+ - [ ] `z-modal` should compute to `900`
419
+
420
+ ### Max width
421
+
422
+ - [ ] `max-w-narrow` constrains width at 1024px
423
+ - [ ] `max-w-standard` is wider than `max-w-narrow`
424
+ - [ ] `max-w-wide` is wider than `max-w-standard`
425
+ - [ ] `max-w-x-wide` is wider than `max-w-wide`
426
+ - [ ] All four blocks visually confirm the width difference on a wide viewport
427
+
428
+ ---
429
+
430
+ ## v4-Specific Checks
431
+
432
+ - [ ] No `tailwind.config.js` exists in the project — v4 works without it
433
+ - [ ] Removing the `@import 'tailwindcss/theme'` line breaks utilities (confirms the layer import is working)
434
+ - [ ] Swap to `@import 'tailwindcss'` (the shorthand) — verify preflight fires and breaks PDS styles, then revert
435
+ - [ ] Inspect `--color-bg-default` in DevTools `:root` — should be present as a CSS custom property
436
+
437
+ ## v3-Specific Checks
438
+
439
+ - [ ] `tailwind.config.js` preset resolves without error on startup
440
+ - [ ] Running `npx tailwindcss --content './app/**/*.tsx' --input ./app/globals.css` produces output CSS with PDS class names
441
+ - [ ] `p-4` generates output and resolves to the same value as `p-m` (confirms numeric alias is working)
442
+ - [ ] `p-7` generates no output (confirms unmapped in-between values are intentionally excluded)
443
+ - [ ] Adding a truly unknown class (e.g. `p-99`) produces nothing in the output
444
+
445
+ ---
446
+
447
+ ## If Something Doesn't Work
448
+
449
+ | Symptom | Likely cause |
450
+ | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
451
+ | All colors render as empty / transparent | `pds-core.css` not loaded before Tailwind, or CSS vars not resolving |
452
+ | Preflight styles are active | v4: Using `@import 'tailwindcss'` shorthand instead of individual layers |
453
+ | Utility classes not generated | v3: `content` array doesn't match file paths; v4: files outside auto-scan root |
454
+ | Font doesn't change to Inter | Google Fonts not loaded — pds-core.css includes the font import, confirm it is loading before Tailwind |
455
+ | Dark mode section looks identical to light | `pds-core.css` dark mode vars may need `data-theme="dark"` on a parent element — check the PDS dark mode implementation |
456
+ | `rounded-button` same as `rounded` | Expected — they share the same token value (`--pds-border-radius-button` = `--pds-border-radius-default`) |
457
+ | Borders invisible despite `border` class | Preflight is disabled — add `border-solid` alongside every `border` class. Without preflight, `border-style` defaults to `none` |
@@ -0,0 +1,238 @@
1
+ /**
2
+ * PDS Tailwind v3 Preset
3
+ *
4
+ * Maps Pantheon Design System tokens to Tailwind CSS v3 utilities.
5
+ * Use as a preset in tailwind.config.js — replaces Tailwind's default
6
+ * color, spacing, and typography scales with PDS values.
7
+ *
8
+ * Requirements:
9
+ * - pds-core.css must be loaded globally (provides --pds-* CSS variables)
10
+ * - Tailwind v3.x
11
+ *
12
+ * Usage:
13
+ * // tailwind.config.js
14
+ * module.exports = {
15
+ * presets: [require('@pantheon-systems/pds-toolkit-react/tailwind/v3/preset')],
16
+ * content: ['./src/**\/*.{js,ts,jsx,tsx}'],
17
+ * };
18
+ */
19
+
20
+ /** @type {import('tailwindcss').Config} */
21
+ module.exports = {
22
+ corePlugins: {
23
+ // Disable Tailwind's CSS reset — PDS provides its own base styles.
24
+ // Enabling preflight alongside PDS will cause style conflicts.
25
+ preflight: false,
26
+ },
27
+ theme: {
28
+ // ─── Colors ──────────────────────────────────────────────────────────────
29
+ // All values reference PDS CSS custom properties so dark mode and token
30
+ // updates are reflected automatically. Requires pds-core.css to be loaded.
31
+ //
32
+ // Note: opacity modifiers (e.g. bg-bg-default/50) are not supported with
33
+ // CSS variable color references.
34
+ colors: {
35
+ // Backgrounds — use as bg-bg-default, bg-bg-secondary, bg-bg-reverse
36
+ bg: {
37
+ default: 'var(--pds-color-bg-default)',
38
+ secondary: 'var(--pds-color-bg-default-secondary)',
39
+ reverse: 'var(--pds-color-bg-reverse)',
40
+ },
41
+ // General foregrounds (icons, decorative elements)
42
+ fg: {
43
+ default: 'var(--pds-color-fg-default)',
44
+ secondary: 'var(--pds-color-fg-default-secondary)',
45
+ reverse: 'var(--pds-color-fg-reverse)',
46
+ },
47
+ // Borders — use as border-border-default, border-border-input, etc.
48
+ border: {
49
+ default: 'var(--pds-color-border-default)',
50
+ input: 'var(--pds-color-border-input)',
51
+ separator: 'var(--pds-color-border-separator)',
52
+ brand: 'var(--pds-color-border-brand)',
53
+ },
54
+ // Interactive elements (links, focus rings)
55
+ interactive: {
56
+ focus: 'var(--pds-color-interactive-focus)',
57
+ 'bg-hover': 'var(--pds-color-interactive-background-hover)',
58
+ 'bg-active': 'var(--pds-color-interactive-background-active)',
59
+ link: 'var(--pds-color-interactive-link-default)',
60
+ 'link-hover': 'var(--pds-color-interactive-link-hover)',
61
+ 'link-active': 'var(--pds-color-interactive-link-active)',
62
+ 'link-visited': 'var(--pds-color-interactive-link-visited)',
63
+ 'reverse-focus': 'var(--pds-color-interactive-reverse-focus)',
64
+ 'reverse-link': 'var(--pds-color-interactive-reverse-link-default)',
65
+ 'reverse-link-hover': 'var(--pds-color-interactive-reverse-link-hover)',
66
+ 'reverse-link-active':
67
+ 'var(--pds-color-interactive-reverse-link-active)',
68
+ 'reverse-link-visited':
69
+ 'var(--pds-color-interactive-reverse-link-visited)',
70
+ },
71
+ // Status colors — background/foreground/border/dot per status type
72
+ status: {
73
+ info: {
74
+ background: 'var(--pds-color-status-info-background)',
75
+ foreground: 'var(--pds-color-status-info-foreground)',
76
+ border: 'var(--pds-color-status-info-border)',
77
+ dot: 'var(--pds-color-status-info-dot)',
78
+ },
79
+ success: {
80
+ background: 'var(--pds-color-status-success-background)',
81
+ foreground: 'var(--pds-color-status-success-foreground)',
82
+ border: 'var(--pds-color-status-success-border)',
83
+ dot: 'var(--pds-color-status-success-dot)',
84
+ },
85
+ warning: {
86
+ background: 'var(--pds-color-status-warning-background)',
87
+ foreground: 'var(--pds-color-status-warning-foreground)',
88
+ border: 'var(--pds-color-status-warning-border)',
89
+ dot: 'var(--pds-color-status-warning-dot)',
90
+ },
91
+ critical: {
92
+ background: 'var(--pds-color-status-critical-background)',
93
+ foreground: 'var(--pds-color-status-critical-foreground)',
94
+ border: 'var(--pds-color-status-critical-border)',
95
+ dot: 'var(--pds-color-status-critical-dot)',
96
+ },
97
+ discovery: {
98
+ background: 'var(--pds-color-status-discovery-background)',
99
+ foreground: 'var(--pds-color-status-discovery-foreground)',
100
+ border: 'var(--pds-color-status-discovery-border)',
101
+ dot: 'var(--pds-color-status-discovery-dot)',
102
+ },
103
+ },
104
+ // Overlay (e.g. modal backdrops)
105
+ overlay: 'var(--pds-color-overlay)',
106
+ // Data visualization palette
107
+ datavis: {
108
+ 1: 'var(--pds-color-datavis-1)',
109
+ 2: 'var(--pds-color-datavis-2)',
110
+ 3: 'var(--pds-color-datavis-3)',
111
+ 4: 'var(--pds-color-datavis-4)',
112
+ 5: 'var(--pds-color-datavis-5)',
113
+ },
114
+ },
115
+
116
+ // ─── Spacing ─────────────────────────────────────────────────────────────
117
+ // Primary scale uses PDS named keys: p-xs, m-xl, gap-m, etc.
118
+ // Numeric aliases map common Tailwind values to the nearest PDS token so
119
+ // that p-4 / p-6 / etc. still work and stay in sync if tokens change.
120
+ spacing: {
121
+ 0: '0px',
122
+ // PDS named scale
123
+ '5xs': 'var(--pds-spacing-5xs)',
124
+ '4xs': 'var(--pds-spacing-4xs)',
125
+ '3xs': 'var(--pds-spacing-3xs)',
126
+ '2xs': 'var(--pds-spacing-2xs)',
127
+ xs: 'var(--pds-spacing-xs)',
128
+ s: 'var(--pds-spacing-s)',
129
+ m: 'var(--pds-spacing-m)',
130
+ l: 'var(--pds-spacing-l)',
131
+ xl: 'var(--pds-spacing-xl)',
132
+ '2xl': 'var(--pds-spacing-2xl)',
133
+ '3xl': 'var(--pds-spacing-3xl)',
134
+ '4xl': 'var(--pds-spacing-4xl)',
135
+ '5xl': 'var(--pds-spacing-5xl)',
136
+ '6xl': 'var(--pds-spacing-6xl)',
137
+ '7xl': 'var(--pds-spacing-7xl)',
138
+ '8xl': 'var(--pds-spacing-8xl)',
139
+ '9xl': 'var(--pds-spacing-9xl)',
140
+ // Numeric aliases → PDS tokens (p-4 = p-m, p-6 = p-xl, etc.)
141
+ // Values reference CSS variables so they stay in sync if tokens change.
142
+ 0.5: 'var(--pds-spacing-5xs)', // 0.125rem
143
+ 1: 'var(--pds-spacing-4xs)', // 0.25rem
144
+ 1.5: 'var(--pds-spacing-3xs)', // 0.375rem
145
+ 2: 'var(--pds-spacing-2xs)', // 0.5rem
146
+ 2.5: 'var(--pds-spacing-xs)', // 0.625rem
147
+ 3: 'var(--pds-spacing-s)', // 0.75rem
148
+ 4: 'var(--pds-spacing-m)', // 1rem
149
+ 5: 'var(--pds-spacing-l)', // 1.25rem
150
+ 6: 'var(--pds-spacing-xl)', // 1.5rem
151
+ 8: 'var(--pds-spacing-2xl)', // 2rem
152
+ 10: 'var(--pds-spacing-3xl)', // 2.5rem
153
+ 12: 'var(--pds-spacing-4xl)', // 3rem
154
+ 16: 'var(--pds-spacing-5xl)', // 4rem
155
+ 20: 'var(--pds-spacing-6xl)', // 5rem
156
+ 24: 'var(--pds-spacing-7xl)', // 6rem
157
+ 32: 'var(--pds-spacing-8xl)', // 8rem
158
+ 40: 'var(--pds-spacing-9xl)', // 10rem
159
+ },
160
+
161
+ // ─── Typography ──────────────────────────────────────────────────────────
162
+ // Font families are intentionally excluded. PDS applies font families
163
+ // automatically via pds-core.css (body, headings, code blocks, etc.).
164
+ // Teams should not override font families via Tailwind utilities.
165
+ fontSize: {
166
+ xs: 'var(--pds-typography-size-xs)',
167
+ s: 'var(--pds-typography-size-s)',
168
+ m: 'var(--pds-typography-size-m)',
169
+ l: 'var(--pds-typography-size-l)',
170
+ xl: 'var(--pds-typography-size-xl)',
171
+ '2xl': 'var(--pds-typography-size-2xl)',
172
+ '3xl': 'var(--pds-typography-size-3xl)',
173
+ '4xl': 'var(--pds-typography-size-4xl)',
174
+ '5xl': 'var(--pds-typography-size-5xl)',
175
+ '6xl': 'var(--pds-typography-size-6xl)',
176
+ '7xl': 'var(--pds-typography-size-7xl)',
177
+ '8xl': 'var(--pds-typography-size-8xl)',
178
+ '9xl': 'var(--pds-typography-size-9xl)',
179
+ },
180
+ fontWeight: {
181
+ light: 'var(--pds-typography-fw-light)',
182
+ normal: 'var(--pds-typography-fw-regular)',
183
+ medium: 'var(--pds-typography-fw-medium)',
184
+ semibold: 'var(--pds-typography-fw-semibold)',
185
+ bold: 'var(--pds-typography-fw-bold)',
186
+ },
187
+ lineHeight: {
188
+ s: 'var(--pds-typography-lh-s)',
189
+ m: 'var(--pds-typography-lh-m)',
190
+ l: 'var(--pds-typography-lh-l)',
191
+ xl: 'var(--pds-typography-lh-xl)',
192
+ },
193
+ letterSpacing: {
194
+ s: 'var(--pds-typography-ls-s)',
195
+ m: 'var(--pds-typography-ls-m)',
196
+ l: 'var(--pds-typography-ls-l)',
197
+ xl: 'var(--pds-typography-ls-xl)',
198
+ },
199
+
200
+ // ─── Border ──────────────────────────────────────────────────────────────
201
+ borderRadius: {
202
+ DEFAULT: 'var(--pds-border-radius-default)',
203
+ button: 'var(--pds-border-radius-button)',
204
+ input: 'var(--pds-border-radius-input)',
205
+ container: 'var(--pds-border-radius-container)',
206
+ bar: 'var(--pds-border-radius-bar)',
207
+ },
208
+ borderWidth: {
209
+ 0: '0px',
210
+ DEFAULT: 'var(--pds-border-width-default)',
211
+ thicker: 'var(--pds-border-width-thicker)',
212
+ },
213
+
214
+ // ─── Z-index ─────────────────────────────────────────────────────────────
215
+ zIndex: {
216
+ 0: '0',
217
+ navigation: 'var(--pds-z-index-navigation)',
218
+ dropdown: 'var(--pds-z-index-dropdown)',
219
+ notifications: 'var(--pds-z-index-notifications)',
220
+ overlay: 'var(--pds-z-index-overlay)',
221
+ modal: 'var(--pds-z-index-modal)',
222
+ max: 'var(--pds-z-index-max)',
223
+ },
224
+
225
+ // ─── Max Width ───────────────────────────────────────────────────────────
226
+ // PDS standard container widths — use to match PDS layout components.
227
+ maxWidth: {
228
+ none: 'none',
229
+ full: '100%',
230
+ narrow: 'var(--pds-container-max-width-narrow)',
231
+ standard: 'var(--pds-container-max-width-standard)',
232
+ wide: 'var(--pds-container-max-width-wide)',
233
+ 'x-wide': 'var(--pds-container-max-width-x-wide)',
234
+ },
235
+
236
+ extend: {},
237
+ },
238
+ };