@fusion.dev/helix-docs 0.104.0 → 0.105.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.
Files changed (48) hide show
  1. package/content/accessibility.mdx +92 -71
  2. package/content/angular.mdx +26 -24
  3. package/content/browser-support.mdx +61 -58
  4. package/content/building-on-the-headless-tier.mdx +100 -74
  5. package/content/charting.mdx +98 -79
  6. package/content/coding-agents.mdx +87 -69
  7. package/content/color-modes.mdx +40 -37
  8. package/content/color.mdx +67 -54
  9. package/content/composition.mdx +85 -83
  10. package/content/elevation-and-material.mdx +32 -29
  11. package/content/events.mdx +77 -65
  12. package/content/forms.mdx +69 -58
  13. package/content/iconography.mdx +75 -71
  14. package/content/installation.mdx +77 -68
  15. package/content/intent-reference.mdx +59 -54
  16. package/content/introduction.mdx +25 -23
  17. package/content/localization.mdx +122 -82
  18. package/content/maps.mdx +222 -0
  19. package/content/metrics.mdx +294 -297
  20. package/content/motion.mdx +44 -36
  21. package/content/other-frameworks.mdx +33 -31
  22. package/content/overlays.mdx +72 -54
  23. package/content/overriding-a-component.mdx +85 -74
  24. package/content/react.mdx +72 -64
  25. package/content/recipes.mdx +64 -47
  26. package/content/routing.mdx +100 -93
  27. package/content/sandbox.mdx +39 -39
  28. package/content/server-rendering.mdx +95 -84
  29. package/content/shape-and-borders.mdx +44 -37
  30. package/content/size-and-density.mdx +51 -46
  31. package/content/space-and-size.mdx +41 -34
  32. package/content/state-and-control.mdx +63 -51
  33. package/content/surfaces-and-separation.mdx +55 -53
  34. package/content/svelte.mdx +20 -19
  35. package/content/theme-builder.mdx +42 -31
  36. package/content/theming.mdx +58 -51
  37. package/content/tiers.mdx +69 -61
  38. package/content/tokens.mdx +72 -53
  39. package/content/typography.mdx +47 -47
  40. package/content/using-helix-with-an-agent.mdx +147 -115
  41. package/content/using-the-elements.mdx +55 -50
  42. package/content/versioning.mdx +42 -35
  43. package/content/visual-axes.mdx +168 -146
  44. package/content/vue.mdx +24 -24
  45. package/content/without-a-bundler.mdx +40 -23
  46. package/dist/pages.generated.js +49 -43
  47. package/dist/sources.generated.js +3337 -2680
  48. package/package.json +3 -3
@@ -1,14 +1,14 @@
1
1
  ---
2
- description: Locale-aware controls, translatable strings, and a layout that already flips.
2
+ description: Set the locale of date, time, and number controls, translate component strings, and lay out pages right to left.
3
3
  section: Essentials
4
4
  title: Localization and RTL
5
5
  ---
6
6
 
7
7
  # Localization and RTL
8
8
 
9
- ## Right-to-left already works
9
+ ## Right-to-left layout
10
10
 
11
- Set `dir` and the layout flips:
11
+ Set `dir`, and the layout flips:
12
12
 
13
13
  ```html
14
14
  <html
@@ -17,46 +17,74 @@ Set `dir` and the layout flips:
17
17
  >
18
18
  ```
19
19
 
