actual-css 0.2.0 → 0.3.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/CHANGELOG.md +49 -1
- package/README.md +24 -9
- package/dist/actual-themes.min.css +1 -0
- package/dist/actual.css +1532 -1114
- package/dist/actual.js +1 -3
- package/dist/actual.min.css +1 -1
- package/dist/optional.css +1048 -0
- package/dist/optional.min.css +1 -0
- package/docs/design-notes/browser-support.md +94 -14
- package/docs/design-notes/cascade-layer.md +7 -6
- package/docs/design-notes/enhancement-contract.md +11 -14
- package/docs/design-notes/forced-colors.md +105 -0
- package/docs/design-notes/naming.md +2 -1
- package/docs/design-notes/platform-alignment.md +492 -0
- package/docs/design-notes/references.md +8 -0
- package/docs/design-notes/widget-primitives.md +37 -1
- package/docs/navigation.json +135 -0
- package/docs/pages/components/accordion.md +80 -0
- package/docs/pages/components/alert.md +203 -0
- package/docs/pages/components/aura.md +35 -0
- package/docs/pages/components/avatar.md +95 -0
- package/docs/pages/components/badge.md +102 -0
- package/docs/pages/components/breadcrumb.md +19 -0
- package/docs/pages/components/button.md +210 -0
- package/docs/pages/components/card.md +195 -0
- package/docs/pages/components/chat.md +50 -0
- package/docs/pages/components/dialog.md +367 -0
- package/docs/pages/components/drawer.md +113 -0
- package/docs/pages/components/fab.md +118 -0
- package/docs/pages/components/key.md +33 -0
- package/docs/pages/components/meter.md +23 -0
- package/docs/pages/components/navbar.md +92 -0
- package/docs/pages/components/pagination.md +55 -0
- package/docs/pages/components/progress.md +29 -0
- package/docs/pages/components/skeleton.md +38 -0
- package/docs/pages/components/spinner.md +93 -0
- package/docs/pages/components/table.md +102 -0
- package/docs/pages/enhancements/flyout.md +391 -0
- package/docs/pages/enhancements/overview.md +36 -0
- package/docs/pages/enhancements/scrollspy.md +71 -0
- package/docs/pages/enhancements/status-bar.md +72 -0
- package/docs/pages/enhancements/tabs.md +80 -0
- package/docs/pages/enhancements/tooltip.md +130 -0
- package/docs/pages/examples/overview.md +43 -0
- package/docs/pages/forms/choice-cards.md +102 -0
- package/docs/pages/forms/controls.md +32 -0
- package/docs/pages/forms/detached-actions.md +59 -0
- package/docs/pages/forms/floating-field.md +88 -0
- package/docs/pages/forms/form-actions.md +56 -0
- package/docs/pages/forms/input-policy.md +91 -0
- package/docs/pages/forms/joined-controls.md +37 -0
- package/docs/pages/forms/labels.md +42 -0
- package/docs/pages/forms/otp.md +50 -0
- package/docs/pages/forms/overview.md +188 -0
- package/docs/pages/forms/password.md +40 -0
- package/docs/pages/forms/range.md +17 -0
- package/docs/pages/forms/states-and-sizes.md +321 -0
- package/docs/pages/forms/sticky-actions.md +187 -0
- package/docs/pages/forms/switch.md +31 -0
- package/docs/pages/forms/validation.md +241 -0
- package/docs/{mental-model.md → pages/foundations/philosophy.md} +33 -18
- package/docs/pages/foundations/theming.md +99 -0
- package/docs/pages/foundations/tokens.md +421 -0
- package/docs/{typography.md → pages/foundations/typography.md} +27 -9
- package/docs/pages/guides/bootstrap.md +438 -0
- package/docs/pages/guides/introduction.md +157 -0
- package/docs/pages/guides/optional-components.md +33 -0
- package/docs/pages/guides/progressive-enhancement.md +686 -0
- package/docs/pages/guides/tailwind.md +455 -0
- package/docs/pages/layout/app-shell.md +25 -0
- package/docs/pages/layout/center.md +29 -0
- package/docs/pages/layout/cluster.md +59 -0
- package/docs/pages/layout/frame.md +30 -0
- package/docs/pages/layout/grid.md +142 -0
- package/docs/pages/layout/list.md +41 -0
- package/docs/pages/layout/media.md +28 -0
- package/docs/pages/layout/overview.md +37 -0
- package/docs/pages/layout/scroll-snap.md +54 -0
- package/docs/pages/layout/sidebar-layout.md +27 -0
- package/docs/pages/layout/stack.md +55 -0
- package/docs/pages/layout/switcher.md +36 -0
- package/docs/pages/layout/topbar.md +23 -0
- package/docs/pages/patterns/actions.md +52 -0
- package/docs/pages/patterns/code-block.md +36 -0
- package/docs/pages/patterns/exclusive-accordion.md +16 -0
- package/docs/pages/patterns/hierarchical-nav.md +26 -0
- package/docs/pages/patterns/icon-input.md +25 -0
- package/docs/pages/patterns/intent-nesting.md +3 -0
- package/docs/pages/patterns/navigation-list.md +235 -0
- package/docs/pages/patterns/overview.md +58 -0
- package/docs/pages/patterns/structured-lists.md +47 -0
- package/docs/pages/utilities/accessibility.md +34 -0
- package/docs/pages/utilities/flex.md +105 -0
- package/docs/pages/utilities/links.md +18 -0
- package/docs/pages/utilities/list.md +32 -0
- package/docs/pages/utilities/overflow.md +43 -0
- package/docs/pages/utilities/overview.md +18 -0
- package/docs/pages/utilities/shape.md +25 -0
- package/docs/pages/utilities/sizing-wrapping.md +115 -0
- package/docs/pages/utilities/spacing.md +79 -0
- package/docs/pages/utilities/text.md +43 -0
- package/llms.txt +4 -4
- package/package.json +21 -12
- package/src/css/actual.css +16 -2
- package/src/css/base.css +3 -5
- package/src/css/components/accordion.css +18 -30
- package/src/css/components/actions.css +4 -1
- package/src/css/components/alert.css +139 -102
- package/src/css/components/avatar.css +16 -10
- package/src/css/components/badge.css +69 -42
- package/src/css/components/breadcrumb.css +7 -15
- package/src/css/components/busy.css +6 -0
- package/src/css/components/button.css +84 -34
- package/src/css/components/card.css +26 -38
- package/src/css/components/drawer.css +30 -13
- package/src/css/components/flyout.css +39 -109
- package/src/css/components/index.css +1 -0
- package/src/css/components/join.css +14 -2
- package/src/css/components/key.css +2 -0
- package/src/css/components/menu.css +125 -0
- package/src/css/components/meter.css +0 -23
- package/src/css/components/modal.css +162 -7
- package/src/css/components/navbar.css +30 -23
- package/src/css/components/overline.css +8 -9
- package/src/css/components/pagination.css +1 -1
- package/src/css/components/progress.css +8 -26
- package/src/css/components/skeleton.css +7 -0
- package/src/css/components/spinner.css +6 -7
- package/src/css/components/status-bar.css +15 -24
- package/src/css/components/surface.css +2 -8
- package/src/css/components/tab.css +19 -48
- package/src/css/components/table.css +7 -5
- package/src/css/components/tooltip.css +14 -7
- package/src/css/focus.css +14 -38
- package/src/css/forms/choice-card.css +13 -14
- package/src/css/forms/choice.css +21 -27
- package/src/css/forms/control.css +18 -17
- package/src/css/forms/custom-select.css +9 -11
- package/src/css/forms/form-actions.css +14 -3
- package/src/css/forms/form.css +7 -4
- package/src/css/forms/index.css +4 -4
- package/src/css/forms/input-icon.css +30 -12
- package/src/css/forms/native.css +50 -11
- package/src/css/forms/range.css +17 -9
- package/src/css/forms/select.css +8 -8
- package/src/css/forms/switch.css +14 -12
- package/src/css/forms/validation.css +32 -5
- package/src/css/grid.css +32 -18
- package/src/css/intents.css +2 -2
- package/src/css/layout.css +45 -2
- package/src/css/optional/aura.css +93 -0
- package/src/css/optional/chat.css +105 -0
- package/src/css/optional/fab.css +104 -0
- package/src/css/optional/floating-field.css +87 -0
- package/src/css/optional/index.css +5 -0
- package/src/css/optional/layout-extra.css +7 -4
- package/src/css/optional/otp.css +115 -0
- package/src/css/optional/scroll-snap.css +6 -0
- package/src/css/optional/scroller.css +13 -7
- package/src/css/optional/typography-fluid.css +5 -0
- package/src/css/optional/utilities-extra.css +17 -2
- package/src/css/prose.css +18 -8
- package/src/css/reset.css +0 -10
- package/src/css/theme.css +21 -5
- package/src/css/themes/cyberpunk.css +1 -1
- package/src/css/themes/dim.css +3 -3
- package/src/css/themes/edge.css +8 -10
- package/src/css/themes/index.css +8 -4
- package/src/css/themes/{dark.css → indigo.css} +5 -4
- package/src/css/themes/neon.css +5 -5
- package/src/css/themes/square.css +0 -3
- package/src/css/tokens.css +74 -20
- package/src/css/utilities.css +8 -10
- package/src/css/variants.css +51 -66
- package/src/js/command.js +1 -3
- package/src/js/context-menu.js +67 -35
- package/src/js/dialog.js +68 -79
- package/src/js/dismiss.js +15 -0
- package/src/js/enhance.js +54 -23
- package/src/js/enhancement-loader.js +301 -0
- package/src/js/events.js +3 -0
- package/src/js/filter.js +3 -3
- package/src/js/floating.js +101 -131
- package/src/js/flyout.js +104 -87
- package/src/js/focus-group.js +116 -0
- package/src/js/focus.js +6 -1
- package/src/js/index.js +4 -2
- package/src/js/input.js +1 -1
- package/src/js/keys.js +27 -0
- package/src/js/mask.js +7 -6
- package/src/js/menu.js +87 -34
- package/src/js/parse-config.js +47 -0
- package/src/js/password.js +9 -1
- package/src/js/scrollspy.js +12 -4
- package/src/js/selectors.js +0 -7
- package/src/js/status.js +3 -1
- package/src/js/surface.js +187 -136
- package/src/js/tab.js +36 -53
- package/src/js/tooltip.js +70 -35
- package/src/js/validation.js +34 -8
- package/dist/actual.js.map +0 -31
- package/docs/README.md +0 -28
- package/docs/components.md +0 -860
- package/docs/design-notes/previous-work.md +0 -5
- package/docs/forms.md +0 -1265
- package/docs/javascript.md +0 -496
- package/docs/layout.md +0 -480
- package/docs/patterns.md +0 -504
- package/docs/reserved.md +0 -7
- package/docs/tokens.md +0 -455
- package/docs/ui.md +0 -929
- package/docs/utilities.md +0 -384
- package/src/css/dialog-fallback.css +0 -56
- package/src/js/dialog-fallback.js +0 -163
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
# Flyout
|
|
2
|
+
|
|
3
|
+
> Positioned surface attached to a trigger, commonly used for action lists and small panels.
|
|
4
|
+
|
|
5
|
+
## Class reference
|
|
6
|
+
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `.flyout-trigger` | Composition | Positioning wrapper for a trigger and its panel; gives the flyout a local absolute-position fallback before JavaScript positions it. |
|
|
10
|
+
| `.stretch` | Modifier | Stretches a `.flyout-trigger` to span its container, e.g. the last row of a full-width sidebar nav list. |
|
|
11
|
+
| `.flyout` | Component | Floating action or nav surface, positioned by JavaScript. |
|
|
12
|
+
| `.menu` | Component | Action-list primitive with strict `.menu > li > .menu-item` anatomy. |
|
|
13
|
+
| `.menu-item` | Component | One action row; participates in roving focus. |
|
|
14
|
+
| `.menu-item-icon` | Slot | Fixed leading column for a decorative icon. |
|
|
15
|
+
| `.menu-item-text` | Slot | Flexible label column; truncates when the row is constrained. |
|
|
16
|
+
| `.menu-item-end` | Slot | Trailing metadata such as a shortcut, badge, or status. |
|
|
17
|
+
| `.menu-label` | Variant | Muted section heading inside a menu; not interactive. |
|
|
18
|
+
| `.menu-separator` | Variant | Divider between menu groups (`<hr role="separator">`). |
|
|
19
|
+
| `.sm` / `.lg` | Variant | Compact or large density. |
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Flyout and context menu share one action-surface runtime:
|
|
24
|
+
|
|
25
|
+
- Flyout = a visible trigger opens a surface.
|
|
26
|
+
- Context menu = right click or a keyboard context action opens that same surface.
|
|
27
|
+
- Sheet = mobile presentation mode of that same surface.
|
|
28
|
+
|
|
29
|
+
### Trigger wiring
|
|
30
|
+
|
|
31
|
+
The runtime resolves the panel from the trigger, so the wiring is part of the
|
|
32
|
+
contract:
|
|
33
|
+
|
|
34
|
+
- Put `data-enhance="flyout"` on the **trigger** (the button, link, or other
|
|
35
|
+
clickable element), never on a wrapper around it.
|
|
36
|
+
- The trigger references its panel with `aria-controls="…"` and the panel owns
|
|
37
|
+
the matching `id`. The runtime reads `aria-controls` to find the panel — a
|
|
38
|
+
trigger without the pairing never opens anything.
|
|
39
|
+
- Wrap the trigger and panel in `.flyout-trigger`. It is the positioning
|
|
40
|
+
context for the no-JS fallback: without it the panel lays out against the
|
|
41
|
+
nearest positioned ancestor (or the page edge) instead of under the trigger.
|
|
42
|
+
- Start the panel with `hidden` so it does not flash open before the runtime
|
|
43
|
+
hides and positions it.
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<div class="flyout-trigger">
|
|
47
|
+
<button data-enhance="flyout"
|
|
48
|
+
aria-expanded="false"
|
|
49
|
+
aria-controls="my-panel">
|
|
50
|
+
Menu
|
|
51
|
+
</button>
|
|
52
|
+
<div class="flyout" id="my-panel" hidden>…</div>
|
|
53
|
+
</div>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Use `data-flyout-mobile` on the flyout to control mobile behavior:
|
|
57
|
+
|
|
58
|
+
- `auto` is the default. It keeps the surface anchored on desktop and switches to a bottom sheet on coarse pointers below the breakpoint.
|
|
59
|
+
- `sheet` always uses the sheet presentation.
|
|
60
|
+
- `anchored` always uses floating positioning.
|
|
61
|
+
- `none` disables the mobile transformation.
|
|
62
|
+
|
|
63
|
+
`data-flyout-breakpoint` only matters for `auto`. Prefer the built-in tokens
|
|
64
|
+
(`sm`, `md`, `lg`) and use raw pixel values only as an escape hatch, for example
|
|
65
|
+
`data-flyout-breakpoint="640"`.
|
|
66
|
+
|
|
67
|
+
Use `data-flyout-placement` for the preferred anchored placement. It accepts the
|
|
68
|
+
placement strings supported by the floating runtime, such as `bottom-start`,
|
|
69
|
+
`bottom-end`, `top-start`, `right`, or `left`.
|
|
70
|
+
|
|
71
|
+
Use `data-flyout-distance` for the trigger gap in pixels. The default is `4`.
|
|
72
|
+
|
|
73
|
+
Use `data-flyout-auto-close` when the default click dismissal behavior is not
|
|
74
|
+
right. Escape still follows the shared surface lifecycle.
|
|
75
|
+
|
|
76
|
+
- `true` is the default. Clicks inside or outside close the flyout.
|
|
77
|
+
- `inside` closes on inside clicks only.
|
|
78
|
+
- `outside` closes on outside click only.
|
|
79
|
+
- `false` disables automatic click closing.
|
|
80
|
+
|
|
81
|
+
These values follow Bootstrap's auto-close vocabulary. They apply to action
|
|
82
|
+
menus and rich panels alike. Add `data-flyout-close` to a control inside the
|
|
83
|
+
flyout when that specific control must close it regardless of the automatic
|
|
84
|
+
policy. This is useful for an Apply or Done action in an `outside` or `false`
|
|
85
|
+
panel. The trigger and Escape continue to close the flyout in every mode.
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<div class="flyout"
|
|
89
|
+
id="filters"
|
|
90
|
+
data-flyout-auto-close="outside"
|
|
91
|
+
hidden>
|
|
92
|
+
<label><input type="checkbox"> Available only</label>
|
|
93
|
+
<button type="button" data-flyout-close>Done</button>
|
|
94
|
+
</div>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Flyout covers two distinct patterns, detected by the `<menu>` element or
|
|
98
|
+
`.menu` class on the panel:
|
|
99
|
+
|
|
100
|
+
## Action list
|
|
101
|
+
|
|
102
|
+
A list of *actions* the user can take: sign out, copy, delete.
|
|
103
|
+
|
|
104
|
+
- Flyout triggers are opt-in: add `data-enhance="flyout"` to the trigger.
|
|
105
|
+
- Wrap the trigger and flyout in `.flyout-trigger` when the flyout should have a local absolute-position fallback before JavaScript positions it. Add `.stretch` when the trigger must span its container, such as the last row of a full-width sidebar nav list.
|
|
106
|
+
- Use `<menu class="flyout menu">` with strict anatomy: `.menu > li > .menu-item`. Items must carry the `.menu-item` class to participate in directional keyboard navigation. ArrowUp/Down and Home/End move focus without rewriting their normal tab stops.
|
|
107
|
+
- Use `.menu-label` on a `li` for a muted section heading inside a menu (e.g. a group title before its items). It is non-interactive and does not participate in roving focus. Use `.menu-separator` (`<hr role="separator">`) between groups.
|
|
108
|
+
- Items are regular `<button>` or `<a>` elements.
|
|
109
|
+
- Use `.sm` or `.lg` for density changes.
|
|
110
|
+
- Add `role="menu"` / `role="menuitem"` only when you intentionally need the ARIA menu pattern described below.
|
|
111
|
+
|
|
112
|
+
```html demo
|
|
113
|
+
<div class="flyout-trigger">
|
|
114
|
+
<button class="btn outline"
|
|
115
|
+
type="button"
|
|
116
|
+
data-enhance="flyout"
|
|
117
|
+
aria-expanded="false"
|
|
118
|
+
aria-controls="account-actions"
|
|
119
|
+
id="account-flyout-trigger">
|
|
120
|
+
Account
|
|
121
|
+
<i class="ti ti-chevron-down" aria-hidden="true"></i>
|
|
122
|
+
</button>
|
|
123
|
+
|
|
124
|
+
<menu class="flyout sm menu"
|
|
125
|
+
id="account-actions"
|
|
126
|
+
aria-labelledby="account-flyout-trigger"
|
|
127
|
+
hidden>
|
|
128
|
+
<li><button class="menu-item" type="button">Profile</button></li>
|
|
129
|
+
<li><button class="menu-item" type="button">Settings</button></li>
|
|
130
|
+
<hr class="menu-separator" role="separator">
|
|
131
|
+
<li><button class="menu-item danger" type="button">Sign out</button></li>
|
|
132
|
+
</menu>
|
|
133
|
+
</div>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### ARIA menu pattern
|
|
137
|
+
|
|
138
|
+
Adding `role="menu"` opts the action list into a composite with one roving tab
|
|
139
|
+
stop. Its usable `.menu-item` children with `role="menuitem"`,
|
|
140
|
+
`role="menuitemcheckbox"`, or `role="menuitemradio"` participate in vertical,
|
|
141
|
+
wrapping Arrow/Home/End navigation. Items without one of those roles are not
|
|
142
|
+
part of the focus group. Plain `.menu` action lists keep every item's normal
|
|
143
|
+
tab stop instead.
|
|
144
|
+
|
|
145
|
+
The runtime owns only focus movement and `tabindex`. The application still owns
|
|
146
|
+
command state and updates attributes such as `aria-checked`.
|
|
147
|
+
|
|
148
|
+
### Rich items and selection state
|
|
149
|
+
|
|
150
|
+
Wrap rich item content in the three optional slots when a menu needs aligned
|
|
151
|
+
icons or trailing metadata. Keep decorative icons hidden from assistive
|
|
152
|
+
technology. Plain text directly inside `.menu-item` remains valid for simple
|
|
153
|
+
actions.
|
|
154
|
+
|
|
155
|
+
```html
|
|
156
|
+
<li>
|
|
157
|
+
<button class="menu-item" type="button" role="menuitem">
|
|
158
|
+
<span class="menu-item-icon" aria-hidden="true">…</span>
|
|
159
|
+
<span class="menu-item-text">Duplicate</span>
|
|
160
|
+
<span class="menu-item-end"><kbd>⌘D</kbd></span>
|
|
161
|
+
</button>
|
|
162
|
+
</li>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Use `role="menuitemcheckbox"` for independent options and
|
|
166
|
+
`role="menuitemradio"` for an exclusive choice. Put `aria-checked` on the menu
|
|
167
|
+
item itself; do not nest a checkbox, radio, or switch inside it. The runtime
|
|
168
|
+
recognizes all three menu-item roles for keyboard activation and the CSS draws
|
|
169
|
+
their state indicator. The application remains responsible for updating
|
|
170
|
+
`aria-checked`, just as it owns the state behind the command.
|
|
171
|
+
|
|
172
|
+
```html
|
|
173
|
+
<li>
|
|
174
|
+
<button class="menu-item"
|
|
175
|
+
type="button"
|
|
176
|
+
role="menuitemcheckbox"
|
|
177
|
+
aria-checked="true">
|
|
178
|
+
<span class="menu-item-text">Show weekends</span>
|
|
179
|
+
</button>
|
|
180
|
+
</li>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Badges and shortcuts are passive trailing metadata. If a trailing pin, switch,
|
|
184
|
+
or button is independently interactive, use a rich flyout panel with normal
|
|
185
|
+
Tab navigation instead of `role="menu"`: a menu item must remain one command.
|
|
186
|
+
|
|
187
|
+
## Nav panel
|
|
188
|
+
|
|
189
|
+
A panel of *links* to other pages: product categories, docs sections. Nav panels
|
|
190
|
+
can be multi-column with `<section>` / `<ul>` groups.
|
|
191
|
+
|
|
192
|
+
- Items are regular `<a href>` links, not `role="menuitem"`.
|
|
193
|
+
- No roving focus — ArrowDown/Enter open the panel and focus the first focusable descendant. Tab from an open trigger also enters the panel. There is no arrow-key navigation between items inside.
|
|
194
|
+
- Just a toggle with outside-click and Escape dismissal.
|
|
195
|
+
- Use grid utilities, such as `.grid-3`, for wider multi-column flyouts.
|
|
196
|
+
|
|
197
|
+
```html demo
|
|
198
|
+
<nav aria-label="Main navigation">
|
|
199
|
+
<ul class="list-reset cluster">
|
|
200
|
+
<li class="flyout-trigger">
|
|
201
|
+
<button class="btn ghost"
|
|
202
|
+
type="button"
|
|
203
|
+
data-enhance="flyout"
|
|
204
|
+
aria-expanded="false"
|
|
205
|
+
aria-controls="products-panel">
|
|
206
|
+
Products
|
|
207
|
+
<i class="ti ti-chevron-down" aria-hidden="true"></i>
|
|
208
|
+
</button>
|
|
209
|
+
|
|
210
|
+
<div class="flyout"
|
|
211
|
+
id="products-panel"
|
|
212
|
+
aria-label="Products"
|
|
213
|
+
data-flyout-mobile="auto"
|
|
214
|
+
hidden>
|
|
215
|
+
<section aria-labelledby="products-design">
|
|
216
|
+
<h3 id="products-design">Design</h3>
|
|
217
|
+
<ul>
|
|
218
|
+
<li><a href="/figma">Figma integration</a></li>
|
|
219
|
+
<li><a href="/tokens">Design tokens</a></li>
|
|
220
|
+
</ul>
|
|
221
|
+
</section>
|
|
222
|
+
|
|
223
|
+
<section aria-labelledby="products-dev">
|
|
224
|
+
<h3 id="products-dev">Development</h3>
|
|
225
|
+
<ul>
|
|
226
|
+
<li><a href="/components">Components</a></li>
|
|
227
|
+
<li><a href="/api">API</a></li>
|
|
228
|
+
</ul>
|
|
229
|
+
</section>
|
|
230
|
+
|
|
231
|
+
<footer>
|
|
232
|
+
<a href="/pricing" class="btn primary">See pricing</a>
|
|
233
|
+
</footer>
|
|
234
|
+
</div>
|
|
235
|
+
</li>
|
|
236
|
+
|
|
237
|
+
<li><a href="/about" class="btn ghost">About</a></li>
|
|
238
|
+
<li><a href="/contact" class="btn ghost">Contact</a></li>
|
|
239
|
+
</ul>
|
|
240
|
+
</nav>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Mega menu
|
|
244
|
+
|
|
245
|
+
Use `class="flyout grid-3"` when a nav panel needs multiple link groups. Keep
|
|
246
|
+
links regular anchors and let the panel collapse to a one-column sheet on mobile
|
|
247
|
+
with `data-flyout-mobile="auto"`.
|
|
248
|
+
|
|
249
|
+
```html demo
|
|
250
|
+
<nav aria-label="Product navigation">
|
|
251
|
+
<ul class="list-reset cluster">
|
|
252
|
+
<li class="flyout-trigger">
|
|
253
|
+
<button class="btn ghost"
|
|
254
|
+
type="button"
|
|
255
|
+
data-enhance="flyout"
|
|
256
|
+
aria-expanded="false"
|
|
257
|
+
aria-controls="product-mega-menu">
|
|
258
|
+
Platform
|
|
259
|
+
<i class="ti ti-chevron-down" aria-hidden="true"></i>
|
|
260
|
+
</button>
|
|
261
|
+
|
|
262
|
+
<div class="flyout grid-3"
|
|
263
|
+
id="product-mega-menu"
|
|
264
|
+
aria-label="Platform"
|
|
265
|
+
data-flyout-mobile="auto"
|
|
266
|
+
style="--flyout-inline-size: 42rem; --flyout-max-inline-size: 42rem"
|
|
267
|
+
hidden>
|
|
268
|
+
<section aria-labelledby="mega-design">
|
|
269
|
+
<h3 id="mega-design">Design</h3>
|
|
270
|
+
<ul>
|
|
271
|
+
<li><a href="/figma">Figma integration</a></li>
|
|
272
|
+
<li><a href="/tokens">Design tokens</a></li>
|
|
273
|
+
<li><a href="/handoff">Developer handoff</a></li>
|
|
274
|
+
</ul>
|
|
275
|
+
</section>
|
|
276
|
+
|
|
277
|
+
<section aria-labelledby="mega-develop">
|
|
278
|
+
<h3 id="mega-develop">Development</h3>
|
|
279
|
+
<ul>
|
|
280
|
+
<li><a href="/components">Components</a></li>
|
|
281
|
+
<li><a href="/api">API</a></li>
|
|
282
|
+
<li><a href="/changelog">Changelog</a></li>
|
|
283
|
+
</ul>
|
|
284
|
+
</section>
|
|
285
|
+
|
|
286
|
+
<section aria-labelledby="mega-operate">
|
|
287
|
+
<h3 id="mega-operate">Operate</h3>
|
|
288
|
+
<ul>
|
|
289
|
+
<li><a href="/analytics">Analytics</a></li>
|
|
290
|
+
<li><a href="/security">Security</a></li>
|
|
291
|
+
<li><a href="/support">Support</a></li>
|
|
292
|
+
</ul>
|
|
293
|
+
</section>
|
|
294
|
+
|
|
295
|
+
<footer class="cluster"
|
|
296
|
+
style="grid-column: 1 / -1; --cluster-justify: flex-end; border-block-start: var(--border-width) solid var(--border)">
|
|
297
|
+
<a href="/pricing" class="btn primary">See pricing</a>
|
|
298
|
+
</footer>
|
|
299
|
+
</div>
|
|
300
|
+
</li>
|
|
301
|
+
</ul>
|
|
302
|
+
</nav>
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Context menu
|
|
306
|
+
|
|
307
|
+
Context menus use the same `.menu > li > .menu-item` presentation primitive as
|
|
308
|
+
action-list flyouts.
|
|
309
|
+
|
|
310
|
+
Put `data-context-menu` on the smallest unit the actions operate on: a file row,
|
|
311
|
+
card, or canvas item. Several units may reference the same
|
|
312
|
+
`<menu class="flyout">`. An explicit trigger button inside the unit, marked with
|
|
313
|
+
`data-context-menu-trigger` and `aria-controls`, opens the menu through the same
|
|
314
|
+
context-aware path — its `aria-controls` must match the `data-context-menu` id
|
|
315
|
+
of the host.
|
|
316
|
+
|
|
317
|
+
Before opening, the context element dispatches the cancelable
|
|
318
|
+
`actual:context-menu` event. Its `detail` contains the shared `menu`, the owning
|
|
319
|
+
`context`, the exact `origin`, and the opening `trigger` (`pointer`, `touch`,
|
|
320
|
+
`keyboard`, or `button`). Use it to tailor the static menu to the selected item,
|
|
321
|
+
or cancel the event to keep it closed. `contextFor(menu)` from
|
|
322
|
+
`actual-css/js/context-menu` returns that detail while handling a menu action.
|
|
323
|
+
Context menus dismiss when a new user interaction scrolls their surrounding
|
|
324
|
+
content. Scroll caused by opening focus, and scrolling inside the menu itself,
|
|
325
|
+
do not dismiss it.
|
|
326
|
+
|
|
327
|
+
Add `data-context-menu-scope` only when the flyout should stay inside a specific
|
|
328
|
+
region. Empty or `self` constrains to the target itself, `parent` constrains to
|
|
329
|
+
the parent, and a selector constrains to the closest matching ancestor or first
|
|
330
|
+
matching element. The scope also constrains the available height, so omit it
|
|
331
|
+
when the menu is allowed to escape the card or list item.
|
|
332
|
+
|
|
333
|
+
Long press is opt-in with `data-context-menu-long-press`. Empty uses the default
|
|
334
|
+
delay; a number sets the delay in milliseconds.
|
|
335
|
+
|
|
336
|
+
```html demo
|
|
337
|
+
<div class="card stack"
|
|
338
|
+
id="file-card"
|
|
339
|
+
data-context-menu="file-actions"
|
|
340
|
+
data-context-menu-long-press
|
|
341
|
+
tabindex="0"
|
|
342
|
+
style="min-block-size: 12rem;">
|
|
343
|
+
<div class="cluster justify-content-space-between items-center">
|
|
344
|
+
<strong>File.pdf</strong>
|
|
345
|
+
<button class="btn ghost"
|
|
346
|
+
type="button"
|
|
347
|
+
data-context-menu-trigger
|
|
348
|
+
aria-controls="file-actions"
|
|
349
|
+
id="file-actions-trigger">
|
|
350
|
+
More
|
|
351
|
+
</button>
|
|
352
|
+
</div>
|
|
353
|
+
<p class="text-sm text-muted">Right click a detail below, press the context-menu key, or use More.</p>
|
|
354
|
+
<div class="cluster">
|
|
355
|
+
<span class="badge" data-context-item="File name">File.pdf</span>
|
|
356
|
+
<span class="badge" data-context-item="Owner">Design team</span>
|
|
357
|
+
</div>
|
|
358
|
+
<output id="context-result" class="text-sm text-muted" aria-live="polite">No context selected.</output>
|
|
359
|
+
|
|
360
|
+
<menu class="flyout menu"
|
|
361
|
+
id="file-actions"
|
|
362
|
+
aria-labelledby="file-actions-trigger"
|
|
363
|
+
hidden>
|
|
364
|
+
<li><button class="menu-item" type="button">Open</button></li>
|
|
365
|
+
<li><button class="menu-item" type="button">Rename</button></li>
|
|
366
|
+
<hr class="menu-separator" role="separator">
|
|
367
|
+
<li><button class="menu-item danger" type="button">Delete</button></li>
|
|
368
|
+
</menu>
|
|
369
|
+
</div>
|
|
370
|
+
|
|
371
|
+
<script>
|
|
372
|
+
const card = document.getElementById("file-card");
|
|
373
|
+
const result = document.getElementById("context-result");
|
|
374
|
+
|
|
375
|
+
card.addEventListener("actual:context-menu", (event) => {
|
|
376
|
+
const item = event.detail.origin.closest?.("[data-context-item]");
|
|
377
|
+
const label = item?.dataset.contextItem ?? "the card";
|
|
378
|
+
result.textContent = `Menu opened for ${label} (${event.detail.trigger}).`;
|
|
379
|
+
});
|
|
380
|
+
</script>
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## CSS hooks
|
|
384
|
+
|
|
385
|
+
- `--flyout-inline-size` — panel width.
|
|
386
|
+
- `--flyout-max-inline-size` — panel width cap.
|
|
387
|
+
- `--menu-item-size` — minimum row height of `.menu-item`.
|
|
388
|
+
- `--menu-item-icon-size` — shared leading-column width for icons and checked-state indicators.
|
|
389
|
+
|
|
390
|
+
`--available-height` and `--surface-anchor-width` are written by the positioner
|
|
391
|
+
at runtime, not set by the author. See the JavaScript runtime documentation.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Progressive Enhancements
|
|
2
|
+
|
|
3
|
+
> The optional JavaScript runtime that completes Actual's interactive components — dialog, drawer, flyout, tooltip, tabs, scrollspy, and status bar — through progressive enhancement.
|
|
4
|
+
|
|
5
|
+
UI components need JavaScript or modern platform behavior to be complete. They
|
|
6
|
+
follow the same principles as every component: semantic markup first, small
|
|
7
|
+
class API, shared tokens, and progressive enhancement.
|
|
8
|
+
|
|
9
|
+
- CSS owns layout, surfaces, state styling, and transitions.
|
|
10
|
+
- JavaScript owns open/closed state, ARIA synchronization, focus management, keyboard behavior, and dismissal.
|
|
11
|
+
- Prefer native platform features when they fit, with small helpers where browser support or ergonomics need it.
|
|
12
|
+
- Keep behavior optional when possible. Markup should remain understandable without JavaScript.
|
|
13
|
+
- Use shared button classes and variants for triggers.
|
|
14
|
+
- Do not add toasts. Use alerts, status regions, dialogs, or inline validation instead.
|
|
15
|
+
|
|
16
|
+
## Modules
|
|
17
|
+
|
|
18
|
+
The full runtime is `actual-css/js`. Each enhancer is also importable on its own
|
|
19
|
+
for projects that use custom components or want a smaller behavior surface:
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
import "actual-css/js/dialog";
|
|
23
|
+
import "actual-css/js/flyout";
|
|
24
|
+
import "actual-css/js/tooltip";
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Enhancer modules self-register when imported. They do not require init calls and
|
|
28
|
+
are safe to import during server-side rendering: outside a browser, registration
|
|
29
|
+
is a no-op until the module is loaded again with a DOM.
|
|
30
|
+
|
|
31
|
+
## Component pages
|
|
32
|
+
|
|
33
|
+
Each interactive component has its own page documenting the exact markup its
|
|
34
|
+
enhancement expects: Dialog, Drawer, Flyout, Tooltip, Tabs, Scrollspy, and
|
|
35
|
+
Status Bar. The default runtime is loaded on the docs pages, so the examples
|
|
36
|
+
work with the documented markup alone.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Scrollspy
|
|
2
|
+
|
|
3
|
+
> Behavior hook for navigation that marks the active section while the page scrolls.
|
|
4
|
+
|
|
5
|
+
Scrollspy is a behavior hook, not a visual component. It marks a navigation
|
|
6
|
+
region for the JavaScript enhancement. Pair it with `.nav-list` and `.nav-link`,
|
|
7
|
+
or style `[aria-current]` yourself.
|
|
8
|
+
|
|
9
|
+
## Class reference
|
|
10
|
+
|
|
11
|
+
| Class | Kind | Description |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `.scrollspy` | Component | Marks the nav region for the enhancer; adds no visual styles. |
|
|
14
|
+
| `.nav-list` | Composition | Vertical list of navigation links. |
|
|
15
|
+
| `.nav-link` | Component | Navigation link whose active state comes from `[aria-current]`. |
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
- `.scrollspy` marks the region for JS detection. It does not add visual styles.
|
|
20
|
+
- `.nav-list` and `.nav-link` provide the visible list and active link styling.
|
|
21
|
+
- The JS enhancer toggles `aria-current="location"` on the active link. Without JavaScript, the links remain regular anchor links.
|
|
22
|
+
- Detection is geometric and deterministic: on each scroll, the active section is the last one whose top has crossed an activation line. Reaching the end of the scroll always activates the last section, and sitting above the first activates none.
|
|
23
|
+
- `data-scrollspy-root="#container"` measures a scroll container instead of the viewport.
|
|
24
|
+
- `data-scrollspy-offset` moves the activation line: a bare number or `px` value is pixels, a `%` value is a share of the root's visible height. Invalid values fall back to `20%`, and negatives clamp to `0`.
|
|
25
|
+
- The same markup also works with the CSS-native scroll markers path (see below).
|
|
26
|
+
|
|
27
|
+
```html demo
|
|
28
|
+
<nav class="scrollspy" data-enhance="scrollspy" aria-label="Page sections">
|
|
29
|
+
<ol class="nav-list stack">
|
|
30
|
+
<li><a class="nav-link" href="#overview" aria-current="location">Overview</a></li>
|
|
31
|
+
<li><a class="nav-link" href="#tokens">Tokens</a></li>
|
|
32
|
+
<li><a class="nav-link" href="#components">Components</a></li>
|
|
33
|
+
</ol>
|
|
34
|
+
</nav>
|
|
35
|
+
|
|
36
|
+
<main>
|
|
37
|
+
<section id="overview" tabindex="-1">
|
|
38
|
+
<h2>Overview</h2>
|
|
39
|
+
</section>
|
|
40
|
+
|
|
41
|
+
<section id="tokens" tabindex="-1">
|
|
42
|
+
<h2>Tokens</h2>
|
|
43
|
+
</section>
|
|
44
|
+
|
|
45
|
+
<section id="components" tabindex="-1">
|
|
46
|
+
<h2>Components</h2>
|
|
47
|
+
</section>
|
|
48
|
+
</main>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Native scroll markers
|
|
52
|
+
|
|
53
|
+
Modern browsers are starting to support CSS-native scroll markers with
|
|
54
|
+
`scroll-target-group` and `:target-current`. This can style the active link
|
|
55
|
+
without JavaScript.
|
|
56
|
+
|
|
57
|
+
```css
|
|
58
|
+
@supports selector(:target-current) {
|
|
59
|
+
.scrollspy {
|
|
60
|
+
scroll-target-group: auto;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.scrollspy a:target-current {
|
|
64
|
+
color: var(--primary);
|
|
65
|
+
font-weight: var(--font-weight-medium);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Keep this as progressive enhancement. The JavaScript enhancement remains the
|
|
71
|
+
portable fallback — the same markup serves both paths.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Status Bar
|
|
2
|
+
|
|
3
|
+
> Singleton floating area for short, non-critical, transient feedback.
|
|
4
|
+
|
|
5
|
+
A status bar is a single live region, not a stacked toaster. New messages
|
|
6
|
+
replace the previous one. Keep one element in the HTML, styled with
|
|
7
|
+
`.status-bar` and carrying the `[data-status][role="status"]` contract that the
|
|
8
|
+
runtime targets, empty by default.
|
|
9
|
+
|
|
10
|
+
- JavaScript only updates its text content; it shows when non-empty and hides when empty, while staying available as a live region.
|
|
11
|
+
- Use it for transient status (`Saved.`, `Reconnected.`, `Copied.`). Critical, persistent, or actionable information belongs in `.alert`, inline messages, or dialogs.
|
|
12
|
+
- Intents: `danger`, `success`, `warning`, `neutral`. The default (no intent) is a neutral dark pill.
|
|
13
|
+
|
|
14
|
+
The runtime auto-wires the status bar to Actual's form validation: a form that
|
|
15
|
+
fails to submit shows its `data-validation-message` in the status bar with the
|
|
16
|
+
`danger` intent. No target in the DOM means the call is a no-op, so the markup
|
|
17
|
+
stays optional.
|
|
18
|
+
|
|
19
|
+
```html demo
|
|
20
|
+
<form class="needs-validation" data-enhance="validation" data-validation-message="Please check the highlighted fields.">
|
|
21
|
+
<label class="field">
|
|
22
|
+
<span class="field-label">Email</span>
|
|
23
|
+
<input class="input" type="email" name="email" required
|
|
24
|
+
aria-describedby="sb-email-error" />
|
|
25
|
+
<span class="field-error" id="sb-email-error" role="alert">Enter a valid email.</span>
|
|
26
|
+
</label>
|
|
27
|
+
<div class="form-actions">
|
|
28
|
+
<button class="btn primary" type="submit">Submit</button>
|
|
29
|
+
</div>
|
|
30
|
+
</form>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Submitting the empty form blocks submission and shows `data-validation-message`
|
|
34
|
+
in the status bar below — no JavaScript required beyond the runtime.
|
|
35
|
+
|
|
36
|
+
```html demo
|
|
37
|
+
<div class="cluster">
|
|
38
|
+
<button class="btn" type="button" commandfor="sb-status" command="--status"
|
|
39
|
+
aria-controls="sb-status"
|
|
40
|
+
data-status-message="Saved." data-status-intent="success">Show success</button>
|
|
41
|
+
<button class="btn" type="button" commandfor="sb-status" command="--status"
|
|
42
|
+
aria-controls="sb-status"
|
|
43
|
+
data-status-message="Could not save." data-status-intent="danger"
|
|
44
|
+
data-status-duration="6000">Show danger</button>
|
|
45
|
+
<button class="btn outline" type="button" commandfor="sb-status" command="--status-clear"
|
|
46
|
+
aria-controls="sb-status">Clear</button>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div class="status-bar" data-status id="sb-status" role="status" aria-live="polite" aria-atomic="true"></div>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
No script required beyond the runtime: `command="--status"` reads its message
|
|
53
|
+
from `data-status-message` (plus optional `data-status-intent` /
|
|
54
|
+
`data-status-duration`), `command="--status-clear"` empties the bar.
|
|
55
|
+
`commandfor` must match the status bar's own `id`.
|
|
56
|
+
|
|
57
|
+
For dynamic messages — a fetch response, a computed value — dispatch the same
|
|
58
|
+
event the commands use under the hood:
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
document.dispatchEvent(new CustomEvent("actual:status", {
|
|
62
|
+
bubbles: true,
|
|
63
|
+
detail: { message: "Saved.", intent: "success" },
|
|
64
|
+
}));
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## CSS hooks
|
|
68
|
+
|
|
69
|
+
- `--status-bg` — bar background.
|
|
70
|
+
- `--status-fg` — bar text color.
|
|
71
|
+
|
|
72
|
+
Prefer an intent class over setting these directly.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Tabs
|
|
2
|
+
|
|
3
|
+
> In-place panel switcher using real tab semantics, with roving tabindex and arrow-key navigation.
|
|
4
|
+
|
|
5
|
+
## Class reference
|
|
6
|
+
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `.tabs` | Component | Tab strip; pairs with `role="tablist"`. |
|
|
10
|
+
| `.tab` | Component | One tab trigger; pairs with `role="tab"`. |
|
|
11
|
+
| `.primary` | Intent | Tints the selected tab's indicator and text. |
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
- Use real tab semantics when panels switch in place.
|
|
16
|
+
- Use normal links and `aria-current="page"` for page navigation that only looks like tabs.
|
|
17
|
+
- JavaScript owns roving `tabindex`, `aria-selected`, `hidden`, and keyboard behavior.
|
|
18
|
+
- Left/Right select tabs and wrap at the ends. Home/End jump to first/last. Down moves focus into the selected panel.
|
|
19
|
+
- A tab list needs both `.tabs` and `role="tablist"`; `.tab` styles each trigger.
|
|
20
|
+
- A `.tab` with an icon uses `--tab-gap` (default `0.375em`) for the space between icon and label.
|
|
21
|
+
|
|
22
|
+
```html demo
|
|
23
|
+
<div class="tabset">
|
|
24
|
+
<div class="tabs" data-enhance="tabs" role="tablist" aria-label="Settings">
|
|
25
|
+
<button class="tab primary"
|
|
26
|
+
type="button"
|
|
27
|
+
role="tab"
|
|
28
|
+
aria-selected="true"
|
|
29
|
+
aria-controls="panel-general"
|
|
30
|
+
id="tab-general">
|
|
31
|
+
General
|
|
32
|
+
</button>
|
|
33
|
+
<button class="tab"
|
|
34
|
+
type="button"
|
|
35
|
+
role="tab"
|
|
36
|
+
aria-selected="false"
|
|
37
|
+
aria-controls="panel-security"
|
|
38
|
+
id="tab-security"
|
|
39
|
+
tabindex="-1">
|
|
40
|
+
Security
|
|
41
|
+
</button>
|
|
42
|
+
<button class="tab"
|
|
43
|
+
type="button"
|
|
44
|
+
role="tab"
|
|
45
|
+
aria-selected="false"
|
|
46
|
+
aria-controls="panel-billing"
|
|
47
|
+
id="tab-billing"
|
|
48
|
+
tabindex="-1">
|
|
49
|
+
Billing
|
|
50
|
+
</button>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<section role="tabpanel" id="panel-general" aria-labelledby="tab-general" tabindex="-1" class="py">
|
|
54
|
+
General content
|
|
55
|
+
</section>
|
|
56
|
+
<section role="tabpanel" id="panel-security" aria-labelledby="tab-security" tabindex="-1" hidden class="py">
|
|
57
|
+
Security content
|
|
58
|
+
</section>
|
|
59
|
+
<section role="tabpanel" id="panel-billing" aria-labelledby="tab-billing" tabindex="-1" hidden class="py">
|
|
60
|
+
Billing content
|
|
61
|
+
</section>
|
|
62
|
+
</div>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
For navigation that only looks like tabs, keep it a plain link list — no
|
|
66
|
+
JavaScript involved:
|
|
67
|
+
|
|
68
|
+
```html demo
|
|
69
|
+
<nav aria-label="Account sections">
|
|
70
|
+
<ul class="tabs">
|
|
71
|
+
<li><a class="tab primary" href="#account" aria-current="page">Profile</a></li>
|
|
72
|
+
<li><a class="tab" href="#security">Security</a></li>
|
|
73
|
+
<li><a class="tab" href="#billing">Billing</a></li>
|
|
74
|
+
</ul>
|
|
75
|
+
</nav>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## CSS hooks
|
|
79
|
+
|
|
80
|
+
- `--tab-gap` — space between an icon and the label text (default `0.375em`).
|