Skip to content

Commit 7783090

Browse files
refactor(tokens,css,link,text,breadcrumbs,input-group,split-button): tokens, CSS foundation, deprecations, tooling DLT-3011 DLT-2961 DLT-3068 DLT-3069 DLT-3070 DLT-3071 DLT-3072 (#1092)
1 parent 16e908a commit 7783090

File tree

88 files changed

+2365
-854
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+2365
-854
lines changed

.claude/rules/css-specificity.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
---
2+
paths:
3+
- "packages/dialtone-css/**"
4+
---
5+
6+
# CSS Specificity Rules
7+
8+
## Target: (0,1,0) Per Selector
9+
10+
Every component selector should aim for a specificity of (0,1,0) — one class. BEM naturally achieves this:
11+
12+
```less
13+
.d-banner {} // (0,1,0) — block
14+
.d-banner__dialog {} // (0,1,0) — element
15+
.d-banner--success {} // (0,1,0) — modifier
16+
```
17+
18+
Modifier overrides should use CSS custom properties, not higher specificity:
19+
20+
```less
21+
// CORRECT — modifier overrides a variable, same specificity
22+
.d-banner { --banner-color: var(--dt-color-surface-primary); }
23+
.d-banner--success { --banner-color: var(--dt-color-surface-success); }
24+
25+
// AVOID — parent modifier targets child, inflates to (0,2,0)
26+
.d-banner--success .d-banner__icon { color: green; }
27+
```
28+
29+
## Element-Type Descendants: Always Wrap in `:where()`
30+
31+
When a component must style bare HTML elements (`th`, `td`, `a`, `button`, `option`, `li`, etc.), wrap them in `:where()` to zero out the element's specificity contribution:
32+
33+
```less
34+
// CORRECT — (0,1,0)
35+
.d-table {
36+
:where(th) { color: var(--table-th-color-text); }
37+
:where(td) { color: var(--table-td-color-text); }
38+
}
39+
40+
// WRONG — (0,1,1), harder to override
41+
.d-table {
42+
th { color: var(--table-th-color-text); }
43+
}
44+
```
45+
46+
## Structural Pseudo-Classes on Elements: Wrap the Full Descendant
47+
48+
When using `:first-child`, `:last-of-type`, `:nth-child()`, etc. on element selectors inside a component, wrap everything in `:where()`:
49+
50+
```less
51+
// CORRECT — (0,1,0)
52+
.d-table {
53+
:where(tbody tr:last-of-type) {
54+
:where(td, th) { border-block-end-width: 0; }
55+
}
56+
}
57+
58+
// WRONG — (0,2,3)
59+
.d-table {
60+
tbody tr:last-of-type {
61+
td, th { border-block-end-width: 0; }
62+
}
63+
}
64+
```
65+
66+
## Do NOT Wrap These
67+
68+
- **The host component class**`.d-table` must retain its (0,1,0) as the anchor selector
69+
- **BEM modifier classes**`.d-table--striped` needs its specificity to override base styles
70+
- **State pseudo-classes**`:hover`, `:disabled`, `:focus-visible`, `:active`, `:checked` where specificity ordering is functional (e.g., `:not(:disabled):hover` must beat `:disabled`)
71+
- **`:not()` / `:has()` containing class selectors** — the specificity reflects semantic complexity, not accidental inflation
72+
73+
## Nesting Depth
74+
75+
- **1 class** (0,1,0): Default. Covers most rules.
76+
- **2 classes** (0,2,0): Acceptable when a parent modifier must affect children (e.g., `.d-tablist--inverted .d-tab`). Prefer CSS custom property overrides when possible.
77+
- **3+ classes**: Avoid. Refactor to use CSS custom properties or restructure the component.
78+
79+
## `@layer` Context
80+
81+
All component styles are inside `@layer dialtone.components`. This means:
82+
83+
- Unlayered consumer CSS always wins regardless of specificity
84+
- Within the layer, lower specificity = easier to extend and override
85+
- Keeping selectors flat benefits consumers who style within the same layer
86+
87+
## Anti-Patterns
88+
89+
- No `#id` selectors
90+
- No bare element selectors without `:where()` wrapping
91+
- No `!important` in component styles (reserved for utility classes)
92+
- No qualifying element selectors on classes (e.g., `div.d-banner` — just use `.d-banner`)
93+
94+
## Reference
95+
96+
Use [Specificity Calculator](https://specificity.keegan.st/) to verify selector specificity values. It supports CSS Selectors Level 4 including `:where()`, `:is()`, and `:has()`.

.claude/rules/documentation-writing.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,44 @@ paths:
88
# Documentation Writing Rules
99

1010
## Use Exact Names — Never Generic Terms
11+
1112
- Package names: `@dialpad/dialtone-vue`, `dialtone-css`, `dialtone-tokens` — never "our library" or "the package"
1213
- Component names: `DtButton`, `DtModal`, `DtInput` — never "the button component"
1314
- Tool names: VuePress, pnpm, Nx, vue-docgen-api, Vitest — never "our build tool" or "the test framework"
1415
- File paths: `packages/dialtone-vue/components/` — never "the components folder"
1516

1617
## Code Examples Must Be Complete
18+
1719
- Include imports, setup, and realistic variable names
1820
- Show runnable code, not pseudo-code
1921
- Add language identifier to all fenced code blocks
2022

2123
## No Placeholder Content
24+
2225
- Never write TODO, TBD, "Coming soon", or empty sections
2326
- If content isn't ready, omit the section entirely
2427

28+
## HTML Code Examples Must Use Refs
29+
30+
In `<code-example-tabs>`, always use the ref-based pattern for `htmlCode`:
31+
32+
```html
33+
<code-well-header>
34+
<dt-notice ref="baseExample" kind="base" title="Base title" />
35+
</code-well-header>
36+
37+
<code-example-tabs
38+
:htmlCode='() => $refs.baseExample'
39+
vueCode='<dt-notice kind="base" title="Base title" />'
40+
showHtmlWarning />
41+
```
42+
43+
- Add `ref="descriptiveName"` to the outermost rendered element inside `<code-well-header>`
44+
- Bind `:htmlCode='() => $refs.refName'` — never use static inline HTML strings (`htmlCode='<div>...'`)
45+
- Always include `showHtmlWarning` when using the ref pattern
46+
- If a `<dt-stack>` or other wrapper surrounds multiple items, put the `ref` on the wrapper
47+
- If there is no `<code-well-header>` (code-only snippet), omit `htmlCode` entirely
48+
2549
## Component Doc Pages (VuePress)
50+
2651
Required sections in order: overview, usage example, variants, props table, events table, slots table, accessibility notes. See `rules/documentation-site.md` for frontmatter and sidebar conventions.

apps/dialtone-documentation/docs/.vuepress/baseComponents/ComponentAccessibleTable.vue

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,34 @@
3535
v-for="({ item, applies, description }) in accessible"
3636
:key="item"
3737
>
38-
<th
39-
scope="row"
40-
class="d-code--sm d-docsite-code"
41-
v-text="item"
42-
/>
43-
<td
44-
class="d-code--sm"
45-
v-text="applies"
46-
/>
47-
<td
48-
class="d-fs-100"
49-
v-html="description"
50-
/>
38+
<th scope="row">
39+
<dt-text
40+
as="span"
41+
kind="code"
42+
size="xs"
43+
class="d-docsite-code"
44+
>
45+
{{ item }}
46+
</dt-text>
47+
</th>
48+
<td>
49+
<dt-text
50+
as="code"
51+
kind="code"
52+
size="xs"
53+
class="code-example--inline"
54+
>
55+
{{ applies }}
56+
</dt-text>
57+
</td>
58+
<td>
59+
<dt-text
60+
kind="body"
61+
size="xs"
62+
>
63+
{{ description }}
64+
</dt-text>
65+
</td>
5166
</tr>
5267
</tbody>
5368
</table>

apps/dialtone-documentation/docs/.vuepress/baseComponents/ComponentClassTable.vue

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,34 @@
3737
>
3838
<th
3939
scope="row"
40-
class="d-code--sm d-docsite-code"
41-
v-text="className.startsWith('data-') ? className : `.${className}`"
42-
/>
43-
<td class="d-code--sm">
44-
<span
40+
>
41+
<dt-text
42+
as="span"
43+
kind="code"
44+
size="xs"
45+
class="d-docsite-code"
46+
>
47+
{{ className.startsWith('data-') ? className : `.${className}` }}
48+
</dt-text>
49+
</th>
50+
<td>
51+
<dt-text
52+
as="code"
53+
kind="code"
54+
size="xs"
4555
class="code-example--inline"
46-
v-text="applies"
47-
/>
56+
>
57+
{{ applies }}
58+
</dt-text>
59+
</td>
60+
<td>
61+
<dt-text
62+
kind="body"
63+
size="xs"
64+
>
65+
{{ description }}
66+
</dt-text>
4867
</td>
49-
<td
50-
class="d-fs-100 d-lh-300"
51-
v-text="description"
52-
/>
5368
</tr>
5469
</tbody>
5570
</table>

apps/dialtone-documentation/docs/.vuepress/baseComponents/ComponentHealthStatusTable.vue

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,9 @@
6464
:key="component.name"
6565
>
6666
<th scope="row">
67-
<router-link
68-
class="d-link"
69-
:to="component.url"
70-
>
67+
<dt-link :to="component.url">
7168
{{ component.name }}
72-
</router-link>
69+
</dt-link>
7370
</th>
7471
<td
7572
tabindex="0"

apps/dialtone-documentation/docs/.vuepress/baseComponents/ComponentVueApiTable.vue

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,16 @@
4646
>
4747
<th scope="row">
4848
<dt-stack gap="300">
49-
<span>
50-
<code class="d-code--sm d-docsite-code">
51-
{{ item.name }}
52-
</code>
53-
</span>
54-
<div
49+
<dt-text as="code" kind="code" size="xs" class="d-docsite-code">
50+
{{ item.name }}
51+
</dt-text>
52+
<dt-text
5553
v-if="item.required"
56-
class="d-fc-critical d-fw-normal"
54+
tone="critical"
55+
strength="normal"
5756
>
5857
required
59-
</div>
58+
</dt-text>
6059
<span v-if="item.deprecated">
6160
<dt-badge
6261
type="critical"
@@ -68,9 +67,9 @@
6867
</th>
6968

7069
<td v-if="withDefault">
71-
<code v-if="item.defaultValue" class="d-code--sm d-docsite-code">
70+
<dt-text v-if="item.defaultValue" as="code" kind="code" size="xs" class="d-docsite-code">
7271
{{ item.defaultValue }}
73-
</code>
72+
</dt-text>
7473
</td>
7574

7675
<td class="vue-api-table">
@@ -89,14 +88,14 @@
8988
<dt-text v-if="index > 0" tone="muted" as="span" kind="body" size="xs">
9089
|
9190
</dt-text>
92-
<code class="d-code--sm d-docsite-code">"{{ value }}"</code>
91+
<dt-text as="code" kind="code" size="xs" class="d-docsite-code">
92+
"{{ value }}"
93+
</dt-text>
9394
</template>
9495
</dt-stack>
95-
<span v-else-if="item.type">
96-
<code class="d-code--sm d-docsite-code">
97-
{{ item.type }}
98-
</code>
99-
</span>
96+
<dt-text v-else-if="item.type" as="code" kind="code" size="xs" class="d-docsite-code">
97+
{{ item.type }}
98+
</dt-text>
10099
<dt-text
101100
v-if="item.description"
102101
as="p"
@@ -113,7 +112,7 @@
113112
as="p"
114113
kind="body"
115114
size="sm"
116-
class="d-fc-critical"
115+
tone="critical"
117116
>
118117
{{ item.deprecatedMessage }}
119118
</dt-text>

apps/dialtone-documentation/docs/.vuepress/baseComponents/DesignColorTable.vue

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,20 @@ const colors = processColorsDocs(props.excludedColors, props.classPrefix);
9393
</th>
9494
<th class="d-lh-300" scope="row">
9595
<span class="d-tt-capitalize" v-text="color.name" />
96-
<span v-if="color.description" class="d-d-block d-fw-normal d-fs-100" v-text="color.description" />
96+
<dt-text v-if="color.description" as="span" kind="body" size="xs" strength="normal" class="d-d-block">
97+
{{ color.description }}
98+
</dt-text>
9799
</th>
98-
<td class="d-code--sm d-docsite-code" v-text="color.tokenName ? `var(${color.tokenName})` : '-'" />
99-
<td class="d-code--sm d-docsite-code" v-text="color.utilityClass" />
100+
<td>
101+
<dt-text as="span" kind="code" size="xs" class="d-docsite-code">
102+
{{ color.tokenName ? `var(${color.tokenName})` : '-' }}
103+
</dt-text>
104+
</td>
105+
<td>
106+
<dt-text as="span" kind="code" size="xs" class="d-docsite-code">
107+
{{ color.utilityClass }}
108+
</dt-text>
109+
</td>
100110
</tr>
101111
</tbody>
102112
</table>

apps/dialtone-documentation/docs/.vuepress/baseComponents/FontUtilitiesNotice.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
>
88
<template #default>
99
Reach for the
10-
<router-link class="d-fw-semibold d-link d-link--muted" to="/components/text">
10+
<dt-link kind="muted" to="/components/text">
1111
DtText
12-
</router-link>
12+
</dt-link>
1313
component before considering any typography utility.
1414
</template>
1515
</dt-notice>

apps/dialtone-documentation/docs/.vuepress/baseComponents/GradientHero.vue

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
<template>
22
<div class="gradient-overlay" style="--overlay-opacity: 0; --text-opacity: .6;">
33
<div class="gradient-overlay__overlay" />
4-
<h1
5-
class="d-headline--xxl d-h100p d-w100p d-d-grid d-plc-center d-ta-center d-fw-medium d-wmx1024 d-m-auto d-p32"
4+
<dt-text
5+
as="h1"
6+
kind="headline"
7+
size="2xl"
8+
strength="medium"
9+
class="d-h100p d-w100p d-d-grid d-plc-center d-ta-center d-wmx1024 d-m-auto d-p32"
610
style="
711
font-size: 64px;
812
font-family: var(--dt-font-family-expressive);
@@ -21,7 +25,7 @@
2125
>
2226
Making every business, a better business through design.
2327
</div>
24-
</h1>
28+
</dt-text>
2529
</div>
2630
</template>
2731

0 commit comments

Comments
 (0)