20
- Every component is written in logical properties, `inline-start` rather than
21
- `left`, `margin-block` rather than `margin-top`. Nothing infers the direction
22
- for you and nothing needs to: the document says it and the components follow.
23
-
24
- **A physical side appears only where the thing it places is physical.** A
25
- floating panel is placed from coordinates measured from the viewport's left
26
- edge, so it and its arrow are written in `left` and `top`. Everything a reader
27
- would expect to mirror still does.
28
-
29
- **Charts mirror too.** A category or time axis starts where the text does, so
30
- on a right-to-left page the first reading is on the right and the drawing,
31
- its labels, its hover targets and its tooltips all turn together. Values keep
32
- their vertical sense and numerals are not reversed. A whole donut stays
33
- clockwise from twelve, which is a clock's convention rather than a script's,
34
- and a scatter chart keeps its left-to-right plane, both of its axes being
35
- measures. [Charting](./charting) has the rest.
36
-
37
- **Carets and arrow keys turn too.** A caret meaning next or previous, the one
38
- between two crumbs and a shut disclosure all point along the line, so on a
39
- right-to-left page they point the other way, and every arrow key moves where it
40
- points on screen: the left arrow moves to the next tab, the next day, the next
41
- control in a toolbar, and opens a tree's branch or a menu's submenu, whose caret
42
- points left. A slider and a splitter's divider move the way the key points.
43
-
44
- A media player is an exception: its timeline and its skip buttons run left to
45
- right in every script, a tape having one direction, so the left arrow rewinds.
46
- A pin input is the other. A code is read like a phone number, so its boxes run
47
- left to right on every page: the first character typed goes in the leftmost
48
- box, a pasted code fills rightward and the right arrow moves on, while its
49
- label, hint and error read the way the page does.
50
-
51
- That is also how `placement` reads. The side is physical and the alignment is
52
- logical: `right` is the right of the anchor in either direction, and
53
- `bottom-start` lines a panel up with the anchor's start edge, which is its right
54
- edge on a right-to-left page. A panel with no room on its side still flips to
55
- the other one, so a `right-start` panel beside a rail at the start of a
56
- right-to-left page opens to its left.
57
-
58
- The same is true of anything you write on top. Use logical properties and your
59
- layout flips with ours; use `left` and `right` and it will not.
20
+ Components are written with logical properties, such as `inline-start` for
21
+ `left` and `margin-block` for `margin-top`. Helix does not detect the direction.
22
+ The components follow the `dir` that your document sets.
23
+
24
+ **Physical properties appear only where the position is physical.** A floating
25
+ panel is placed by coordinates measured from the viewport's left edge, so the
26
+ panel and its arrow use `left` and `top`. Everything you would expect to mirror
27
+ still mirrors.
28
+
29
+ ### Charts
30
+
31
+ A category or time axis starts on the same side as the text. On a right-to-left
32
+ page, the first value is on the right. The drawing, its labels, its hover
33
+ targets, and its tooltips all mirror together. The vertical axis does not
34
+ change, and numerals are not reversed. Two charts keep their direction:
35
+
36
+ - A whole donut runs clockwise from twelve o'clock, following the convention of
37
+ a clock.
38
+ - A scatter chart keeps its left-to-right plane, because both of its axes are
39
+ measures.
40
+
41
+ See [Charting](./charting) for the rest.
42
+
43
+ ### Carets and arrow keys
44
+
45
+ These carets point along the line of text:
46
+
47
+ - a caret that means next or previous
48
+ - the caret between two breadcrumbs
49
+ - the caret on a closed disclosure
50
+
51
+ On a right-to-left page, they point the other way. Every arrow key moves in the
52
+ direction it points on screen. On a right-to-left page, the Left Arrow key:
53
+
54
+ - moves to the next tab
55
+ - moves to the next day
56
+ - moves to the next control in a toolbar
57
+ - opens a tree's branch or a menu's submenu, whose caret points left
58
+
59
+ A slider and a splitter's divider move in the direction of the key.
60
+
61
+ ### Media players and pin inputs
62
+
63
+ These two components run left to right on every page.
64
+
65
+ A media player's timeline and skip buttons run left to right in every script,
66
+ like a tape, so the Left Arrow key rewinds.
67
+
68
+ A pin input's boxes run left to right, because a code is read like a phone
69
+ number. The first character you type goes in the leftmost box, a pasted code
70
+ fills to the right, and the Right Arrow key moves to the next box. The pin
71
+ input's label, hint, and error follow the direction of the page.
72
+
73
+ ### Floating panel placement
74
+
75
+ In `placement`, the side is physical and the alignment is logical:
76
+
77
+ - `right` is the right side of the anchor in both directions.
78
+ - `bottom-start` aligns a panel with the anchor's start edge, which is its right
79
+ edge on a right-to-left page.
80
+
81
+ A panel with no room on its side flips to the other side. A `right-start` panel
82
+ beside a rail at the start of a right-to-left page opens to its left.
83
+
84
+ ### Your own styles
85
+
86
+ Use logical properties in your own styles, so your layout flips with the
87
+ components. Styles written with `left` and `right` do not flip.
60
88
 
