kmcom-nuxt-layers 6.0.0 → 6.1.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/docs/adr/0003-modular-step-system-replaces-fluid-clamps.md +58 -0
- package/layers/core/app/assets/css/tokens/spacing-fluid.css +24 -19
- package/layers/core/app/components/Element.test.ts +2 -2
- package/layers/core/app/composables/useLayoutAttrs.test.ts +35 -5
- package/layers/core/app/composables/useLayoutAttrs.ts +1 -1
- package/layers/core/app/utils/resolveElementStyle.test.ts +2 -2
- package/layers/design-system/theming/app/types/designSystem.ts +21 -17
- package/layers/design-system/typography/app/app.config.ts +26 -0
- package/layers/design-system/typography/app/assets/css/typography.css +216 -187
- package/layers/design-system/typography/app/components/Typography/CodeBlock.vue +4 -4
- package/layers/design-system/typography/app/components/Typography/Headline.test.ts +36 -0
- package/layers/design-system/typography/app/components/Typography/Headline.vue +20 -21
- package/layers/design-system/typography/app/components/Typography/QuoteBlock.vue +4 -4
- package/layers/design-system/typography/app/components/Typography/RepeatText.vue +7 -6
- package/layers/design-system/typography/app/components/Typography/index.test.ts +31 -0
- package/layers/design-system/typography/app/components/Typography/index.vue +10 -8
- package/layers/design-system/typography/app/composables/typography.test.ts +53 -0
- package/layers/design-system/typography/app/composables/typography.ts +28 -43
- package/layers/design-system/typography/app/types/typography.ts +5 -32
- package/layers/structure/grid/app/assets/css/grid.css +11 -7
- package/package.json +1 -1
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
// Explicit import so Headline mounts under vitest's 'vue' project (no Nuxt auto-imports)
|
|
3
|
+
// — same exemption as ElementTw.vue (eslint.config.mjs).
|
|
4
|
+
import { computed } from 'vue'
|
|
5
|
+
|
|
2
6
|
import { useColor } from '../../composables/color'
|
|
3
7
|
import { useTypography } from '../../composables/typography'
|
|
4
8
|
import type { UiColors } from '../../types/colors'
|
|
5
9
|
import type {
|
|
6
|
-
FluidFontSize,
|
|
7
10
|
FontFamily,
|
|
8
11
|
FontLeading,
|
|
9
12
|
FontSize,
|
|
@@ -13,6 +16,7 @@
|
|
|
13
16
|
FontWidth,
|
|
14
17
|
TextAlign,
|
|
15
18
|
TextTransform,
|
|
19
|
+
TypeStep,
|
|
16
20
|
} from '../../types/typography'
|
|
17
21
|
|
|
18
22
|
const {
|
|
@@ -20,13 +24,13 @@
|
|
|
20
24
|
weight = 'font-bold',
|
|
21
25
|
width = 'font-stretch-normal',
|
|
22
26
|
slant = 'normal',
|
|
23
|
-
leading =
|
|
27
|
+
leading = undefined,
|
|
24
28
|
tracking = 'tracking-tight',
|
|
25
29
|
align = 'left',
|
|
26
30
|
transform = 'none',
|
|
27
31
|
color = undefined,
|
|
28
32
|
size = undefined,
|
|
29
|
-
|
|
33
|
+
step = undefined,
|
|
30
34
|
font = undefined,
|
|
31
35
|
} = defineProps<{
|
|
32
36
|
level?: 1 | 2 | 3 | 4 | 5 | 6
|
|
@@ -39,43 +43,38 @@
|
|
|
39
43
|
transform?: TextTransform
|
|
40
44
|
color?: UiColors
|
|
41
45
|
size?: FontSize
|
|
42
|
-
|
|
46
|
+
step?: TypeStep
|
|
43
47
|
font?: FontFamily
|
|
44
48
|
}>()
|
|
45
49
|
const tag = computed(() => `h${level}` as const)
|
|
46
50
|
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const appliedFluidSize = computed(() =>
|
|
59
|
-
size !== undefined ? undefined : (fluidSize ?? defaultFluidSizes[level])
|
|
60
|
-
)
|
|
51
|
+
// Display hierarchy by default: each level sits one scale step below the previous, starting
|
|
52
|
+
// at the fluid display step, so every level stays fluid (h1 51 → 97px, h2 40 → 77px …). Set as
|
|
53
|
+
// --step rather than a class so typography.css's h1–h6 base rules size it. Only when neither
|
|
54
|
+
// `step` nor `size` is passed; an explicit step beats size.
|
|
55
|
+
const defaultStepStyle = computed(() => {
|
|
56
|
+
if (step !== undefined || size !== undefined) return undefined
|
|
57
|
+
const below = level - 1
|
|
58
|
+
return { '--step': below ? `calc(var(--step-display) - ${below})` : 'var(--step-display)' }
|
|
59
|
+
})
|
|
61
60
|
|
|
62
61
|
const { classes } = useTypography(() => ({
|
|
63
62
|
weight,
|
|
64
63
|
width,
|
|
65
64
|
slant,
|
|
66
|
-
leading,
|
|
65
|
+
...(leading !== undefined && { leading }),
|
|
67
66
|
tracking,
|
|
68
67
|
align,
|
|
69
68
|
transform,
|
|
70
69
|
...(font !== undefined && { font }),
|
|
71
70
|
...(size !== undefined && { size }),
|
|
72
|
-
...(
|
|
71
|
+
...(step !== undefined && { step }),
|
|
73
72
|
}))
|
|
74
73
|
const colorClass = useColor(() => color, 'text')
|
|
75
74
|
</script>
|
|
76
75
|
|
|
77
76
|
<template>
|
|
78
|
-
<component :is="tag" :class="[classes, colorClass]">
|
|
77
|
+
<component :is="tag" :class="[classes, colorClass]" :style="defaultStepStyle">
|
|
79
78
|
<slot />
|
|
80
79
|
</component>
|
|
81
80
|
</template>
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { useTypography } from '../../composables/typography'
|
|
4
4
|
import type { UiColors } from '../../types/colors'
|
|
5
5
|
import type {
|
|
6
|
-
FluidFontSize,
|
|
7
6
|
FontFamily,
|
|
8
7
|
FontLeading,
|
|
9
8
|
FontSize,
|
|
@@ -13,6 +12,7 @@
|
|
|
13
12
|
FontWidth,
|
|
14
13
|
TextAlign,
|
|
15
14
|
TextTransform,
|
|
15
|
+
TypeStep,
|
|
16
16
|
} from '../../types/typography'
|
|
17
17
|
|
|
18
18
|
const {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
transform = 'none',
|
|
26
26
|
color = undefined,
|
|
27
27
|
size = undefined,
|
|
28
|
-
|
|
28
|
+
step = undefined,
|
|
29
29
|
font = undefined,
|
|
30
30
|
} = defineProps<{
|
|
31
31
|
weight?: FontWeight
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
transform?: TextTransform
|
|
38
38
|
color?: UiColors
|
|
39
39
|
size?: FontSize
|
|
40
|
-
|
|
40
|
+
step?: TypeStep
|
|
41
41
|
font?: FontFamily
|
|
42
42
|
}>()
|
|
43
43
|
const { classes } = useTypography(() => ({
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
transform,
|
|
51
51
|
...(font !== undefined && { font }),
|
|
52
52
|
...(size !== undefined && { size }),
|
|
53
|
-
...(
|
|
53
|
+
...(step !== undefined && { step }),
|
|
54
54
|
}))
|
|
55
55
|
const colorClass = useColor(() => color, 'text')
|
|
56
56
|
</script>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { useRepeatFill } from '../../composables/repeatFill'
|
|
4
4
|
import { useTypography } from '../../composables/typography'
|
|
5
5
|
import type { UiColors } from '../../types/colors'
|
|
6
|
-
import type {
|
|
6
|
+
import type { FontWeight, TypeStep, TypographyTag } from '../../types/typography'
|
|
7
7
|
|
|
8
8
|
const {
|
|
9
9
|
rows = 1,
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
repeat = 'auto',
|
|
13
13
|
separator = '',
|
|
14
14
|
weight = undefined,
|
|
15
|
-
|
|
15
|
+
step = 7,
|
|
16
16
|
color = undefined,
|
|
17
17
|
offset = [],
|
|
18
18
|
letterSpacing = undefined,
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
repeat?: number | 'auto'
|
|
29
29
|
separator?: string
|
|
30
30
|
weight?: FontWeight | FontWeight[]
|
|
31
|
-
|
|
31
|
+
step?: TypeStep | TypeStep[]
|
|
32
32
|
color?: UiColors | UiColors[]
|
|
33
33
|
offset?: string[]
|
|
34
34
|
letterSpacing?: string | string[]
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
|
|
50
50
|
const rowText = (i: number) => pick(text, i) ?? ''
|
|
51
51
|
const rowWeight = (i: number) => pick(weight, i)
|
|
52
|
-
const
|
|
52
|
+
const rowStep = (i: number) => pick(step, i)
|
|
53
53
|
const rowColor = (i: number) => pick(color, i)
|
|
54
54
|
const rowOffset = (i: number) => offset[i] ?? '0'
|
|
55
55
|
const rowLetterSpacing = (i: number) => pick(letterSpacing, i)
|
|
@@ -58,10 +58,11 @@
|
|
|
58
58
|
const rowClasses = computed(() =>
|
|
59
59
|
Array.from({ length: rows }, (_, i) => {
|
|
60
60
|
const weight = rowWeight(i)
|
|
61
|
-
const
|
|
61
|
+
const step = rowStep(i)
|
|
62
62
|
return useTypography({
|
|
63
|
+
leading: 'leading-normal',
|
|
63
64
|
...(weight !== undefined && { weight }),
|
|
64
|
-
...(
|
|
65
|
+
...(step !== undefined && { step }),
|
|
65
66
|
}).classes.value
|
|
66
67
|
})
|
|
67
68
|
)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils'
|
|
2
|
+
import { describe, expect, it } from 'vite-plus/test'
|
|
3
|
+
|
|
4
|
+
import ElementTw from '#layers/core/app/components/ElementTw.vue'
|
|
5
|
+
|
|
6
|
+
import Typography from './index.vue'
|
|
7
|
+
|
|
8
|
+
const classesOf = (props: Record<string, unknown> = {}) =>
|
|
9
|
+
mount(Typography, {
|
|
10
|
+
props,
|
|
11
|
+
slots: { default: 'Body copy' },
|
|
12
|
+
global: { components: { ElementTw } },
|
|
13
|
+
}).classes()
|
|
14
|
+
|
|
15
|
+
describe('Typography size', () => {
|
|
16
|
+
it('inherits the surrounding size by default instead of pinning text-base', () => {
|
|
17
|
+
expect(classesOf()).not.toContain('text-base')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('inherits the body line height by default', () => {
|
|
21
|
+
expect(classesOf().filter((c) => c.startsWith('leading-'))).toEqual([])
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('still applies an explicit size', () => {
|
|
25
|
+
expect(classesOf({ size: 'lg' })).toContain('text-lg')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('applies an explicit step', () => {
|
|
29
|
+
expect(classesOf({ step: 1 })).toContain('text-step-1')
|
|
30
|
+
})
|
|
31
|
+
})
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { useTypography } from '../../composables/typography'
|
|
4
4
|
import type { UiColors } from '../../types/colors'
|
|
5
5
|
import type {
|
|
6
|
-
FluidFontSize,
|
|
7
6
|
FontFamily,
|
|
8
7
|
FontLeading,
|
|
9
8
|
FontSize,
|
|
@@ -13,6 +12,7 @@
|
|
|
13
12
|
FontWidth,
|
|
14
13
|
TextAlign,
|
|
15
14
|
TextTransform,
|
|
15
|
+
TypeStep,
|
|
16
16
|
TypographyTag,
|
|
17
17
|
} from '../../types/typography'
|
|
18
18
|
|
|
@@ -21,13 +21,15 @@
|
|
|
21
21
|
weight = 'font-normal',
|
|
22
22
|
width = 'font-stretch-normal',
|
|
23
23
|
slant = 'normal',
|
|
24
|
-
leading =
|
|
24
|
+
leading = undefined,
|
|
25
25
|
tracking = 'tracking-normal',
|
|
26
26
|
align = 'left',
|
|
27
27
|
transform = 'none',
|
|
28
28
|
color = undefined,
|
|
29
|
-
size
|
|
30
|
-
|
|
29
|
+
// No default size: body copy inherits the body step (20 → 24px) rather than pinning
|
|
30
|
+
// Tailwind's 16px text-base inside it.
|
|
31
|
+
size = undefined,
|
|
32
|
+
step = undefined,
|
|
31
33
|
font = undefined,
|
|
32
34
|
} = defineProps<{
|
|
33
35
|
tag?: TypographyTag
|
|
@@ -40,20 +42,20 @@
|
|
|
40
42
|
transform?: TextTransform
|
|
41
43
|
color?: UiColors
|
|
42
44
|
size?: FontSize
|
|
43
|
-
|
|
45
|
+
step?: TypeStep
|
|
44
46
|
font?: FontFamily
|
|
45
47
|
}>()
|
|
46
48
|
const { classes } = useTypography(() => ({
|
|
47
49
|
weight,
|
|
48
50
|
width,
|
|
49
51
|
slant,
|
|
50
|
-
leading,
|
|
52
|
+
...(leading !== undefined && { leading }),
|
|
51
53
|
tracking,
|
|
52
54
|
align,
|
|
53
55
|
transform,
|
|
54
|
-
size,
|
|
56
|
+
...(size !== undefined && { size }),
|
|
55
57
|
...(font !== undefined && { font }),
|
|
56
|
-
...(
|
|
58
|
+
...(step !== undefined && { step }),
|
|
57
59
|
}))
|
|
58
60
|
const colorClass = useColor(() => color, 'text')
|
|
59
61
|
</script>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from 'vite-plus/test'
|
|
4
|
+
|
|
5
|
+
import { TYPE_STEP_CLASSES, useTypography } from './typography'
|
|
6
|
+
|
|
7
|
+
// Tailwind only emits a class that appears literally in source AND has an @utility — a map
|
|
8
|
+
// entry without a utility renders unstyled, a utility without an entry is unreachable from the
|
|
9
|
+
// components. Both fail silently, so pin the two lists to each other.
|
|
10
|
+
const css = readFileSync(new URL('../assets/css/typography.css', import.meta.url), 'utf8')
|
|
11
|
+
const utilities = [...css.matchAll(/@utility\s+(text-step-[\w-]+)/g)].map(([, name]) => name)
|
|
12
|
+
const mapped = Object.values(TYPE_STEP_CLASSES)
|
|
13
|
+
|
|
14
|
+
describe('TYPE_STEP_CLASSES ↔ typography.css', () => {
|
|
15
|
+
it('has an @utility for every mapped class', () => {
|
|
16
|
+
for (const cls of mapped) expect(utilities).toContain(cls)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('maps every text-step @utility', () => {
|
|
20
|
+
for (const name of utilities) expect(mapped).toContain(name)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('names each class after its step', () => {
|
|
24
|
+
for (const [step, cls] of Object.entries(TYPE_STEP_CLASSES)) {
|
|
25
|
+
expect(cls).toBe(`text-step-${step}`)
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
describe('useTypography step', () => {
|
|
31
|
+
const classesOf = (props: Parameters<typeof useTypography>[0]) =>
|
|
32
|
+
useTypography(props).classes.value.split(' ')
|
|
33
|
+
|
|
34
|
+
it('emits step 0 rather than treating it as unset', () => {
|
|
35
|
+
expect(classesOf({ step: 0 })).toContain('text-step-0')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('wins over size instead of emitting two font sizes', () => {
|
|
39
|
+
const classes = classesOf({ step: 3, size: 'sm' })
|
|
40
|
+
expect(classes).toContain('text-step-3')
|
|
41
|
+
expect(classes).not.toContain('text-sm')
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('falls back to size when no step is given', () => {
|
|
45
|
+
expect(classesOf({ size: 'sm' })).toContain('text-sm')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
// A leading-* class sorts after text-step-* and would override the step's line height.
|
|
49
|
+
it('emits no leading class unless one is given', () => {
|
|
50
|
+
expect(classesOf({ step: 3 }).filter((c) => c.startsWith('leading-'))).toEqual([])
|
|
51
|
+
expect(classesOf({ step: 3, leading: 'leading-tight' })).toContain('leading-tight')
|
|
52
|
+
})
|
|
53
|
+
})
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { toValue, type MaybeRefOrGetter } from 'vue'
|
|
1
|
+
import { computed, toValue, type MaybeRefOrGetter } from 'vue'
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
|
-
FluidFontSize,
|
|
5
4
|
FontFamily,
|
|
6
5
|
FontLeading,
|
|
7
6
|
FontSize,
|
|
@@ -11,6 +10,7 @@ import type {
|
|
|
11
10
|
FontWidth,
|
|
12
11
|
TextAlign,
|
|
13
12
|
TextTransform,
|
|
13
|
+
TypeStep,
|
|
14
14
|
} from '../types/typography'
|
|
15
15
|
|
|
16
16
|
type AxisValue = string | number | undefined
|
|
@@ -36,39 +36,25 @@ function getSizeClass(size: FontSize | undefined): string {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// Literal map, not template-literal interpolation — Tailwind's content scanner
|
|
39
|
-
// looks for complete class-name strings in source, so `text-
|
|
40
|
-
// invisible to it and silently drops the utility.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
sm: 'text-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
'lg-cq': 'text-fluid-lg-cq',
|
|
59
|
-
'xl-cq': 'text-fluid-xl-cq',
|
|
60
|
-
'2xl-cq': 'text-fluid-2xl-cq',
|
|
61
|
-
'3xl-cq': 'text-fluid-3xl-cq',
|
|
62
|
-
'4xl-cq': 'text-fluid-4xl-cq',
|
|
63
|
-
'5xl-cq': 'text-fluid-5xl-cq',
|
|
64
|
-
'6xl-cq': 'text-fluid-6xl-cq',
|
|
65
|
-
'7xl-cq': 'text-fluid-7xl-cq',
|
|
66
|
-
'8xl-cq': 'text-fluid-8xl-cq',
|
|
67
|
-
'9xl-cq': 'text-fluid-9xl-cq',
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function getFluidSizeClass(fluidSize: FluidFontSize | undefined): string {
|
|
71
|
-
return fluidSize ? FLUID_SIZE_CLASSES[fluidSize] : ''
|
|
39
|
+
// looks for complete class-name strings in source, so `text-step-${x}` is
|
|
40
|
+
// invisible to it and silently drops the utility. Kept in sync with
|
|
41
|
+
// typography.css's @utility list by typography.test.ts.
|
|
42
|
+
export const TYPE_STEP_CLASSES: Record<TypeStep, string> = {
|
|
43
|
+
sm: 'text-step-sm',
|
|
44
|
+
0: 'text-step-0',
|
|
45
|
+
1: 'text-step-1',
|
|
46
|
+
2: 'text-step-2',
|
|
47
|
+
3: 'text-step-3',
|
|
48
|
+
4: 'text-step-4',
|
|
49
|
+
5: 'text-step-5',
|
|
50
|
+
6: 'text-step-6',
|
|
51
|
+
7: 'text-step-7',
|
|
52
|
+
8: 'text-step-8',
|
|
53
|
+
9: 'text-step-9',
|
|
54
|
+
10: 'text-step-10',
|
|
55
|
+
11: 'text-step-11',
|
|
56
|
+
12: 'text-step-12',
|
|
57
|
+
display: 'text-step-display',
|
|
72
58
|
}
|
|
73
59
|
|
|
74
60
|
export function useTypography(
|
|
@@ -81,7 +67,7 @@ export function useTypography(
|
|
|
81
67
|
align?: TextAlign
|
|
82
68
|
transform?: TextTransform
|
|
83
69
|
size?: FontSize
|
|
84
|
-
|
|
70
|
+
step?: TypeStep
|
|
85
71
|
font?: FontFamily
|
|
86
72
|
}>
|
|
87
73
|
) {
|
|
@@ -103,20 +89,19 @@ export function useTypography(
|
|
|
103
89
|
fallback: 'not-italic',
|
|
104
90
|
}),
|
|
105
91
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}),
|
|
92
|
+
// No fallback: a leading-* class sorts after text-step-* and would override the step's
|
|
93
|
+
// line height, so only emit one when asked.
|
|
94
|
+
normalizeAxis(p.leading, { prefix: 'leading' }),
|
|
110
95
|
|
|
111
96
|
normalizeAxis(p.tracking, {
|
|
112
97
|
prefix: 'tracking',
|
|
113
98
|
fallback: 'tracking-normal',
|
|
114
99
|
}),
|
|
115
100
|
|
|
116
|
-
//
|
|
101
|
+
// step is the parallel modular-scale namespace (see typography.css) — takes
|
|
117
102
|
// precedence over size when both are set, rather than emitting two
|
|
118
|
-
// conflicting font-size utilities.
|
|
119
|
-
p.
|
|
103
|
+
// conflicting font-size utilities. Checked against undefined: step 0 is valid.
|
|
104
|
+
p.step !== undefined ? TYPE_STEP_CLASSES[p.step] : getSizeClass(p.size),
|
|
120
105
|
|
|
121
106
|
p.align ? `text-${p.align}` : '',
|
|
122
107
|
|
|
@@ -61,40 +61,13 @@ export type FontSize =
|
|
|
61
61
|
| number
|
|
62
62
|
|
|
63
63
|
/* ======================================================
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
- Companion to text-
|
|
64
|
+
Type Step
|
|
65
|
+
- Step on the modular scale: base × 1.26^step, parallel to Tailwind's --text-*
|
|
66
|
+
- Companion to text-step-* utilities (typography.css)
|
|
67
|
+
- 'sm' is step −1; 'display' is fluid, 5 → 7 with viewport width
|
|
67
68
|
====================================================== */
|
|
68
69
|
|
|
69
|
-
export type
|
|
70
|
-
| 'xs'
|
|
71
|
-
| 'sm'
|
|
72
|
-
| 'md'
|
|
73
|
-
| 'lg'
|
|
74
|
-
| 'xl'
|
|
75
|
-
| '2xl'
|
|
76
|
-
| '3xl'
|
|
77
|
-
| '4xl'
|
|
78
|
-
| '5xl'
|
|
79
|
-
| '6xl'
|
|
80
|
-
| '7xl'
|
|
81
|
-
| '8xl'
|
|
82
|
-
| '9xl'
|
|
83
|
-
// Container-relative (cqi) variants — require a `container-type` ancestor
|
|
84
|
-
// (e.g. `@container`), otherwise cqi resolves against the small viewport.
|
|
85
|
-
| 'xs-cq'
|
|
86
|
-
| 'sm-cq'
|
|
87
|
-
| 'md-cq'
|
|
88
|
-
| 'lg-cq'
|
|
89
|
-
| 'xl-cq'
|
|
90
|
-
| '2xl-cq'
|
|
91
|
-
| '3xl-cq'
|
|
92
|
-
| '4xl-cq'
|
|
93
|
-
| '5xl-cq'
|
|
94
|
-
| '6xl-cq'
|
|
95
|
-
| '7xl-cq'
|
|
96
|
-
| '8xl-cq'
|
|
97
|
-
| '9xl-cq'
|
|
70
|
+
export type TypeStep = 'sm' | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 'display'
|
|
98
71
|
|
|
99
72
|
/* ======================================================
|
|
100
73
|
Font Width
|
|
@@ -3,15 +3,19 @@
|
|
|
3
3
|
for the full derivation rationale. Column composition is NOT here — it comes from
|
|
4
4
|
useGridTracks().toColumnsCss(), applied inline per grid-tracks instance. */
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
/* --fs stays unregistered on purpose: a registered <length> holding rem on :root, read by
|
|
7
|
+
:root's own line-height, is a dependency cycle in Gecko -- Firefox falls back to the initial
|
|
8
|
+
value and freezes the unit at 24px. Unregistered, it substitutes and resolves the same in
|
|
9
|
+
every engine. (An `initial-value: 1rem` @property is invalid anyway: rem is not
|
|
10
|
+
computationally independent.) */
|
|
11
11
|
|
|
12
12
|
:root {
|
|
13
|
-
/*
|
|
14
|
-
|
|
13
|
+
/* Shares the type scale's endpoints (typography.css --type-min/--type-max) but stays
|
|
14
|
+
continuous across 320 → 1280px, so the unit never takes the type base's 48rem jump.
|
|
15
|
+
Fallbacks keep grid valid on core alone. The slope is hand-fitted to 1rem → 1.2rem over
|
|
16
|
+
320 → 1280px — retune it if --type-min/--type-max change. rem term keeps this WCAG
|
|
17
|
+
1.4.4 zoom-safe; svi never vw (viewport-bar-collapse safe) */
|
|
18
|
+
--fs: clamp(var(--type-min, 1rem), 0.9333rem + 0.3333svi, var(--type-max, 1.2rem));
|
|
15
19
|
|
|
16
20
|
/* rounded, not raw, so grid boundaries land on-pixel */
|
|
17
21
|
line-height: round(nearest, var(--fs) * 1.5, 1px);
|
package/package.json
CHANGED