@startsimpli/ui 0.4.92 → 0.4.94
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/package.json +3 -3
- package/src/components/dashboard/DashboardSection.tsx +36 -5
- package/src/components/dashboard/MetricCard.tsx +4 -1
- package/src/components/dashboard/StatTile.tsx +20 -1
- package/src/components/states/Absence.tsx +156 -0
- package/src/components/states/Caveat.tsx +167 -0
- package/src/components/states/EmptyState.tsx +39 -10
- package/src/components/states/Footnote.tsx +171 -0
- package/src/components/states/__tests__/caveat-and-absence.test.tsx +662 -0
- package/src/components/states/index.ts +7 -1
- package/src/components/ui/card.tsx +37 -6
- package/src/components/unified-table/__tests__/components/TablePagination.test.tsx +62 -5
- package/src/components/unified-table/__tests__/hooks/usePagination.test.ts +22 -0
- package/src/components/unified-table/__tests__/utils/border-tokens.test.ts +61 -0
- package/src/components/unified-table/components/BulkActionBar/index.tsx +1 -1
- package/src/components/unified-table/components/DataTableCore/index.tsx +1 -1
- package/src/components/unified-table/components/MobileView/Card.tsx +1 -1
- package/src/components/unified-table/components/TableFilters/index.tsx +2 -2
- package/src/components/unified-table/components/TablePagination/index.tsx +19 -5
- package/src/components/unified-table/hooks/usePagination.ts +12 -0
- package/src/components/unified-table/utils/themes.ts +8 -5
- package/src/theme/__tests__/type-scale.test.tsx +145 -0
- package/src/theme/contract.ts +5 -0
- package/src/theme/index.ts +10 -0
- package/src/theme/type-scale.ts +119 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The type scale — packages/ui's contract for how big text is.
|
|
3
|
+
*
|
|
4
|
+
* Before this existed, every consumer picked font sizes by hand and the ladder
|
|
5
|
+
* collapsed: across one app 77% of all text was `text-sm` or `text-xs`, two
|
|
6
|
+
* ADJACENT steps, so a card title and its body differed by 1.5px and were told
|
|
7
|
+
* apart only by weight. The same "big number" was rendered at seven different
|
|
8
|
+
* sizes on seven screens because there was no rule to point at.
|
|
9
|
+
*
|
|
10
|
+
* There are seven roles, named for the job the text does, not for its size.
|
|
11
|
+
* Pick the role; the scale picks the pixels. The ladder is a deliberate 4:1
|
|
12
|
+
* from `display` down to `caption`, so any two adjacent roles are visibly
|
|
13
|
+
* different — that is the whole point.
|
|
14
|
+
*
|
|
15
|
+
* display 48px / 800 the one hero figure on a screen
|
|
16
|
+
* stat 32px / 800 a metric's value in a tile
|
|
17
|
+
* heading 20px / 700 a section header
|
|
18
|
+
* cardTitle 18px / 600 the name of a card
|
|
19
|
+
* body 16px / 400 prose and table cells
|
|
20
|
+
* muted 14px / 400 supporting copy under a title
|
|
21
|
+
* caption 12px / 400 labels, kickers, timestamps
|
|
22
|
+
*
|
|
23
|
+
* Mirrors packages/ui-native/src/tokens.ts + styles.ts, so a screen reads the
|
|
24
|
+
* same on web and iOS.
|
|
25
|
+
*
|
|
26
|
+
* SIZE and LINE-HEIGHT come from CSS variables (packages/ui/theme/contract.css),
|
|
27
|
+
* so an app reshapes the whole estate by overriding seven numbers — the same way
|
|
28
|
+
* `--radius` reshapes every corner. Each utility carries the default inline as a
|
|
29
|
+
* `var()` fallback, so a component still renders correctly in an app that has
|
|
30
|
+
* not adopted the contract file.
|
|
31
|
+
*
|
|
32
|
+
* WEIGHT and TRACKING are fixed per role, deliberately. They are what makes a
|
|
33
|
+
* role recognisable; an app that wants a lighter heading wants a different
|
|
34
|
+
* design, not a different token.
|
|
35
|
+
*
|
|
36
|
+
* Usage:
|
|
37
|
+
* import { TYPE_SCALE } from '@startsimpli/ui/theme'
|
|
38
|
+
* <h2 className={cn(TYPE_SCALE.heading, 'text-foreground')}>{title}</h2>
|
|
39
|
+
*
|
|
40
|
+
* The scale sets size/weight/leading only. COLOUR stays separate and must come
|
|
41
|
+
* from a theme token (`text-foreground`, `text-muted-foreground`) — never a
|
|
42
|
+
* `gray-*` literal, or the component is light-locked and unreadable on a dark
|
|
43
|
+
* tenant.
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
export type TypeScaleRole =
|
|
47
|
+
| 'display'
|
|
48
|
+
| 'stat'
|
|
49
|
+
| 'heading'
|
|
50
|
+
| 'cardTitle'
|
|
51
|
+
| 'body'
|
|
52
|
+
| 'muted'
|
|
53
|
+
| 'caption'
|
|
54
|
+
|
|
55
|
+
/** Tailwind utilities for each role. Compose with a colour token. */
|
|
56
|
+
export const TYPE_SCALE: Record<TypeScaleRole, string> = {
|
|
57
|
+
display:
|
|
58
|
+
'text-[length:var(--text-display-size,3rem)] leading-[var(--text-display-leading,1.05)] font-extrabold tracking-tight',
|
|
59
|
+
stat: 'text-[length:var(--text-stat-size,2rem)] leading-[var(--text-stat-leading,1.1)] font-extrabold tracking-tight tabular-nums',
|
|
60
|
+
heading:
|
|
61
|
+
'text-[length:var(--text-heading-size,1.25rem)] leading-[var(--text-heading-leading,1.3)] font-bold tracking-tight',
|
|
62
|
+
cardTitle:
|
|
63
|
+
'text-[length:var(--text-card-title-size,1.125rem)] leading-[var(--text-card-title-leading,1.4)] font-semibold',
|
|
64
|
+
body: 'text-[length:var(--text-body-size,1rem)] leading-[var(--text-body-leading,1.5)] font-normal',
|
|
65
|
+
muted:
|
|
66
|
+
'text-[length:var(--text-muted-size,0.875rem)] leading-[var(--text-muted-leading,1.5)] font-normal',
|
|
67
|
+
caption:
|
|
68
|
+
'text-[length:var(--text-caption-size,0.75rem)] leading-[var(--text-caption-leading,1.4)] font-normal',
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The roles in visual order, largest first. Useful for rendering the ladder in
|
|
73
|
+
* a harness and for tests that assert the steps stay distinct.
|
|
74
|
+
*/
|
|
75
|
+
export const TYPE_SCALE_ORDER: readonly TypeScaleRole[] = [
|
|
76
|
+
'display',
|
|
77
|
+
'stat',
|
|
78
|
+
'heading',
|
|
79
|
+
'cardTitle',
|
|
80
|
+
'body',
|
|
81
|
+
'muted',
|
|
82
|
+
'caption',
|
|
83
|
+
] as const
|
|
84
|
+
|
|
85
|
+
/** Default size of each role, in rem — the fallback baked into the utilities. */
|
|
86
|
+
export const TYPE_SCALE_DEFAULTS: Record<TypeScaleRole, number> = {
|
|
87
|
+
display: 3,
|
|
88
|
+
stat: 2,
|
|
89
|
+
heading: 1.25,
|
|
90
|
+
cardTitle: 1.125,
|
|
91
|
+
body: 1,
|
|
92
|
+
muted: 0.875,
|
|
93
|
+
caption: 0.75,
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** CSS custom properties an app may override to reshape the scale. */
|
|
97
|
+
export const TYPE_SCALE_TOKENS = [
|
|
98
|
+
'--text-display-size',
|
|
99
|
+
'--text-display-leading',
|
|
100
|
+
'--text-stat-size',
|
|
101
|
+
'--text-stat-leading',
|
|
102
|
+
'--text-heading-size',
|
|
103
|
+
'--text-heading-leading',
|
|
104
|
+
'--text-card-title-size',
|
|
105
|
+
'--text-card-title-leading',
|
|
106
|
+
'--text-body-size',
|
|
107
|
+
'--text-body-leading',
|
|
108
|
+
'--text-muted-size',
|
|
109
|
+
'--text-muted-leading',
|
|
110
|
+
'--text-caption-size',
|
|
111
|
+
'--text-caption-leading',
|
|
112
|
+
] as const
|
|
113
|
+
|
|
114
|
+
export type TypeScaleToken = (typeof TYPE_SCALE_TOKENS)[number]
|
|
115
|
+
|
|
116
|
+
/** `typeClass('heading')` — the utilities for a role, for dynamic call sites. */
|
|
117
|
+
export function typeClass(role: TypeScaleRole): string {
|
|
118
|
+
return TYPE_SCALE[role]
|
|
119
|
+
}
|