61
89
  ## Locale-aware controls
62
90
 
@@ -76,18 +104,18 @@ Six families format numbers or dates and take a `locale`:
76
104
  ></helix-pagination>
77
105
  ```
78
106
 
79
- Left unset, they use the browser's own locale, which is usually right. Set it
80
- when your application's language is a choice the reader made rather than the one
81
- their operating system is in.
107
+ If you do not set `locale`, these controls use the browser's locale, which is
108
+ usually correct. Set `locale` when your users choose your application's
109
+ language separately from the language of their operating system.
82
110
 
83
- Formatting goes through `Intl`, so there is no locale data bundled and nothing
84
- to keep up to date.
111
+ Formatting uses `Intl`, so Helix bundles no locale data, and you have nothing to
112
+ keep up to date.
85
113
 
86
- ## Translatable strings
114
+ ## Translate component strings
87
115
 
88
- Over a hundred properties across the headless tier are strings a reader sees,
89
- from `pan-up-label` on a map to `remove-label` on a combobox's chosen tags. The
90
- ones that combine values are format templates:
116
+ More than a hundred properties in the headless tier set text that your users
117
+ see. Examples include `pan-up-label` on a map and `remove-label` on a combobox's
118
+ selected tags. Properties that combine values are format templates:
91
119
 
92
120
  ```html
93
121
  <helix-pagination-summary
@@ -99,16 +127,22 @@ ones that combine values are format templates:
99
127
  ></helix-pagination-summary>
100
128
  ```
101
129
 
102
- The placeholders are named rather than positional, so a translation can reorder
103
- them, which some languages require and a positional format cannot express.
130
+ Placeholders have names, so a translation can put them in any order. Some
131
+ languages need a different order, and a positional format cannot express it.
104
132
 
105
- **Validation messages are properties too**, named for the validity flag each
106
- one reports: `value-missing-message`, `bad-input-message`,
107
- `range-underflow-message`, `range-overflow-message`, `too-short-message`. They
108
- reach the browser's own bubble as well as the line under the field, which
109
- `feedback` alone does not. Left unset, a text field keeps the browser's own
110
- message, which is already in the reader's language, and every other control
111
- keeps its English sentence.
133
+ Validation messages are properties too. Each one is named for the validity flag
134
+ it reports:
135
+
136
+ - `value-missing-message`
137
+ - `bad-input-message`
138
+ - `range-underflow-message`
139
+ - `range-overflow-message`
140
+ - `too-short-message`
141
+
142
+ A message appears in the browser's own validation bubble and on the line under
143
+ the field. `feedback` does not reach the bubble. If you do not set a message, a
144
+ text field shows the browser's own message, which is already in your user's
145
+ language. Every other control shows its English sentence.
112
146
 
113
147
  ```html
114
148
  <helix-number-input
@@ -118,22 +152,24 @@ keeps its English sentence.
118
152
  ></helix-number-input>
