@solidrt/components 0.0.69 → 0.0.70
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/AGENTS.md +1 -1
- package/README.md +4 -5
- package/docs/policy.md +0 -1
- package/docs/typography.md +3 -3
- package/package.json +2 -2
- package/src/badge.tsx +3 -4
- package/src/button.tsx +2 -8
- package/src/editor-field.tsx +1 -2
- package/src/index.ts +1 -1
- package/src/policy.ts +0 -10
- package/src/segmented-control.tsx +2 -2
- package/src/text.tsx +3 -5
- package/src/typography.ts +13 -54
package/AGENTS.md
CHANGED
|
@@ -110,7 +110,7 @@ One bullet per module, generated from the first paragraph of its docs/ file.
|
|
|
110
110
|
- `Theming` - Appearance (colors, spacing, border, font roles) comes from one shared, reactive theme backed by a Solid store: reads are tracked, so switching the theme at runtime recolors the live UI without remounting. Four presets ship, `darkTheme` and `lightTheme` (the flat look, default dark) and `litDarkTheme` and `litLightTheme` (the same palette under a light, see below); `setTheme(preset)` switches, `setTheme(partial)` merges an override one level deep per category. A resolved theme carries every key of every category (unset ones as `undefined`), so switching to one replaces the previous theme outright, per-component overrides and icon slots included; a partial keeps whatever it does not name. Custom themes are authored with `defineTheme`.
|
|
111
111
|
- `Policies` - Theme answers "how does it look"; policies answer "how does it behave". `policy` is a second reactive layer derived from the platform facts in `@solidrt/core` (`capabilities`, `env`), so components adapt to touch vs. desktop, window size, and display without every app wiring that logic itself. Reads are reactive like `theme`: a window resize or the first mouse move on a touch-capable device updates every consuming component live.
|
|
112
112
|
- `Density` - `<Density value="compact">` overrides the density policy for its subtree: every density-scaled metric below - `space()`, control sizes (Checkbox, Switch, Radio, Slider), `Item` and `Button` paddings - resolves this value instead of the global `policy.density`. Regions nest; the nearest wins. Use it to tighten a toolbar, a data table, or a sidebar without per-child props.
|
|
113
|
-
- `Typography helpers` - `typeStyle(variant)` resolves a theme type-scale role (`caption`/`label`/`body`/`title`/`heading`) to font props ready to spread onto a `<text>` or `d-text`: `fontSize` carries `policy.textScale`,
|
|
113
|
+
- `Typography helpers` - `typeStyle(variant)` resolves a theme type-scale role (`caption`/`label`/`body`/`title`/`heading`) to font props ready to spread onto a `<text>` or `d-text`: `fontSize` carries `policy.textScale`, `fontWeight` is the role's own. Reactive when called inside a tracked scope, like any theme/policy read. `Text` applies it for you; reach for the helpers when building custom text out of core primitives.
|
|
114
114
|
- `Spacing` - `space(token)` is density-scaled spacing: a `theme.spacing` token (`sm`/`md`/`lg`/`xl`) multiplied by the density scale of the nearest `<Density>` region (falling back to the global policy) and rounded to whole pixels. Use it for gaps and paddings that should tighten under `compact`/`dense` density; read `theme.spacing` directly only for distances that must not move with density. Reactive when called inside a tracked scope.
|
|
115
115
|
- `Layout and style` - Most components group their props into two objects, split by one rule: `layout` properties feed the layout engine (flexbox/grid, sizing, padding, margin, position - the core `LayoutProps` set) and changing them triggers a relayout; `style` properties are paint-only and never affect layout: `color`, `backgroundColor`, `borderColor`, `borderWidth`, `borderRadius`, `opacity`, `glow` (a halo on the component's accent part; `null` clears the theme's), `material` (layers merged over the role's material for the component's faces) and `elevation` (the level its raised face stands at), see Theming, and the transform (`x`, `y`, `scale`, `rotate`, `rotateX`/`rotateY` with `perspective`, `originX`/`originY`, `clipRadius`). Event handlers (`onPointerDown`, `onKeyDown`, ...) are top-level props, never inside `layout` or `style`.
|
|
116
116
|
<!-- END GENERATED: exports -->
|
package/README.md
CHANGED
|
@@ -132,7 +132,6 @@ The fields:
|
|
|
132
132
|
- `motion` (`"normal" | "reduced" | "none"`) - animation intensity. Gates every built-in component transition: `reduced` keeps the color/opacity fades (a fade is not movement) but snaps everything that travels or scales, and halves the indeterminate `Spinner`/`ProgressBar` speeds; `none` snaps it all and parks the indeterminate loops.
|
|
133
133
|
- `focusRing` (`boolean`) - whether focused controls draw a visible focus indicator (true when a keyboard or gamepad/remote is present).
|
|
134
134
|
- `textScale` (`number`) - multiplier on type-scale font sizes; defaults to the OS text-scale preference.
|
|
135
|
-
- `textWeightDelta` (`number`) - weight compensation (steps of 100) for light-on-dark text on low-DPI displays.
|
|
136
135
|
- `navigation` (`"bottomTabs" | "rail" | "sidebar"`) - recommended nav layout, derived from the pane count: `sidebar` beside a two-pane layout, `bottomTabs` under a single pane (a side strip spends the width a narrow window is short of). `rail` is never derived; set it for a content-dense two-pane app. `NavShell` follows it.
|
|
137
136
|
- `layout` (`"singlePane" | "twoPane"`) - recommended pane count, derived from the window size class. `SplitView` follows it.
|
|
138
137
|
|
|
@@ -161,13 +160,13 @@ API: `StyleProps`, `Glow`, `Glass`, `Material`, `MaterialRole`, `ElevationLevel`
|
|
|
161
160
|
|
|
162
161
|
## Typography helpers
|
|
163
162
|
|
|
164
|
-
`typeStyle(variant)` resolves a theme type-scale role (`caption`/`label`/`body`/`title`/`heading`) to font props ready to spread onto a `<text>` or `d-text`: `fontSize` carries `policy.textScale`,
|
|
163
|
+
`typeStyle(variant)` resolves a theme type-scale role (`caption`/`label`/`body`/`title`/`heading`) to font props ready to spread onto a `<text>` or `d-text`: `fontSize` carries `policy.textScale`, `fontWeight` is the role's own. Reactive when called inside a tracked scope, like any theme/policy read. `Text` applies it for you; reach for the helpers when building custom text out of core primitives.
|
|
165
164
|
|
|
166
|
-
`typeScaleStyles()` is the type scale as font styles (every role
|
|
165
|
+
`typeScaleStyles()` is the type scale as font styles (every role, plus the mono family at body size), and `warmTypeScale()` hands them to core's `warmText`, which makes their glyph cells ahead of the first screen on the text engine's worker. `Window` does this on mount and again when the theme or the text policy changes; an app that draws its own window calls it once at startup.
|
|
167
166
|
|
|
168
|
-
|
|
167
|
+
There is no weight compensation: the text engine blends glyph coverage with DirectWrite's gamma-aware recipe, so light-on-dark text keeps its stems at every display scale.
|
|
169
168
|
|
|
170
|
-
API: `typeStyle`, `
|
|
169
|
+
API: `typeStyle`, `typeScaleStyles`, `warmTypeScale` - typed and commented in [src/typography.ts](./src/typography.ts).
|
|
171
170
|
|
|
172
171
|
## Spacing
|
|
173
172
|
|
package/docs/policy.md
CHANGED
|
@@ -9,7 +9,6 @@ The fields:
|
|
|
9
9
|
- `motion` (`"normal" | "reduced" | "none"`) - animation intensity. Gates every built-in component transition: `reduced` keeps the color/opacity fades (a fade is not movement) but snaps everything that travels or scales, and halves the indeterminate `Spinner`/`ProgressBar` speeds; `none` snaps it all and parks the indeterminate loops.
|
|
10
10
|
- `focusRing` (`boolean`) - whether focused controls draw a visible focus indicator (true when a keyboard or gamepad/remote is present).
|
|
11
11
|
- `textScale` (`number`) - multiplier on type-scale font sizes; defaults to the OS text-scale preference.
|
|
12
|
-
- `textWeightDelta` (`number`) - weight compensation (steps of 100) for light-on-dark text on low-DPI displays.
|
|
13
12
|
- `navigation` (`"bottomTabs" | "rail" | "sidebar"`) - recommended nav layout, derived from the pane count: `sidebar` beside a two-pane layout, `bottomTabs` under a single pane (a side strip spends the width a narrow window is short of). `rail` is never derived; set it for a content-dense two-pane app. `NavShell` follows it.
|
|
14
13
|
- `layout` (`"singlePane" | "twoPane"`) - recommended pane count, derived from the window size class. `SplitView` follows it.
|
|
15
14
|
|
package/docs/typography.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Typography helpers
|
|
2
2
|
|
|
3
|
-
`typeStyle(variant)` resolves a theme type-scale role (`caption`/`label`/`body`/`title`/`heading`) to font props ready to spread onto a `<text>` or `d-text`: `fontSize` carries `policy.textScale`,
|
|
3
|
+
`typeStyle(variant)` resolves a theme type-scale role (`caption`/`label`/`body`/`title`/`heading`) to font props ready to spread onto a `<text>` or `d-text`: `fontSize` carries `policy.textScale`, `fontWeight` is the role's own. Reactive when called inside a tracked scope, like any theme/policy read. `Text` applies it for you; reach for the helpers when building custom text out of core primitives.
|
|
4
4
|
|
|
5
|
-
`typeScaleStyles()` is the type scale as font styles (every role
|
|
5
|
+
`typeScaleStyles()` is the type scale as font styles (every role, plus the mono family at body size), and `warmTypeScale()` hands them to core's `warmText`, which makes their glyph cells ahead of the first screen on the text engine's worker. `Window` does this on mount and again when the theme or the text policy changes; an app that draws its own window calls it once at startup.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
There is no weight compensation: the text engine blends glyph coverage with DirectWrite's gamma-aware recipe, so light-on-dark text keeps its stems at every display scale.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidrt/components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.70",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"funding": "https://github.com/sponsors/wellawaretech",
|
|
6
6
|
"author": "Antoine van Wel",
|
|
@@ -21,6 +21,6 @@
|
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
23
|
"@solidjs/signals": "2.0.0-rc.13",
|
|
24
|
-
"@solidrt/core": "0.0.
|
|
24
|
+
"@solidrt/core": "0.0.70"
|
|
25
25
|
}
|
|
26
26
|
}
|
package/src/badge.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { Show, children } from "@solidrt/core"
|
|
|
2
2
|
import type { LayoutProps } from "@solidrt/core"
|
|
3
3
|
import { theme } from "./theme"
|
|
4
4
|
import { space } from "./spacing"
|
|
5
|
-
import { typeStyle
|
|
5
|
+
import { typeStyle } from "./typography"
|
|
6
6
|
import { policy } from "./policy"
|
|
7
7
|
import { Surface } from "./surface"
|
|
8
8
|
import type { ElevationLevel, MaterialRole, StyleProps, TransitionProps } from "./types"
|
|
@@ -51,7 +51,6 @@ export function Badge(props: BadgeProps) {
|
|
|
51
51
|
// share one build - reading the raw getter again would orphan native nodes.
|
|
52
52
|
let resolved = children(() => props.children)
|
|
53
53
|
let isText = () => typeof resolved() === "string" || typeof resolved() === "number"
|
|
54
|
-
let labelOnDark = () => lightOnDark(fg(), bg())
|
|
55
54
|
|
|
56
55
|
let split = () => splitTransition(props.transition)
|
|
57
56
|
|
|
@@ -90,8 +89,8 @@ export function Badge(props: BadgeProps) {
|
|
|
90
89
|
<text
|
|
91
90
|
transition={colorFade()}
|
|
92
91
|
color={fg()}
|
|
93
|
-
{...typeStyle("caption"
|
|
94
|
-
fontWeight={
|
|
92
|
+
{...typeStyle("caption")}
|
|
93
|
+
fontWeight={600}
|
|
95
94
|
>
|
|
96
95
|
{resolved()}
|
|
97
96
|
</text>
|
package/src/button.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { createPress } from "./press"
|
|
|
3
3
|
import { theme } from "./theme"
|
|
4
4
|
import { policy } from "./policy"
|
|
5
5
|
import { space } from "./spacing"
|
|
6
|
-
import { typeStyle
|
|
6
|
+
import { typeStyle } from "./typography"
|
|
7
7
|
import { Spinner } from "./spinner"
|
|
8
8
|
import { Surface, surfaceSinks } from "./surface"
|
|
9
9
|
import type { LayoutProps } from "@solidrt/core"
|
|
@@ -93,12 +93,6 @@ export function Button(props: ButtonProps) {
|
|
|
93
93
|
// share this single memoized build (an unmounted build leaks native nodes).
|
|
94
94
|
let resolved = children(() => props.children)
|
|
95
95
|
let isText = () => typeof resolved() === "string" || typeof resolved() === "number"
|
|
96
|
-
// The label's polarity against the idle fill: onPrimary on a saturated fill
|
|
97
|
-
// is light-on-dark even in a light theme, so it needs the low-DPI weight
|
|
98
|
-
// compensation there too. The base fill, not the lit gradient: the
|
|
99
|
-
// compensation reads a solid color.
|
|
100
|
-
let labelOnDark = () => lightOnDark(label(), bg())
|
|
101
|
-
|
|
102
96
|
// props (not a literal) so a swapped-in onPress is read at event time.
|
|
103
97
|
let press = createPress(props)
|
|
104
98
|
let pressed = () => !props.disabled && press.pressed()
|
|
@@ -167,7 +161,7 @@ export function Button(props: ButtonProps) {
|
|
|
167
161
|
onOutlineTransitionEnd={transitionEndFor("border", props.onTransitionEnd)}
|
|
168
162
|
/>
|
|
169
163
|
<Show when={isText()} fallback={resolved()}>
|
|
170
|
-
<text transition={colorFade()} color={press.pending() ? withAlpha(label(), 0) : label()} {...typeStyle("body"
|
|
164
|
+
<text transition={colorFade()} color={press.pending() ? withAlpha(label(), 0) : label()} {...typeStyle("body")}>
|
|
171
165
|
{resolved()}
|
|
172
166
|
</text>
|
|
173
167
|
</Show>
|
package/src/editor-field.tsx
CHANGED
|
@@ -30,7 +30,6 @@ import { Surface } from "./surface"
|
|
|
30
30
|
import { theme } from "./theme"
|
|
31
31
|
import { policy } from "./policy"
|
|
32
32
|
import { space } from "./spacing"
|
|
33
|
-
import { typeWeight } from "./typography"
|
|
34
33
|
|
|
35
34
|
// Caret thickness. Shared so the drawn caret and the scroll offset's reserved
|
|
36
35
|
// edge column cannot drift apart.
|
|
@@ -421,7 +420,7 @@ export function EditorField(props: EditorFieldProps) {
|
|
|
421
420
|
fontSize: fontSize(),
|
|
422
421
|
lineHeight: lineHeight(),
|
|
423
422
|
fontStyle: layoutFont().fontStyle,
|
|
424
|
-
fontWeight:
|
|
423
|
+
fontWeight: layoutFont().fontWeight ?? theme.text.body.weight,
|
|
425
424
|
}),
|
|
426
425
|
{ equals: sameFont },
|
|
427
426
|
)
|
package/src/index.ts
CHANGED
|
@@ -70,7 +70,7 @@ export {
|
|
|
70
70
|
type LayoutPolicy,
|
|
71
71
|
} from "./policy"
|
|
72
72
|
export { Density, type DensityProps, densityScale } from "./density"
|
|
73
|
-
export { typeStyle,
|
|
73
|
+
export { typeStyle, typeScaleStyles, warmTypeScale } from "./typography"
|
|
74
74
|
export { space } from "./spacing"
|
|
75
75
|
export type {
|
|
76
76
|
StyleProps,
|
package/src/policy.ts
CHANGED
|
@@ -23,12 +23,6 @@ export type Policies = {
|
|
|
23
23
|
// Multiplier on type-scale font sizes (Dynamic Type). Follows the OS
|
|
24
24
|
// preference (env.textScale); override via setPolicy to pin it.
|
|
25
25
|
textScale: number
|
|
26
|
-
// Base weight compensation for light-on-dark text on this display, in
|
|
27
|
-
// steps of 100 (other steps decode as 400): low-DPI rendering thins
|
|
28
|
-
// inverted-polarity glyphs. Applied by typeWeight to light-on-dark runs
|
|
29
|
-
// only (per-run polarity, or the theme's palette polarity as the default),
|
|
30
|
-
// with one extra step for small font sizes; see typography.ts.
|
|
31
|
-
textWeightDelta: number
|
|
32
26
|
// Application policies: recommendations derived from the window size class
|
|
33
27
|
// (layout), and from the resulting pane count (navigation).
|
|
34
28
|
// The application owns the final decision; accept them by consuming
|
|
@@ -63,7 +57,6 @@ export function defaultPolicyResolver(caps: Capabilities): Policies {
|
|
|
63
57
|
// otherwise navigate ringless on keyboard-free TVs.
|
|
64
58
|
focusRing: caps.keyboardNav || gamepads().some((p) => p != null),
|
|
65
59
|
textScale: env.textScale,
|
|
66
|
-
textWeightDelta: env.displayScale < 1.5 ? 100 : 0,
|
|
67
60
|
// Navigation follows the pane count, not its own breakpoint: a side strip
|
|
68
61
|
// spends width, which a single-pane window is short of, so only a
|
|
69
62
|
// two-pane layout earns one. "rail" is never a default output; it is the
|
|
@@ -98,9 +91,6 @@ export let policy = {
|
|
|
98
91
|
get textScale(): number {
|
|
99
92
|
return overrides().textScale ?? resolved().textScale
|
|
100
93
|
},
|
|
101
|
-
get textWeightDelta(): number {
|
|
102
|
-
return overrides().textWeightDelta ?? resolved().textWeightDelta
|
|
103
|
-
},
|
|
104
94
|
get navigation(): NavigationPolicy {
|
|
105
95
|
return overrides().navigation ?? resolved().navigation
|
|
106
96
|
},
|
|
@@ -4,7 +4,7 @@ import { createPress } from "./press"
|
|
|
4
4
|
import { theme } from "./theme"
|
|
5
5
|
import { policy } from "./policy"
|
|
6
6
|
import { space } from "./spacing"
|
|
7
|
-
import { typeStyle
|
|
7
|
+
import { typeStyle } from "./typography"
|
|
8
8
|
import { Surface, facePaint } from "./surface"
|
|
9
9
|
import type { ElevationLevel, Option, StyleProps, TransitionProps, TransitionStyleProp, TransitionViewProp } from "./types"
|
|
10
10
|
import { partTransition, partTransitionEnd, splitTransition, transitionEndFor } from "./types"
|
|
@@ -241,7 +241,7 @@ export function SegmentedControl<T>(props: SegmentedControlProps<T>) {
|
|
|
241
241
|
<text
|
|
242
242
|
transition={colorFade()}
|
|
243
243
|
color={label(active())}
|
|
244
|
-
{...typeStyle("body"
|
|
244
|
+
{...typeStyle("body")}
|
|
245
245
|
>
|
|
246
246
|
{opt.label}
|
|
247
247
|
</text>
|
package/src/text.tsx
CHANGED
|
@@ -4,7 +4,6 @@ import type { StyleProps, TextLayoutProps, TransitionProps, TransitionViewProp }
|
|
|
4
4
|
import { splitTextLayout, splitTransition, transitionEndFor, withTransitionDefaults } from "./types"
|
|
5
5
|
import { theme, type TextVariant } from "./theme"
|
|
6
6
|
import { policy } from "./policy"
|
|
7
|
-
import { typeWeight } from "./typography"
|
|
8
7
|
import { colorFade } from "./motion"
|
|
9
8
|
|
|
10
9
|
// Semantic text colors, resolved through the theme. Curated: only tokens that
|
|
@@ -15,9 +14,8 @@ export interface TextProps extends PointerProps, TransitionProps<TransitionViewP
|
|
|
15
14
|
children?: any
|
|
16
15
|
// Typography role from the theme's type scale; defaults to "body". Explicit
|
|
17
16
|
// layout font props override the role's fields individually. fontSize
|
|
18
|
-
// (role-derived or explicit) is multiplied by policy.textScale
|
|
19
|
-
//
|
|
20
|
-
// <text> primitive for text that must not scale.
|
|
17
|
+
// (role-derived or explicit) is multiplied by policy.textScale; use the
|
|
18
|
+
// core <text> primitive for text that must not scale.
|
|
21
19
|
variant?: TextVariant
|
|
22
20
|
// Semantic color from the theme; defaults to "text". style.color still wins.
|
|
23
21
|
color?: TextColor
|
|
@@ -86,7 +84,7 @@ export function Text(props: TextProps) {
|
|
|
86
84
|
fontSize={size()}
|
|
87
85
|
lineHeight={props.layout?.lineHeight ?? role().lineHeight}
|
|
88
86
|
fontStyle={props.layout?.fontStyle}
|
|
89
|
-
fontWeight={
|
|
87
|
+
fontWeight={props.layout?.fontWeight ?? role().weight}
|
|
90
88
|
textAlign={props.layout?.textAlign}
|
|
91
89
|
maxLines={props.layout?.maxLines}
|
|
92
90
|
>
|
package/src/typography.ts
CHANGED
|
@@ -1,65 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { warmText } from "@solidrt/core"
|
|
2
2
|
import type { MeasureTextOptions } from "@solidrt/core"
|
|
3
|
-
import { theme, type
|
|
3
|
+
import { theme, type TextVariant } from "./theme"
|
|
4
4
|
import { policy } from "./policy"
|
|
5
5
|
|
|
6
|
-
// Below this effective font size, light-on-dark text on a low-DPI display
|
|
7
|
-
// needs an extra compensation step (edge pixels dominate small glyphs).
|
|
8
|
-
const SMALL_TEXT = 16
|
|
9
|
-
|
|
10
|
-
// The rendering polarity of `text` drawn on `fill`, for typeWeight/typeStyle:
|
|
11
|
-
// true when the text is the lighter of the two. Returns undefined (= fall
|
|
12
|
-
// back to the theme's default polarity) when either side is not a comparable
|
|
13
|
-
// color (gradients, "transparent").
|
|
14
|
-
export function lightOnDark(text: unknown, fill: unknown): boolean | undefined {
|
|
15
|
-
if (typeof text !== "string" || typeof fill !== "string" || fill === "transparent") return undefined
|
|
16
|
-
return brightness(text) > brightness(fill)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// The theme's default polarity, derived from its own palette: light text on
|
|
20
|
-
// a dark window background means a dark scheme. Nothing to declare per
|
|
21
|
-
// preset, and it cannot disagree with the colors.
|
|
22
|
-
function themeOnDark(): boolean {
|
|
23
|
-
return lightOnDark(theme.color.text, theme.color.background) ?? false
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// A themed font weight with low-DPI rendering compensation applied. The
|
|
27
|
-
// renderer (Impeller) rasterizes glyphs unhinted and composites the coverage
|
|
28
|
-
// in nonlinear sRGB, which steals stem ink from light-on-dark text only (and
|
|
29
|
-
// donates it to dark-on-light); the loss grows as glyphs shrink. Compensated
|
|
30
|
-
// text adds policy.textWeightDelta (0 on high-DPI displays) plus one extra
|
|
31
|
-
// step under SMALL_TEXT px; dark-on-light text passes through untouched.
|
|
32
|
-
// `onDark` is the run's own polarity where the caller knows both colors (use
|
|
33
|
-
// the lightOnDark() helper, like Button does for its fills); omitted, it
|
|
34
|
-
// defaults to the theme's palette polarity. `size` is the effective
|
|
35
|
-
// (post-textScale) font size. Clamped to the 900 ceiling; reactive like any
|
|
36
|
-
// theme/policy read.
|
|
37
|
-
export function typeWeight(weight: number, size: number, onDark?: boolean): TextStyle["weight"] {
|
|
38
|
-
let delta = (onDark ?? themeOnDark()) ? policy.textWeightDelta : 0
|
|
39
|
-
if (delta > 0 && size < SMALL_TEXT) delta += 100
|
|
40
|
-
return Math.min(900, weight + delta) as TextStyle["weight"]
|
|
41
|
-
}
|
|
42
|
-
|
|
43
6
|
// Resolved font props for a type-scale role, with the text policies applied:
|
|
44
7
|
// spread onto a <text> or d-text. fontSize carries policy.textScale
|
|
45
|
-
// (lineHeight is relative to the size, so it scales implicitly)
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
export function typeStyle(variant: TextVariant
|
|
8
|
+
// (lineHeight is relative to the size, so it scales implicitly). Reactive
|
|
9
|
+
// when called inside a tracked scope, like any theme/policy read. The weight
|
|
10
|
+
// is the role's own: the text engine blends coverage with DirectWrite's
|
|
11
|
+
// recipe, so light-on-dark text needs no compensation at any display scale.
|
|
12
|
+
export function typeStyle(variant: TextVariant) {
|
|
50
13
|
let role = theme.text[variant]
|
|
51
|
-
let size = role.size * policy.textScale
|
|
52
14
|
return {
|
|
53
15
|
fontFamily: theme.text.fontFamily,
|
|
54
|
-
fontSize: size,
|
|
16
|
+
fontSize: role.size * policy.textScale,
|
|
55
17
|
lineHeight: role.lineHeight,
|
|
56
|
-
fontWeight:
|
|
18
|
+
fontWeight: role.weight,
|
|
57
19
|
}
|
|
58
20
|
}
|
|
59
21
|
|
|
60
|
-
// Every role of the type scale,
|
|
61
|
-
//
|
|
62
|
-
// the mono family at body size for code spans.
|
|
22
|
+
// Every role of the type scale, plus the mono family at body size for code
|
|
23
|
+
// spans.
|
|
63
24
|
const TYPE_SCALE_VARIANTS: TextVariant[] = ["caption", "label", "body", "title", "heading"]
|
|
64
25
|
|
|
65
26
|
// The font styles the theme's type scale draws in, as warmText takes them.
|
|
@@ -67,10 +28,8 @@ const TYPE_SCALE_VARIANTS: TextVariant[] = ["caption", "label", "body", "title",
|
|
|
67
28
|
export function typeScaleStyles(): MeasureTextOptions[] {
|
|
68
29
|
let styles: MeasureTextOptions[] = []
|
|
69
30
|
for (let variant of TYPE_SCALE_VARIANTS) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
styles.push({ fontFamily: style.fontFamily, fontSize: style.fontSize, fontWeight: style.fontWeight })
|
|
73
|
-
}
|
|
31
|
+
let style = typeStyle(variant)
|
|
32
|
+
styles.push({ fontFamily: style.fontFamily, fontSize: style.fontSize, fontWeight: style.fontWeight })
|
|
74
33
|
}
|
|
75
34
|
let body = typeStyle("body")
|
|
76
35
|
styles.push({ fontFamily: theme.text.monoFamily, fontSize: body.fontSize, fontWeight: body.fontWeight })
|