@ixfx/components 0.6.2 → 0.7.1
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/bundle/index.d.ts +1918 -835
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +22137 -16840
- package/bundle/index.js.map +1 -1
- package/bundle/style.css +1 -1
- package/dist/ac-text.d.ts +1 -1
- package/dist/ac-text.js +3 -2
- package/dist/ac-text.js.map +1 -1
- package/dist/{ac-token-BAa6ke09.d.ts → ac-token--_vCHXWw.d.ts} +2 -2
- package/dist/{ac-token-BAa6ke09.d.ts.map → ac-token--_vCHXWw.d.ts.map} +1 -1
- package/dist/ac-token.d.ts +1 -1
- package/dist/ac-token.js +3 -2
- package/dist/ac-token.js.map +1 -1
- package/dist/{button-Bn0BuLpO.js → button-DsFbV4XD.js} +5 -4
- package/dist/button-DsFbV4XD.js.map +1 -0
- package/dist/button.d.ts.map +1 -1
- package/dist/button.js +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/{colour-picker-0stHB90J.js → colour-picker-Ddsk-7E_.js} +4 -3
- package/dist/{colour-picker-0stHB90J.js.map → colour-picker-Ddsk-7E_.js.map} +1 -1
- package/dist/colour-picker.js +1 -1
- package/dist/crumbs.d.ts +1 -1
- package/dist/crumbs.js +4 -2
- package/dist/crumbs.js.map +1 -1
- package/dist/data-display.js +1 -1
- package/dist/{data-grid-C8qIo1-u.d.ts → data-grid-Bh4YrQGK.d.ts} +2 -2
- package/dist/{data-grid-C8qIo1-u.d.ts.map → data-grid-Bh4YrQGK.d.ts.map} +1 -1
- package/dist/data-grid.d.ts +1 -1
- package/dist/data-grid.js +4 -2
- package/dist/data-grid.js.map +1 -1
- package/dist/{defaults-BCiDhZbF.js → defaults-BJwDsMH4.js} +27 -20
- package/dist/defaults-BJwDsMH4.js.map +1 -0
- package/dist/editable-label-rzXkjf1H.d.ts +75 -0
- package/dist/editable-label-rzXkjf1H.d.ts.map +1 -0
- package/dist/editable-label.d.ts +2 -75
- package/dist/editable-label.js +2 -1
- package/dist/editable-label.js.map +1 -1
- package/dist/{fallbacks-DEE1nCTt.js → fallbacks-DNI9xt0F.js} +2 -2
- package/dist/{fallbacks-DEE1nCTt.js.map → fallbacks-DNI9xt0F.js.map} +1 -1
- package/dist/{grouped-item-lister-_pMDwIo1.d.ts → grouped-item-lister-DnWB-eFT.d.ts} +2 -2
- package/dist/{grouped-item-lister-_pMDwIo1.d.ts.map → grouped-item-lister-DnWB-eFT.d.ts.map} +1 -1
- package/dist/grouped-item-lister.d.ts +1 -1
- package/dist/{hex-editor-Bk6rxhfg.js → hex-editor-BiRfwTz1.js} +2 -2
- package/dist/{hex-editor-Bk6rxhfg.js.map → hex-editor-BiRfwTz1.js.map} +1 -1
- package/dist/hex.js +1 -1
- package/dist/{icon-DpA9x2Ve.d.ts → icon-CDGprSdE.d.ts} +1 -12
- package/dist/icon-CDGprSdE.d.ts.map +1 -0
- package/dist/{icons-Bm2ByQ3s.js → icon-DcEEGQa_.js} +38 -12
- package/dist/icon-DcEEGQa_.js.map +1 -0
- package/dist/icons.d.ts +3 -3
- package/dist/icons.js +9 -3
- package/dist/icons.js.map +1 -0
- package/dist/{index-CKtLhgYj.d.ts → index-9AhaHIT2.d.ts} +3 -3
- package/dist/{index-CKtLhgYj.d.ts.map → index-9AhaHIT2.d.ts.map} +1 -1
- package/dist/index-CG2vIgPv.d.ts +101 -0
- package/dist/index-CG2vIgPv.d.ts.map +1 -0
- package/dist/{index-BtGFYfaK.d.ts → index-CS9yM8L-.d.ts} +14 -4
- package/dist/index-CS9yM8L-.d.ts.map +1 -0
- package/dist/index.d.ts +861 -71
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4257 -931
- package/dist/index.js.map +1 -1
- package/dist/interaction-D5XdKzbR.js +2 -0
- package/dist/labelled-radial-input.js +2 -1
- package/dist/labelled-radial-input.js.map +1 -1
- package/dist/labelled-slider-input-DzigjMwP.js +808 -0
- package/dist/labelled-slider-input-DzigjMwP.js.map +1 -0
- package/dist/labelled-slider-input.d.ts +2 -0
- package/dist/labelled-slider-input.js +2 -0
- package/dist/{types-DlVNJez_.d.ts → list-selection-types-DSuRNWpx.d.ts} +10 -2
- package/dist/list-selection-types-DSuRNWpx.d.ts.map +1 -0
- package/dist/menu-CXDFJxNm.js +825 -0
- package/dist/menu-CXDFJxNm.js.map +1 -0
- package/dist/{menu-item-Bs2MYyHq.d.ts → menu-item-CZi9vy5O.d.ts} +4 -2
- package/dist/menu-item-CZi9vy5O.d.ts.map +1 -0
- package/dist/menu-item-D2S4i8u1.js +809 -0
- package/dist/menu-item-D2S4i8u1.js.map +1 -0
- package/dist/menu.d.ts +2 -2
- package/dist/menu.js +2 -1
- package/dist/miller.d.ts +1 -1
- package/dist/miller.js +3 -2
- package/dist/miller.js.map +1 -1
- package/dist/narrowed-text.js +4 -2
- package/dist/narrowed-text.js.map +1 -1
- package/dist/notification-pill-DyZydXoZ.d.ts.map +1 -1
- package/dist/notifier.js +4 -3
- package/dist/notifier.js.map +1 -1
- package/dist/panel.d.ts +13 -13
- package/dist/panel.d.ts.map +1 -1
- package/dist/panel.js +37 -253
- package/dist/panel.js.map +1 -1
- package/dist/plots.js +1 -1
- package/dist/polar-pad.js +1 -1
- package/dist/{radial-input-Dk8Wydp5.js → radial-input-Dp5qz0ly.js} +2 -2
- package/dist/{radial-input-Dk8Wydp5.js.map → radial-input-Dp5qz0ly.js.map} +1 -1
- package/dist/radial-input.js +1 -1
- package/dist/range-input.js +1 -1
- package/dist/range.js +1 -1
- package/dist/registry-BEtb8_wB.js +46 -0
- package/dist/registry-BEtb8_wB.js.map +1 -0
- package/dist/select-horiz.js +3 -2
- package/dist/select-horiz.js.map +1 -1
- package/dist/{slider-input-XppH3vcy.d.ts → slider-input-BfRUW2ZB.d.ts} +16 -3
- package/dist/slider-input-BfRUW2ZB.d.ts.map +1 -0
- package/dist/{slider-input-CT4gcF-o.js → slider-input-De4eoT11.js} +382 -67
- package/dist/slider-input-De4eoT11.js.map +1 -0
- package/dist/slider-input.d.ts +1 -1
- package/dist/slider-input.js +1 -1
- package/dist/snackbar.js +1 -1
- package/dist/split-layout-BFSbUZQv.js +969 -0
- package/dist/split-layout-BFSbUZQv.js.map +1 -0
- package/dist/split-layout-JK3xWVX2.d.ts +179 -0
- package/dist/split-layout-JK3xWVX2.d.ts.map +1 -0
- package/dist/split-layout.d.ts +2 -60
- package/dist/split-layout.js +1 -617
- package/dist/style.css +1 -1
- package/dist/swipe.js +1 -1
- package/dist/{tab-list-D_1cYhB_.d.ts → tab-list-CGyPt07Z.d.ts} +10 -2
- package/dist/tab-list-CGyPt07Z.d.ts.map +1 -0
- package/dist/tabs.d.ts +1 -1
- package/dist/tabs.js +128 -27
- package/dist/tabs.js.map +1 -1
- package/dist/{tickled-controller-BtevrRLV.d.ts → tickled-controller-CRzdIEjJ.d.ts} +7 -1
- package/dist/tickled-controller-CRzdIEjJ.d.ts.map +1 -0
- package/dist/{tickled-controller-DkAU-0qL.js → tickled-controller-h9GmJ_bU.js} +8 -2
- package/dist/tickled-controller-h9GmJ_bU.js.map +1 -0
- package/dist/titlebar-Bj5pfdw_.d.ts +50 -0
- package/dist/titlebar-Bj5pfdw_.d.ts.map +1 -0
- package/dist/titlebar.d.ts +2 -0
- package/dist/titlebar.js +324 -0
- package/dist/titlebar.js.map +1 -0
- package/dist/tooltip-BlvBUQxx.d.ts.map +1 -1
- package/dist/{tree-BO6BXI2b.js → tree-Ch4W8qXQ.js} +4 -3
- package/dist/{tree-BO6BXI2b.js.map → tree-Ch4W8qXQ.js.map} +1 -1
- package/dist/tree.d.ts +1 -1
- package/dist/tree.js +1 -1
- package/dist/vertical-list-ClnqTkF3.js +814 -0
- package/dist/vertical-list-ClnqTkF3.js.map +1 -0
- package/dist/vertical-list.d.ts +8 -9
- package/dist/vertical-list.d.ts.map +1 -1
- package/dist/vertical-list.js +1 -736
- package/dist/{xy-axis-B6yMjckW.js → xy-axis-DWizs0bt.js} +109 -3
- package/dist/xy-axis-DWizs0bt.js.map +1 -0
- package/dist/xy-pad.js +1 -1
- package/docs-user/README.md +5 -0
- package/docs-user/detail-list.md +398 -0
- package/docs-user/dock.md +461 -0
- package/docs-user/icons.md +4 -0
- package/docs-user/index.json +28 -3
- package/docs-user/labelled-slider-input.md +198 -0
- package/docs-user/llms.txt +6 -1
- package/docs-user/panel.md +20 -1
- package/docs-user/slider-input.md +55 -15
- package/docs-user/split-layout.md +136 -170
- package/docs-user/tabs.md +54 -0
- package/docs-user/titlebar.md +102 -0
- package/docs-user/toolbar.md +95 -22
- package/docs-user/twosplit-layout.md +254 -0
- package/docs-user/user-catalog.md +8 -1
- package/docs-user/user-theming.md +109 -0
- package/llms.txt +6 -1
- package/package.json +1 -2
- package/dist/button-Bn0BuLpO.js.map +0 -1
- package/dist/defaults-BCiDhZbF.js.map +0 -1
- package/dist/editable-label.d.ts.map +0 -1
- package/dist/icon-DpA9x2Ve.d.ts.map +0 -1
- package/dist/icons-Bm2ByQ3s.js.map +0 -1
- package/dist/index-BtGFYfaK.d.ts.map +0 -1
- package/dist/menu-DIfU70AA.js +0 -1609
- package/dist/menu-DIfU70AA.js.map +0 -1
- package/dist/menu-item-Bs2MYyHq.d.ts.map +0 -1
- package/dist/slider-input-CT4gcF-o.js.map +0 -1
- package/dist/slider-input-XppH3vcy.d.ts.map +0 -1
- package/dist/split-layout.d.ts.map +0 -1
- package/dist/split-layout.js.map +0 -1
- package/dist/tab-list-D_1cYhB_.d.ts.map +0 -1
- package/dist/tickled-controller-BtevrRLV.d.ts.map +0 -1
- package/dist/tickled-controller-DkAU-0qL.js.map +0 -1
- package/dist/types-DlVNJez_.d.ts.map +0 -1
- package/dist/vertical-list.js.map +0 -1
- package/dist/xy-axis-B6yMjckW.js.map +0 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# `<ixfx-labelled-slider-input>`
|
|
2
|
+
|
|
3
|
+
A composite slider input that pairs an editable label (`ixfx-editable-number`) with a slider (`ixfx-slider-input`). The two controls are always in sync — dragging the slider updates the number, and editing the number moves the slider.
|
|
4
|
+
|
|
5
|
+
## Basic usage
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
<ixfx-labelled-slider-input label="Volume" value="0.5" min="0" max="1" step="0.01">
|
|
9
|
+
</ixfx-labelled-slider-input>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Layout
|
|
13
|
+
|
|
14
|
+
Layout is driven by a container query on the component's own height.
|
|
15
|
+
|
|
16
|
+
| Height | Layout |
|
|
17
|
+
|-----------------|---------------------------------|
|
|
18
|
+
| >= 80px (default) | **Vertical** — label above slider |
|
|
19
|
+
| < 80px | **Horizontal** — label beside slider |
|
|
20
|
+
|
|
21
|
+
The component defaults to `height: 100px`, so unconstrained usage shows the vertical layout. Constrain the height in your CSS to switch to horizontal.
|
|
22
|
+
|
|
23
|
+
### Force a layout with `--flow`
|
|
24
|
+
|
|
25
|
+
Override the container query entirely:
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<ixfx-labelled-slider-input style="--flow: row" ...> <!-- always horizontal -->
|
|
29
|
+
<ixfx-labelled-slider-input style="--flow: column" ...> <!-- always vertical -->
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Control label width (horizontal layout)
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<ixfx-labelled-slider-input style="--label-width: 8em" ...>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Mini mode
|
|
39
|
+
|
|
40
|
+
When the component is very small the label is hidden and only the slider is shown.
|
|
41
|
+
|
|
42
|
+
Mini mode activates when **both** of the following are true:
|
|
43
|
+
- `width < mini-width-threshold` (default 120px)
|
|
44
|
+
- `height < mini-height-threshold` (default 40px)
|
|
45
|
+
|
|
46
|
+
Override with a CSS variable:
|
|
47
|
+
|
|
48
|
+
```html
|
|
49
|
+
<ixfx-labelled-slider-input style="--mini: 1" ...> <!-- always mini -->
|
|
50
|
+
<ixfx-labelled-slider-input style="--mini: 0" ...> <!-- never mini -->
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Formatter
|
|
54
|
+
|
|
55
|
+
Apply a function to format the displayed value. Set it as a JS property — it cannot be set as an HTML attribute.
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
const el = document.querySelector('ixfx-labelled-slider-input');
|
|
59
|
+
el.formatter = (v) => `${Math.round(Number(v))}%`;
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The formatter receives the raw string value and returns the string to display in the editable-number label. Note the inner slider has no tooltip — the label already shows the value, so a tooltip would be redundant.
|
|
63
|
+
|
|
64
|
+
## Properties / attributes
|
|
65
|
+
|
|
66
|
+
| Attribute | Type | Default | Description |
|
|
67
|
+
|------------------------|-----------------------------------------------|--------------|-----------------------------------------------------|
|
|
68
|
+
| `label` | `string` | `""` | Label text shown in the editable-number |
|
|
69
|
+
| `value` | `number` | `0` | Current value |
|
|
70
|
+
| `min` | `number` | `0` | Minimum value |
|
|
71
|
+
| `max` | `number` | `1` | Maximum value |
|
|
72
|
+
| `step` | `number` | `0.01` | Step increment |
|
|
73
|
+
| `stops` | `number` | — | Quantise to N discrete positions |
|
|
74
|
+
| `drag-sensitivity` | `number` | `1` | Steps per pixel when dragging the number label |
|
|
75
|
+
| `precision` | `number` | `0` | Decimal places shown |
|
|
76
|
+
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Slider track orientation |
|
|
77
|
+
| `single-style` | `"range" \| "bipolar" \| "unipolar"` | `"range"` | How the value bar is drawn |
|
|
78
|
+
| `marker-style` | `"needle" \| "dot" \| "triangle" \| "none"` | `"needle"` | Marker shape |
|
|
79
|
+
| `disabled` | `boolean` | `false` | Disables all interaction |
|
|
80
|
+
| `swipeable` | `boolean` | `false` | Swipe-to-draw gesture (step-sequencer layouts) |
|
|
81
|
+
| `switch-height` | `number` | `80` | Height (px) at which layout switches vertical↔horizontal |
|
|
82
|
+
| `mini-width-threshold` | `number` | `120` | Width (px) below which mini mode can activate |
|
|
83
|
+
| `mini-height-threshold`| `number` | `40` | Height (px) below which mini mode can activate |
|
|
84
|
+
| `display-text-logic` | `"hidden" \| "show" \| "override" \| "transient"` | `"transient"` | Controls when label text vs value is shown |
|
|
85
|
+
| `formatter` | `(value: string) => string` | — | JS property only — formats value for display |
|
|
86
|
+
| `lighttouch` | `boolean` | `false` | Wheel adjusts the value on hover without focus |
|
|
87
|
+
|
|
88
|
+
### `display-text-logic` values
|
|
89
|
+
|
|
90
|
+
| Value | Behaviour |
|
|
91
|
+
|-------------|--------------------------------------------------------|
|
|
92
|
+
| `transient` | Shows the label when idle, value on hover/interaction |
|
|
93
|
+
| `show` | Always shows the value |
|
|
94
|
+
| `hidden` | Always shows the label text, never the value |
|
|
95
|
+
| `override` | Label text replaces value at all times |
|
|
96
|
+
|
|
97
|
+
## Events
|
|
98
|
+
|
|
99
|
+
| Event | Detail | Description |
|
|
100
|
+
|----------|---------------------------|----------------------------------------------------------|
|
|
101
|
+
| `change` | `{ value: string }` | Fired when the value is committed (slider release or number edit) |
|
|
102
|
+
| `input` | `{ value: number }` | Fired on every slider move |
|
|
103
|
+
|
|
104
|
+
Both events bubble and are composed (cross shadow boundary).
|
|
105
|
+
|
|
106
|
+
## CSS variables
|
|
107
|
+
|
|
108
|
+
### Layout
|
|
109
|
+
|
|
110
|
+
| Variable | Default | Description |
|
|
111
|
+
|--------------------------|--------------|-----------------------------------------------------------|
|
|
112
|
+
| `--height` | `100px` | Component height. Set to `100%` to fill a constrained parent |
|
|
113
|
+
| `--width` | `auto` | Component width |
|
|
114
|
+
| `--min-height` | `20px` | Minimum height |
|
|
115
|
+
| `--min-width` | `50px` | Minimum width |
|
|
116
|
+
| `--flow` | *(container query)* | `row` or `column` — overrides the automatic layout |
|
|
117
|
+
| `--label-width` | `5ch` | Width of the editable-number in horizontal layout |
|
|
118
|
+
| `--mini` | *(auto)* | `1` to force mini mode, `0` to disable it |
|
|
119
|
+
|
|
120
|
+
### Label (passed to `ixfx-editable-number`)
|
|
121
|
+
|
|
122
|
+
| Variable | Default | Description |
|
|
123
|
+
|-----------------------|----------------------------|--------------------------|
|
|
124
|
+
| `--label-font-size` | `var(--text-m)` | Font size |
|
|
125
|
+
| `--label-font-family` | `var(--font-family)` | Font family |
|
|
126
|
+
| `--label-color` | `var(--surface-text)` | Text colour |
|
|
127
|
+
| `--label-muted-color` | `var(--surface-muted-text)`| Muted text colour |
|
|
128
|
+
| `--label-padding` | `var(--space-xs) var(--space-s)` | Padding |
|
|
129
|
+
| `--label-radius` | `var(--radius-s)` | Border radius |
|
|
130
|
+
| `--label-align` | `center` | Text alignment |
|
|
131
|
+
|
|
132
|
+
### Slider (passed to `ixfx-slider-input`)
|
|
133
|
+
|
|
134
|
+
| Variable | Default | Description |
|
|
135
|
+
|-----------------------------------|--------------------------|------------------------------------------|
|
|
136
|
+
| `--lane-track-color` | `var(--surface-4)` | Colour of the background track lane |
|
|
137
|
+
| `--lane-value-color` | `var(--accent)` | Colour of the value lane |
|
|
138
|
+
| `--lane-color` | `var(--accent)` | Fallback colour for custom lanes |
|
|
139
|
+
| `--lane-dasharray` | `none` | Dash pattern for lanes |
|
|
140
|
+
| `--marker-color` | `var(--accent)` | Marker colour |
|
|
141
|
+
| `--marker-thickness` | `0.15` | Marker thickness (fraction of cross axis)|
|
|
142
|
+
| `--marker-length` | `0.8` | Needle length (fraction of cross axis) |
|
|
143
|
+
| `--marker-offset` | `0` | Perpendicular offset from centreline |
|
|
144
|
+
| `--track-color` | `var(--surface-4)` | Track stroke colour |
|
|
145
|
+
| `--track-width` | `2` | Track stroke width (SVG units) |
|
|
146
|
+
|
|
147
|
+
See `ixfx-slider-input` for the full list of lane, marker, and midpoint variables.
|
|
148
|
+
|
|
149
|
+
## Examples
|
|
150
|
+
|
|
151
|
+
### Horizontal layout with percentage formatter
|
|
152
|
+
|
|
153
|
+
```html
|
|
154
|
+
<ixfx-labelled-slider-input
|
|
155
|
+
id="my-slider"
|
|
156
|
+
label="Mix"
|
|
157
|
+
value="0.75"
|
|
158
|
+
style="height: 50px"
|
|
159
|
+
></ixfx-labelled-slider-input>
|
|
160
|
+
|
|
161
|
+
<script type="module">
|
|
162
|
+
document.querySelector('#my-slider').formatter = (v) =>
|
|
163
|
+
`${Math.round(Number(v) * 100)}%`;
|
|
164
|
+
</script>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Custom slider colours
|
|
168
|
+
|
|
169
|
+
```html
|
|
170
|
+
<ixfx-labelled-slider-input
|
|
171
|
+
label="Intensity"
|
|
172
|
+
value="0.7"
|
|
173
|
+
style="
|
|
174
|
+
--lane-value-color: hsl(280, 80%, 60%);
|
|
175
|
+
--lane-track-color: hsl(280, 30%, 30%);
|
|
176
|
+
--marker-color: hsl(280, 100%, 70%);
|
|
177
|
+
"
|
|
178
|
+
></ixfx-labelled-slider-input>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Force mini mode
|
|
182
|
+
|
|
183
|
+
```html
|
|
184
|
+
<ixfx-labelled-slider-input label="Vol" value="0.5" style="--mini: 1">
|
|
185
|
+
</ixfx-labelled-slider-input>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Listen for changes
|
|
189
|
+
|
|
190
|
+
```js
|
|
191
|
+
const el = document.querySelector('ixfx-labelled-slider-input');
|
|
192
|
+
|
|
193
|
+
// Committed value (slider release or number edit)
|
|
194
|
+
el.addEventListener('change', (e) => console.log(e.detail.value));
|
|
195
|
+
|
|
196
|
+
// Every slider move
|
|
197
|
+
el.addEventListener('input', (e) => console.log(e.detail.value));
|
|
198
|
+
```
|
package/docs-user/llms.txt
CHANGED
|
@@ -19,6 +19,8 @@ import '@ixfx/components/data-grid';
|
|
|
19
19
|
- [crumbs](docs-user/crumbs.md): Breadcrumb navigation with lazy-loading child support. Uses the same `TreeNode` / `TreeItem` data model as `ixfx-tree-list`, allowing easy swapping between the two components.
|
|
20
20
|
- [data-display](docs-user/data-display.md): A debug data display component that renders key-value pairs from a plain object. Supports 7 inline render modes (`led`, `plot`, `plot-xy`, `plot-heat`, `plot-histogram`, `time-elapsed`, `hide`) via `c
|
|
21
21
|
- [data-grid](docs-user/data-grid.md): A virtualised data grid with sortable/resizable/reorderable columns, single/multi selection, grouping, and inline cell editing. Handles 200+ rows with windowed rendering and keyboard navigation.
|
|
22
|
+
- [detail-list](docs-user/detail-list.md): A list that scales horizontally, not vertically. Items are laid out in equal-width columns; they flow top→bottom down a column, then wrap to the top of the next column to the right. The component has
|
|
23
|
+
- [dock](docs-user/dock.md): Dockable, movable panels like VS Code / Photoshop. Drag a panel by its
|
|
22
24
|
- [editable-label](docs-user/editable-label.md): Inline editable text components. `ixfx-editable-number` extends `ixfx-editable-label` with drag-to-adjust and fill-bar visualization.
|
|
23
25
|
- [form](docs-user/form.md): Primitives for typical form layout with responsive label positioning and data binding.
|
|
24
26
|
- [grouped-item-lister](docs-user/grouped-item-lister.md): A meta-component that renders a typed item list using any sub-component you supply. Items can be displayed in a single sub-component (_ungrouped_ mode) or split into labelled groups, each with its own
|
|
@@ -26,6 +28,7 @@ import '@ixfx/components/data-grid';
|
|
|
26
28
|
- [incr-search](docs-user/incr-search.md): Utilities for incremental (type-ahead) search over data collections or DOM-backed lists.
|
|
27
29
|
- [labelled-radial-input](docs-user/labelled-radial-input.md): A composite radial input that pairs an editable label (`ixfx-editable-number`) with a rotary dial (`ixfx-radial-input`). The two controls are always in sync — turning the dial updates the number, and
|
|
28
30
|
- [labelled-range-input](docs-user/labelled-range-input.md): A composite range input that pairs an editable label (`ixfx-editable-number`) with a slider (`ixfx-range-input`). The two controls are always in sync — dragging the slider updates the number, and edit
|
|
31
|
+
- [labelled-slider-input](docs-user/labelled-slider-input.md): A composite slider input that pairs an editable label (`ixfx-editable-number`) with a slider (`ixfx-slider-input`). The two controls are always in sync — dragging the slider updates the number, and ed
|
|
29
32
|
- [led](docs-user/led.md): An LED indicator component with color mixing and optional blinking animation.
|
|
30
33
|
- [menu](docs-user/menu.md): A custom menu system built on native HTML popovers with keyboard navigation, tickled focus management, and command routing.
|
|
31
34
|
- [miller](docs-user/miller.md): A Miller column component displays hierarchical data as multiple vertical columns, like macOS Finder or email clients. Each column shows the children of the selected item in the previous column.
|
|
@@ -42,13 +45,15 @@ import '@ixfx/components/data-grid';
|
|
|
42
45
|
- [slider-input](docs-user/slider-input.md): A linear SVG-based slider. Supports horizontal and vertical orientations, three value modes (single/dual/triple), three single-mode styles (range/bipolar/unipolar), triangle/needle/dot markers, and `v
|
|
43
46
|
- [snackbar](docs-user/snackbar.md): A small floating toolbar anchored in visual proximity to another element on the page (the "target"), built on the native Popover and CSS Anchor Positioning APIs.
|
|
44
47
|
- [snap-container](docs-user/snap-container.md): A container that positions its child element at configurable snap positions along an axis. The child can be dragged, clicked to snap, or controlled via keyboard.
|
|
45
|
-
- [split-layout](docs-user/split-layout.md): A Lit web component that lays out
|
|
48
|
+
- [split-layout](docs-user/split-layout.md): A Lit web component that lays out any number of panels along one axis with draggable gutters between them.
|
|
46
49
|
- [swipe](docs-user/swipe.md): A touch-friendly swipe/nudge component. User taps and drags to generate a value in range [-1, 1]. Value is emitted only on pointer release.
|
|
47
50
|
- [tabs](docs-user/tabs.md): A complete tabbed interface system using several coordinated components:
|
|
48
51
|
- [timeline](docs-user/timeline.md): A canvas-based timeline component with tracks, events, zoom/pan, and vertical track resizing. Suitable for visualizing time-series data, event logs, or scheduling.
|
|
52
|
+
- [titlebar](docs-user/titlebar.md): Standalone titlebar chrome extracted from `ixfx-panel`: title text, icon, toolbar slot, close button and an optional collapse/expand caret. Use it when you need a panel-style header without the collap
|
|
49
53
|
- [toolbar](docs-user/toolbar.md): Two components for building toolbars:
|
|
50
54
|
- [transitory-label](docs-user/transitory-label.md): An inline text label that animates between values instead of changing instantly. Displays as `inline-block` and inherits text styling from its parent.
|
|
51
55
|
- [tree](docs-user/tree.md): Three components share a common `TreeComponent` interface: **`ixfx-tree-list`**, **`ixfx-miller-list`**, and **`ixfx-crumb-navigation`**. This document describes the shared API, plus component-specifi
|
|
56
|
+
- [twosplit-layout](docs-user/twosplit-layout.md): A Lit web component that lays out two elements within a container with a split bar to adjust their proportions.
|
|
52
57
|
- [util](docs-user/util.md): A tooltip component that renders a value with optional icon and formatted number display. Uses native render root (no shadow DOM).
|
|
53
58
|
- [vertical-list](docs-user/vertical-list.md): A scrollable vertical list of items with selection, keyboard navigation, and incremental search. Items can be plain `<li>` elements declared in HTML or rich custom elements added programmatically.
|
|
54
59
|
- [xy-pad](docs-user/xy-pad.md): A 2D touch-friendly XY pad for controlling two parameters simultaneously. Each axis supports independent linear/logarithmic scaling.
|
package/docs-user/panel.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
An collapsible panel component with support for titles, icons, toolbars, and multiple visual variants.
|
|
4
4
|
|
|
5
|
+
The header chrome is an `ixfx-titlebar` (see [`ixfx-titlebar`](../titlebar/README.md)); the panel adds the collapsible content area beneath it.
|
|
6
|
+
|
|
5
7
|
```html
|
|
6
8
|
<ixfx-panel title="Settings">
|
|
7
9
|
<p>Panel content goes here.</p>
|
|
@@ -17,6 +19,7 @@ An collapsible panel component with support for titles, icons, toolbars, and mul
|
|
|
17
19
|
| Attribute / Property | Type | Default | Description |
|
|
18
20
|
|--------------------------|---------------------------------------------------|---------------|--------------------------------------------------|
|
|
19
21
|
| `collapsed` | boolean | `false` | Whether the panel is collapsed (content hidden) |
|
|
22
|
+
| `collapsible` | boolean | `true` | Whether the caret is shown and the panel can be toggled (opt-out) |
|
|
20
23
|
| `orientation` | `'horizontal'` \| `'vertical'` | `'horizontal'`| Layout direction of title bar |
|
|
21
24
|
| `title` | string | `''` | Panel title text |
|
|
22
25
|
| `icon-name` | string | `''` | Icon name from the registry |
|
|
@@ -32,6 +35,18 @@ An collapsible panel component with support for titles, icons, toolbars, and mul
|
|
|
32
35
|
| `explicit` | Only clicking the caret button toggles the panel |
|
|
33
36
|
| `disabled` | Caret is hidden; no user toggle possible (programmatic only) |
|
|
34
37
|
|
|
38
|
+
Set `collapsible` to `false` (via property binding or JS — `collapsible` defaults to `true`, so a bare `collapsible="false"` attribute would still count as present) or use `toggle-interaction="disabled"` for a fixed header with no user toggle:
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<ixfx-panel id="fixed" title="Fixed" toggle-interaction="disabled">
|
|
42
|
+
<p>This panel cannot be collapsed by the user.</p>
|
|
43
|
+
</ixfx-panel>
|
|
44
|
+
<script>
|
|
45
|
+
// Opt out of collapsing entirely (hides the caret):
|
|
46
|
+
document.querySelector('#fixed').collapsible = false;
|
|
47
|
+
</script>
|
|
48
|
+
```
|
|
49
|
+
|
|
35
50
|
### Slots
|
|
36
51
|
|
|
37
52
|
| Slot | Description |
|
|
@@ -184,6 +199,7 @@ A container component that manages multiple panels with exclusive open behavior
|
|
|
184
199
|
| `variant` | `'titlebar'` \| `'midline'` | `'titlebar'` | Visual style applied to all child panels |
|
|
185
200
|
| `toggle-interaction` | `'implicit'` \| `'explicit'` \| `'disabled'` | `'implicit'` | Toggle behavior applied to all child panels |
|
|
186
201
|
| `allow-multiple` | boolean | `false` | Allow multiple panels to be open simultaneously |
|
|
202
|
+
| `collapsible` | boolean | `true` | Collapse behaviour propagated to child panels |
|
|
187
203
|
| `gap` | string | `'var(--space-m)'` | CSS gap between panels |
|
|
188
204
|
|
|
189
205
|
### Group orientation vs child panel orientation
|
|
@@ -225,7 +241,7 @@ By default, only one panel can be open at a time. Set `allow-multiple` to allow
|
|
|
225
241
|
|
|
226
242
|
### Group-propagated properties
|
|
227
243
|
|
|
228
|
-
When you set `variant
|
|
244
|
+
When you set `variant`, `toggle-interaction` or `collapsible` on the group, those values are automatically applied to all child panels that don't have an explicit value set. This simplifies declaration when all panels in a group share the same styling:
|
|
229
245
|
|
|
230
246
|
```html
|
|
231
247
|
<ixfx-panel-group variant="midline" toggle-interaction="explicit">
|
|
@@ -241,10 +257,13 @@ When you set `variant` or `toggle-interaction` on the group, those values are au
|
|
|
241
257
|
|
|
242
258
|
```ts
|
|
243
259
|
import type { PanelOrientation, PanelVariant, PanelToggleInteraction, PanelToggleDetail, PanelGroupOrientation } from 'ixfxfun-components';
|
|
260
|
+
// Canonical titlebar types (Panel* are aliases):
|
|
261
|
+
import type { TitlebarOrientation, TitlebarVariant, TitlebarToggleInteraction, TitlebarToggleDetail } from 'ixfxfun-components';
|
|
244
262
|
```
|
|
245
263
|
|
|
246
264
|
---
|
|
247
265
|
|
|
248
266
|
## See also
|
|
249
267
|
|
|
268
|
+
- [`ixfx-titlebar`](../titlebar/README.md) — Standalone titlebar chrome composed by this panel
|
|
250
269
|
- [`ixfx-icon`](../icons/README.md) — Icon component used by panel
|
|
@@ -10,7 +10,7 @@ A linear SVG-based slider. Supports horizontal and vertical orientations, three
|
|
|
10
10
|
<ixfx-slider-input min="0" max="100" value-a="50"></ixfx-slider-input>
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
The component defaults to `200px` wide and `
|
|
13
|
+
The component defaults to `200px` wide and `12px` tall (the horizontal cross axis). The SVG box hugs its content (see Implementation Notes), so rows pack densely — e.g. in step-sequencer layouts. Set width and height via CSS:
|
|
14
14
|
|
|
15
15
|
```html
|
|
16
16
|
<ixfx-slider-input min="0" max="100" value-a="50" style="width: 320px;"></ixfx-slider-input>
|
|
@@ -22,14 +22,14 @@ Vertical orientation swaps the dimensions and rotates interaction to up/down:
|
|
|
22
22
|
<ixfx-slider-input
|
|
23
23
|
orientation="vertical"
|
|
24
24
|
min="0" max="100" value-a="30"
|
|
25
|
-
style="width:
|
|
25
|
+
style="width: 12px; height: 200px;"
|
|
26
26
|
></ixfx-slider-input>
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
To fill a container, set both `width: 100%` and `height: 100%`:
|
|
30
30
|
|
|
31
31
|
```html
|
|
32
|
-
<div style="width: 100%; height:
|
|
32
|
+
<div style="width: 100%; height: 12px;">
|
|
33
33
|
<ixfx-slider-input min="0" max="100" value-a="50" style="width: 100%; height: 100%;"></ixfx-slider-input>
|
|
34
34
|
</div>
|
|
35
35
|
```
|
|
@@ -57,14 +57,16 @@ To fill a container, set both `width: 100%` and `height: 100%`:
|
|
|
57
57
|
| `value-min` | `number` | `1` | Minimum gap between A and B in value units (dual/triple) |
|
|
58
58
|
| `value-c-follow` | `"none"` \| `"proportional"` | `"none"` | How C follows when A/B move the band (triple mode) |
|
|
59
59
|
| `disabled` | `boolean` | `false` | Disables all interaction. Reflected as attribute |
|
|
60
|
+
| `swipeable` | `boolean` | `false` | Swipe-to-draw gesture (no pointer capture; press or enter with pointer down sets value). Reflected as attribute |
|
|
61
|
+
| `lighttouch` | `boolean` | `false` | Wheel adjusts the value on hover instead of requiring focus |
|
|
60
62
|
|
|
61
63
|
### Sizing
|
|
62
64
|
|
|
63
|
-
Size via CSS `width`/`height`. The horizontal default is 200×
|
|
65
|
+
Size via CSS `width`/`height`. The horizontal default is 200×12, vertical 12×200. Both can be overridden freely.
|
|
64
66
|
|
|
65
67
|
```html
|
|
66
|
-
<!-- Thin (
|
|
67
|
-
<ixfx-slider-input style="height:
|
|
68
|
+
<!-- Thin (8px tall) -->
|
|
69
|
+
<ixfx-slider-input style="height: 8px;" min="0" max="100" value-a="60"></ixfx-slider-input>
|
|
68
70
|
|
|
69
71
|
<!-- Large (32px tall) -->
|
|
70
72
|
<ixfx-slider-input style="height: 32px;" min="0" max="100" value-a="60"></ixfx-slider-input>
|
|
@@ -104,10 +106,28 @@ Size via CSS `width`/`height`. The horizontal default is 200×24, vertical 24×2
|
|
|
104
106
|
|
|
105
107
|
**Wheel** (when focused or `lighttouch` is on):
|
|
106
108
|
|
|
107
|
-
Wheel forward increases the value, wheel backward decreases it (sign is platform-agnostic — both `deltaY` and `deltaX` are considered so Mac shift-scrolls are handled correctly). Shift narrows the step to 1/10th.
|
|
109
|
+
Wheel forward increases the value, wheel backward decreases it (sign is platform-agnostic — both `deltaY` and `deltaX` are considered so Mac shift-scrolls are handled correctly). Shift narrows the step to 1/10th. Add the `lighttouch` attribute to step on hover without focusing first:
|
|
110
|
+
|
|
111
|
+
```html
|
|
112
|
+
<ixfx-slider-input lighttouch min="0" max="100" step="5" value-a="50"></ixfx-slider-input>
|
|
113
|
+
```
|
|
108
114
|
|
|
109
115
|
Step size priority: `stops` > explicit `step` > 10% of range.
|
|
110
116
|
|
|
117
|
+
### Swipeable mode (step sequencer)
|
|
118
|
+
|
|
119
|
+
Mirrors `ixfx-range-input[swipeable]`. When the `swipeable` attribute is present, pressing down on the slider or entering it while the pointer is pressed sets the value from the cursor coordinate. Pointer capture is NOT held, so the cursor can move to adjacent swipeable sliders and update them too. Leaving the slider (above/below for horizontal, left/right for vertical) freezes the value; re-entering re-engages. `input` fires continuously; `change` fires debounced 150 ms after interaction, as usual.
|
|
120
|
+
|
|
121
|
+
Single mode sets value-A directly. Dual/triple modes move the nearest handle to the cursor.
|
|
122
|
+
|
|
123
|
+
```html
|
|
124
|
+
<div id="sequencer" style="display:flex; flex-direction:column; gap:2px;">
|
|
125
|
+
<ixfx-slider-input swipeable min="0" max="1" step="0.05" value-a="0.5"></ixfx-slider-input>
|
|
126
|
+
<ixfx-slider-input swipeable min="0" max="1" step="0.05" value-a="0.3"></ixfx-slider-input>
|
|
127
|
+
<ixfx-slider-input swipeable min="0" max="1" step="0.05" value-a="0.7"></ixfx-slider-input>
|
|
128
|
+
</div>
|
|
129
|
+
```
|
|
130
|
+
|
|
111
131
|
---
|
|
112
132
|
|
|
113
133
|
## Value Modes
|
|
@@ -256,8 +276,11 @@ slider.addEventListener('change', (e: SliderInputChangeEvent) => {
|
|
|
256
276
|
| Variable | Default | Description |
|
|
257
277
|
|---|---|---|
|
|
258
278
|
| `--track-color` | `var(--surface-4)` | Stroke colour of the central track rect |
|
|
259
|
-
| `--track-width` | `
|
|
279
|
+
| `--track-width` | `0` | Stroke width of the track (SVG units). Defaults to 0 — the `track`/`value` lanes carry the default visuals, so the rect is an opt-in backdrop (combine with `--track-fill`). Set it for an outlined band behind the lanes |
|
|
260
280
|
| `--track-fill` | `transparent` | Fill colour of the track rect |
|
|
281
|
+
| `--track-margin` | `0` | Extra inline-direction margin at both track ends (SVG units), added to the computed marker inset |
|
|
282
|
+
| `--track-margin-start` | `--track-margin` | Margin at the low-value end (left / bottom) |
|
|
283
|
+
| `--track-margin-end` | `--track-margin` | Margin at the high-value end (right / top) |
|
|
261
284
|
|
|
262
285
|
```html
|
|
263
286
|
<ixfx-slider-input
|
|
@@ -266,6 +289,17 @@ slider.addEventListener('change', (e: SliderInputChangeEvent) => {
|
|
|
266
289
|
></ixfx-slider-input>
|
|
267
290
|
```
|
|
268
291
|
|
|
292
|
+
### Track margins (inline direction)
|
|
293
|
+
|
|
294
|
+
The track hugs the host by default, inset only for marker clearance. If a custom lane overhangs the value at the extremes — e.g. an `anchored` tolerance band centred on the marker — reserve room so it never leaves the component bounds. Margins shorten and offset the track along its axis (start = low-value end):
|
|
295
|
+
|
|
296
|
+
```html
|
|
297
|
+
<ixfx-slider-input
|
|
298
|
+
min="0" max="100" value-a="50"
|
|
299
|
+
style="--track-margin: 7;"
|
|
300
|
+
></ixfx-slider-input>
|
|
301
|
+
```
|
|
302
|
+
|
|
269
303
|
### Lanes
|
|
270
304
|
|
|
271
305
|
Lanes are line segments drawn over the track. The built-in lanes are `track` (the grey background) and `value` (the accent-coloured progress bar). Custom lanes can be added at runtime (see [Data Lanes](#data-lanes-programmatic-api)).
|
|
@@ -277,6 +311,8 @@ Lanes are line segments drawn over the track. The built-in lanes are `track` (th
|
|
|
277
311
|
| `--lane-color` | `var(--accent)` | Fallback colour for custom lanes |
|
|
278
312
|
| `--lane-<key>-color` | — | Per-lane colour override (e.g. `--lane-sweep-color`) |
|
|
279
313
|
| `--lane-<key>-width` | — | Per-lane width override (e.g. `--lane-sweep-width`) |
|
|
314
|
+
| `--lane-track-width` | `0.08` | Thickness of the `track` lane (fraction of cross axis) |
|
|
315
|
+
| `--lane-value-width` | follows track (`0.12`) | Thickness of the `value` lane. Falls back to `--lane-track-width` when unset, so a thick track automatically gets a matching value bar; set it explicitly to diverge |
|
|
280
316
|
| `--lane-dasharray` | `none` | SVG `stroke-dasharray` applied to all lanes |
|
|
281
317
|
| `--lane-dashoffset` | `0` | SVG `stroke-dashoffset` — animate for marching-ants effect |
|
|
282
318
|
|
|
@@ -295,10 +331,12 @@ Dashed lanes:
|
|
|
295
331
|
```html
|
|
296
332
|
<ixfx-slider-input
|
|
297
333
|
min="0" max="100" value-a="60"
|
|
298
|
-
style="--track-width: 6; --lane-track-width: 0.
|
|
334
|
+
style="--track-width: 6; --lane-track-width: 0.7;"
|
|
299
335
|
></ixfx-slider-input>
|
|
300
336
|
```
|
|
301
337
|
|
|
338
|
+
The `value` lane follows `--lane-track-width` here — no need to set `--lane-value-width` unless you want it to differ from the track.
|
|
339
|
+
|
|
302
340
|
### Marker (value indicator)
|
|
303
341
|
|
|
304
342
|
| Variable | Default | Description |
|
|
@@ -387,7 +425,7 @@ With a border halo (useful for contrast against coloured lanes):
|
|
|
387
425
|
|
|
388
426
|
### `dot`
|
|
389
427
|
|
|
390
|
-
A filled circle placed at the value's track position. `--marker-offset` shifts it perpendicular to the track (0 = on the centreline, positive = away from the centreline in the track's perpendicular direction).
|
|
428
|
+
A filled circle placed at the value's track position. `--marker-offset` shifts it perpendicular to the track (0 = on the centreline, positive = away from the centreline in the track's perpendicular direction). The radius follows `--marker-thickness` with a screen-px floor (widest lane + 2px), so the dot always reads larger than the value track it sits on. It renders as an aspect-corrected ellipse in viewBox units, so it stays circular on screen despite the stretched viewBox.
|
|
391
429
|
|
|
392
430
|
```html
|
|
393
431
|
<!-- Dot on the track -->
|
|
@@ -595,12 +633,12 @@ The track, value bar, and markers all use the same `CROSS` axis for their perpen
|
|
|
595
633
|
|
|
596
634
|
### SVG gradient on the value bar
|
|
597
635
|
|
|
598
|
-
Define gradients in a hidden `<svg>` at the top of the page using `gradientUnits="userSpaceOnUse"`
|
|
636
|
+
Define gradients in a hidden `<svg>` at the top of the page using `gradientUnits="userSpaceOnUse"` spanning the full viewBox long axis (`0`–`100`; the track insets itself slightly for marker clearance, so full-bleed coordinates stay correct for any marker style), then reference them via `--lane-value-color`:
|
|
599
637
|
|
|
600
638
|
```html
|
|
601
639
|
<svg width="0" height="0" style="position:absolute" aria-hidden="true">
|
|
602
640
|
<defs>
|
|
603
|
-
<linearGradient id="slider-grad-h" gradientUnits="userSpaceOnUse" x1="
|
|
641
|
+
<linearGradient id="slider-grad-h" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="100" y2="0">
|
|
604
642
|
<stop offset="0%" stop-color="oklch(70% 0.22 25)" />
|
|
605
643
|
<stop offset="100%" stop-color="oklch(75% 0.22 145)" />
|
|
606
644
|
</linearGradient>
|
|
@@ -618,13 +656,15 @@ Define gradients in a hidden `<svg>` at the top of the page using `gradientUnits
|
|
|
618
656
|
|
|
619
657
|
These are lessons learned from building the component — useful context when building a similar thing from scratch.
|
|
620
658
|
|
|
621
|
-
### SVG in a
|
|
659
|
+
### SVG in a dynamic viewBox (tight cross axis + tight end inset)
|
|
660
|
+
|
|
661
|
+
All geometry is computed in a `100×cross` viewBox coordinate space for horizontal, or `cross×100` for vertical, with the track running along the long axis. Only `LONG = 100` stays fixed. Each render computes the tightest cross that fits the actual content — markers (`--marker-length/thickness/offset`), lane widths/offsets, and `--track-width` — as the fixed point `cross = pad / (0.5 − F)` where `F` is the largest fractional half-extent and `pad = 2` covers strokes/linecaps (clamped to 4…40, fractions capped at 0.45). The default needle slider lands around `cross ≈ 6.7` instead of the legacy `CROSS = 24`, so the element's block size hugs the track instead of reserving 7 units of dead air per side. `marker-style="none"` with thin lanes collapses to the minimum. The long-axis end insets are computed the same way from the markers' along-axis extent (dot/triangle caps extend past the track ends; needles need only the stroke pad), clamped to 1…5, so the track uses the full available width. Authored `--track-margin` / `--track-margin-start` / `--track-margin-end` are added on top per end (scaled back proportionally only if the track span would drop below 10 units). Pointer mapping is calibrated to the drawn track span, not the host edges, so the visible track ends hit min/max exactly. The SVG `viewBox` attribute handles scaling to actual DOM pixels, so every calculation stays coordinate-system-agnostic. Because the inset is dynamic, gradients should span the full `0`–`100` long axis rather than the old fixed `5`–`95` track span.
|
|
622
662
|
|
|
623
|
-
|
|
663
|
+
Lane stroke widths resolve to screen px per render (`width fraction × measured cross px`, emitted as a px number with `vector-effect: non-scaling-stroke` so it paints verbatim). A `calc(var * 24%)` percentage cannot do this job: percentages resolve against the host-size-independent viewBox diagonal (~71 units), so documented 0..1 fractions painted ~10x too thin and never scaled with the host. Because strokes are px-per-render, a host `ResizeObserver` re-renders on size changes to keep them (and the measured box) exact. Dashes stay frozen via the same `non-scaling-stroke`, so `--lane-dasharray` values keep their px meaning.
|
|
624
664
|
|
|
625
665
|
### Lane offset needs a CSS unit
|
|
626
666
|
|
|
627
|
-
`transform: translateY(${offset})` (unitless) is **invalid** CSS — a `<length>` is required, otherwise the whole `transform` declaration is dropped and the lane renders on the centreline. The code uses `translateY(${offset *
|
|
667
|
+
`transform: translateY(${offset})` (unitless) is **invalid** CSS — a `<length>` is required, otherwise the whole `transform` declaration is dropped and the lane renders on the centreline. The code uses `translateY(${offset * crossPx / 2}px)` so the offset stays a true fraction of the measured cross axis (with `px` suffix for CSS).
|
|
628
668
|
|
|
629
669
|
### Marker rendering uses `part` + per-handle CSS variable patterns
|
|
630
670
|
|