119
153
  ```
120
154
 
121
- **Pass these from your own translation system.** Helix ships English defaults
122
- and no translation machinery: a design system that owned the string catalog
123
- would be a second one to keep in step with yours.
124
-
125
- ## What to check when adding a language
126
-
127
- - **Long strings.** German and Finnish will find every control that assumed a
128
- short label. Controls take their width from the layout rather than carrying
129
- one, which helps, but a toolbar that fitted six buttons may now fit four.
130
- - **The `lang` attribute, not just the strings.** Hyphenation, quotation marks
131
- and font fallback all key off it.
132
- - **Numerals.** `Intl` handles the digits; a hardcoded `%` or a currency symbol
133
- in your own markup will not move to the right side.
134
- - **Icons that point.** A caret a component draws turns on its own. An icon you
135
- place does not unless you ask, because the names are physical: `mirror` turns
136
- one on a right-to-left page, for an arrow that means forward or back.
155
+ **Pass these strings from your own translation system.** Helix ships English
156
+ defaults and no translation tools. If Helix had its own string catalog, you
157
+ would have to keep two catalogs in step.
158
+
159
+ ## What to check when you add a language
160
+
161
+ - **Long strings.** Labels in German and Finnish are often long. A control sized
162
+ for a short label may not fit them. Controls take their width from the
163
+ layout and set no width of their own, which helps. A toolbar that fit six
164
+ buttons may now fit four.
165
+ - **The `lang` attribute.** Set it as well as translating the strings.
166
+ Hyphenation, quotation marks, and font fallback all depend on it.
167
+ - **Numerals.** `Intl` formats the digits. A `%` or a currency symbol hardcoded
168
+ in your own markup does not move to the correct side.
169
+ - **Icons that point.** A caret that a component draws turns by itself. An icon
170
+ you place turns only when you add `mirror`, because icon names are physical.
171
+ Use `mirror` on an arrow that means forward or back, and it turns on a
172
+ right-to-left page.
137
173
 
138
174
  ```html
139
175
  <helix-button>
@@ -146,9 +182,13 @@ would be a second one to keep in step with yours.
146
182
  </helix-button>
147
183
  ```
148
184
 
149
- ## What is not covered
185
+ ## What Helix does not provide
186
+
187
+ Helix does not include:
188
+
189
+ - a message catalog
190
+ - a pluralization helper
191
+ - a date-range formatter, beyond what the controls format themselves
150
192
 
151
- There is no message catalog, no pluralization helper and no date-range
152
- formatter beyond what the controls do for themselves. Those belong to your
153
- application's i18n layer, and every one of these properties is designed to be
154
- fed from it.
193
+ These belong to your application's i18n layer. You can set every translatable
194
+ property from that layer.
@@ -0,0 +1,222 @@
1
+ ---
2
+ description: Add interactive maps to your site, styled with your theme and drawn by MapLibre or Leaflet.
3
+ section: Essentials
4
+ title: Maps
5
+ ---
6
+
7
+ # Maps
8
+
9
+ Helix Maps puts a frame around a map drawn by MapLibre, Leaflet, or a renderer of
10
+ your own. The frame adds pan and zoom buttons and a place for the map credit. You
11
+ add places, routes, areas, live positions, and data as elements inside the
12
+ frame, and `@fusion.dev/helix-map` connects the frame to the renderer and styles
13
+ the map with your theme.
14
+
15
+ ## Add a map
16
+
17
+ Install Helix, the map connector, and MapLibre:
18
+
19
+ ```sh
20
+ bun add @fusion.dev/helix @fusion.dev/helix-map maplibre-gl
21
+ ```
22
+
23
+ Add the map frame, an element for MapLibre to draw in, and your places:
24
+
25
+ ```html
26
+ <helix-map label="Our stores">
27
+ <div id="map"></div>
28
+ <helix-map-marker label="Flagship" lat="30.2672" lng="-97.7431"></helix-map-marker>
29
+ </helix-map>
30
+ ```
31
+
32
+ Create the map with a style from your theme, then connect it to the frame:
33
+
34
+ ```js
35
+ import '@fusion.dev/helix'
36
+ import 'maplibre-gl/dist/maplibre-gl.css'
37
+ import { colorsReady, connectMap } from '@fusion.dev/helix-map'
38
+ import { followTheme, mapLibreDriver, mapLibreStyle } from '@fusion.dev/helix-map/maplibre'
39
+ import maplibregl from 'maplibre-gl'
40
+
41
+ const frame = document.querySelector('helix-map')
42
+ const style = (colors) => mapLibreStyle(colors)
43
+ const map = new maplibregl.Map({
44
+ attributionControl: false,
45
+ container: 'map',
46
+ style: style(await colorsReady(frame)),
47
+ })
48
+
49
+ const connection = connectMap(frame, mapLibreDriver(map))
50
+ connection.fit({ animate: false })
51
+ followTheme(map, frame, style)
52
+ ```
53
+
54
+ ## What the connector does
55
+
56
+ `connectMap` links the frame to the renderer:
57
+
58
+ - The frame's pan and zoom buttons and keys move the map, using your theme's
59
+ motion settings. The map moves without animation when a user has asked for
60
+ reduced motion.
61
+ - The renderer's own keyboard handling and zoom buttons are turned off, so the
62
+ frame's controls are the only ones.
63
+ - The renderer's credit is shown in the frame's footer.
64
+ - `connection.fit()` frames every place on the map.
65
+ - `connection.disconnect()` puts back everything `connectMap` changed.
66
+
67
+ Use `mapLibreDriver(map)` for MapLibre GL JS 5 and `leafletDriver(map, L)` for
68
+ Leaflet 1.9. Neither renderer is bundled with Helix, so you can use the version
69
+ you already have. Leaflet draws routes, areas, and points only when you pass it
70
+ `L`.
71
+
72
+ ## Style the map with your theme
73
+
74
+ `mapLibreStyle(colors)` builds a MapLibre style from five colors in your theme:
75
+
76
+ - Land uses `surface`.
77
+ - Water uses `info`.
78
+ - Parks use `success`.
79
+ - Main roads use `primary`, your brand color.
80
+ - Smaller roads, buildings, borders, and labels use `foreground`.
81
+
82
+ The same call builds a light map for a light theme and a dark map for a dark
83
+ theme. Map labels meet a contrast target of 4.5 against the land. Pass
84
+ `contrast` to change it, `language` to choose which name each place is labeled
85
+ with, and `tiles` and `glyphs` to use your own tile server.
86
+
87
+ `followTheme(map, frame, style)` restyles the map when your theme changes. It
88
+ watches for a new color mode, class, or theme value on the frame or its
89
+ ancestors, and for a change in the system's light or dark setting. If your page
90
+ changes its theme another way, such as by replacing a stylesheet, call
91
+ `update()` on the object `followTheme` returns.
92
+
93
+ `colorsReady(frame)` waits until your theme's colors can be read, which can take
94
+ a frame or two after the page loads. If the colors never become available, it
95
+ reports which one is missing.
96
+
97
+ ## What you can add to a map
98
+
99
+ | Element | What it adds |
100
+ |---|---|
101
+ | `helix-map-marker` | A named place on the map |
102
+ | `helix-map-route` | A line, such as a delivery route |
103
+ | `helix-map-area` | A shape, such as a delivery zone |
104
+ | `helix-map-position` | A moving point or arrow, such as a vehicle |
105
+ | `helix-map-points` | Thousands of places loaded from GeoJSON |
106
+
107
+ Each element takes `tone`, such as `primary` or `danger`, for its color.
108
+
109
+ ### Markers
110
+
111
+ ```html
112
+ <helix-map-marker label="Texas Capitol" lat="30.2747" lng="-97.7405" shape="ring">
113
+ <span slot="icon">B</span>
114
+ </helix-map-marker>
115
+ ```
116
+
117
+ A marker is a button placed at its latitude and longitude. Its `label` appears
118
+ when you hover over or focus the marker. The `icon` slot holds a letter, a
119
+ number, or an icon, and `shape` sets the marker's form: `ring`, `rounded`,
120
+ `square`, `diamond`, or `pin`. Pressing a marker sends `helix-activate` from the
121
+ frame with the marker's `name`, or its `label` if it has no name.
122
+
123
+ To show that a place has been visited, add `passed`. The marker is drawn in a
124
+ muted color, and screen readers hear its name followed by "passed". Use
125
+ `passed-label` to change that word.
126
+
127
+ ### Clusters
128
+
129
+ Add `cluster` to the frame to combine markers that would overlap into one
130
+ count. The count splits apart as you zoom in, and pressing it zooms in to its
131
+ places. Places at the same location, such as two businesses at one address,
132
+ spread out around that point when you press their count. Press Escape to
133
+ combine them again.
134
+
135
+ To handle a pressed cluster yourself, for example by listing its places in a
136
+ panel, pass `clusterZoom: false` to `connectMap` and listen for
137
+ `helix-map-cluster`.
138
+
139
+ ### Routes and areas
140
+
141
+ ```html
142
+ <helix-map-route
143
+ label="Depot to Mission"
144
+ description="4.2 km"
145
+ points="37.7955,-122.3937 37.7644,-122.427"
146
+ progress="0.4"
147
+ ></helix-map-route>
148
+ ```
149
+
150
+ Write `points` as `lat,lng` pairs separated by spaces. A route draws straight
151
+ lines between its points, so to follow streets, pass the path from a routing
152
+ service such as OSRM or Valhalla.
153
+
154
+ - `progress`, from 0 to 1, draws the part already traveled in a lighter color.
155
+ - `variant="dotted"` draws a route as dots, for a walk off the road network.
156
+ - `distancesAlong(points)` measures a route the same way the connector does, so
157
+ something you move along the route and the lighter part stay in step.
158
+
159
+ ### Live positions
160
+
161
+ ```html
162
+ <helix-map-position
163
+ label="Van 12"
164
+ lat="37.78"
165
+ lng="-122.41"
166
+ heading="90"
167
+ accuracy="30"
168
+ description="Two stops away"
169
+ ></helix-map-position>
170
+ ```
171
+
172
+ Update `lat`, `lng`, and `heading` as the position moves. `heading` turns it
173
+ into an arrow, and `accuracy` draws a ring with a radius of that many meters. Screen
174
+ readers announce its `description` when it changes, at most once every
175
+ `announce-every` milliseconds. Its movement is not announced.
176
+
177
+ ### Thousands of points
178
+
179
+ ```html
180
+ <helix-map-points label="Food and drink" src="/places.geojson" cluster></helix-map-points>
181
+ ```
182
+
183
+ Use `helix-map-points` for more places than markers can handle. MapLibre draws
184
+ all of them as one layer, loaded from a GeoJSON file in `src` or from data you
185
+ set on `data`. With `cluster`, nearby points combine into counts, and pressing a
186
+ count zooms in to it. Pressing a point sends `helix-activate` from the layer
187
+ with the point's id, or with the property named by `name-key`. Leaflet draws
188
+ each point on its own, which works for hundreds of points.
189
+
190
+ ## Keyboard and screen readers
191
+
192
+ - The frame is one tab stop. Arrow keys pan the map, and the plus and minus keys
193
+ zoom it.
194
+ - The markers are one tab stop. Arrow keys move between them in the order you
195
+ wrote them. The map pans to show a marker that is off screen.
196
+ - A points layer is one tab stop over the points and counts in view. Arrow keys
197
+ move top to bottom and along each line. Enter on a count zooms in to it.
198
+ - Screen readers find routes, areas, and points layers in a list inside the
199
+ frame, named by their `label` and `description`.
200
+
201
+ ## Write a driver
202
+
203
+ To use another renderer, write a driver: an object with two methods.
204
+
205
+ - `panBy(x, y, motion)` moves the map by a number of pixels.
206
+ - `zoomBy(direction, motion)` zooms in for `1` and out for `-1`.
207
+
208
+ `motion` is your theme's `{ duration, easing }`, or `null` to move without
209
+ animation. Each optional method turns on a feature:
210
+
211
+ | Method | Turns on |
212
+ |---|---|
213
+ | `project`, `onView` | Placing markers and positions |
214
+ | `show` | Bringing a focused marker into view |
215
+ | `fit` | `connection.fit()` and zooming in to clusters |
216
+ | `layers` | Drawing routes, areas, and points |
217
+ | `credits` | The map credit in the frame's footer |
218
+ | `silenceKeyboard`, `focusTarget`, `replaceZoom` | Using the frame's keys and zoom buttons |
219
+ | `bearing` | Arrows that stay correct when the map is rotated |
220
+
221
+ Without `project`, markers stay hidden. To animate a move your page makes
222
+ itself, read the same motion with `motionOf(element, pace)`.