zaniah 0.2.0 → 0.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/LICENSE.txt +18 -0
- data/README.md +14 -4
- data/assets/icons/check.svg +1 -0
- data/assets/icons/close.svg +1 -0
- data/assets/icons/info.svg +1 -0
- data/assets/icons/menu.svg +1 -0
- data/assets/icons/search.svg +1 -0
- data/assets/icons/warning.svg +1 -0
- data/docs/accessibility.md +61 -0
- data/docs/adr/004-style-resolution.md +17 -0
- data/docs/adr/005-instance-layout.md +43 -0
- data/docs/adr/006-component-model.md +17 -0
- data/docs/adr/007-text-buffer.md +17 -0
- data/docs/adr/008-accessibility-bridge.md +19 -0
- data/docs/adr/009-grid-scope.md +17 -0
- data/docs/adr/010-text-overlay-layout.md +24 -0
- data/docs/animation.md +46 -0
- data/docs/components.md +109 -0
- data/docs/gallery/command-palette-dark.png +0 -0
- data/docs/gallery/command-palette-high_contrast.png +0 -0
- data/docs/gallery/command-palette-light.png +0 -0
- data/docs/gallery/components-dark.png +0 -0
- data/docs/gallery/components-high_contrast.png +0 -0
- data/docs/gallery/components-light.png +0 -0
- data/docs/gallery/context-menu-dark.png +0 -0
- data/docs/gallery/context-menu-high_contrast.png +0 -0
- data/docs/gallery/context-menu-light.png +0 -0
- data/docs/gallery/dialog-dark.png +0 -0
- data/docs/gallery/dialog-high_contrast.png +0 -0
- data/docs/gallery/dialog-light.png +0 -0
- data/docs/gallery/drawer-left-dark.png +0 -0
- data/docs/gallery/drawer-left-high_contrast.png +0 -0
- data/docs/gallery/drawer-left-light.png +0 -0
- data/docs/gallery/drawer-right-dark.png +0 -0
- data/docs/gallery/drawer-right-high_contrast.png +0 -0
- data/docs/gallery/drawer-right-light.png +0 -0
- data/docs/gallery/menu-dark.png +0 -0
- data/docs/gallery/menu-high_contrast.png +0 -0
- data/docs/gallery/menu-light.png +0 -0
- data/docs/gallery/modal-dark.png +0 -0
- data/docs/gallery/modal-high_contrast.png +0 -0
- data/docs/gallery/modal-light.png +0 -0
- data/docs/gallery/popover-bottom-dark.png +0 -0
- data/docs/gallery/popover-bottom-high_contrast.png +0 -0
- data/docs/gallery/popover-bottom-light.png +0 -0
- data/docs/gallery/popover-left-dark.png +0 -0
- data/docs/gallery/popover-left-high_contrast.png +0 -0
- data/docs/gallery/popover-left-light.png +0 -0
- data/docs/gallery/popover-right-dark.png +0 -0
- data/docs/gallery/popover-right-high_contrast.png +0 -0
- data/docs/gallery/popover-right-light.png +0 -0
- data/docs/gallery/popover-top-dark.png +0 -0
- data/docs/gallery/popover-top-high_contrast.png +0 -0
- data/docs/gallery/popover-top-light.png +0 -0
- data/docs/gallery/toast-danger-dark.png +0 -0
- data/docs/gallery/toast-danger-high_contrast.png +0 -0
- data/docs/gallery/toast-danger-light.png +0 -0
- data/docs/gallery/toast-info-dark.png +0 -0
- data/docs/gallery/toast-info-high_contrast.png +0 -0
- data/docs/gallery/toast-info-light.png +0 -0
- data/docs/gallery/toast-success-dark.png +0 -0
- data/docs/gallery/toast-success-high_contrast.png +0 -0
- data/docs/gallery/toast-success-light.png +0 -0
- data/docs/gallery/toast-warning-dark.png +0 -0
- data/docs/gallery/toast-warning-high_contrast.png +0 -0
- data/docs/gallery/toast-warning-light.png +0 -0
- data/docs/gallery/tooltip-bottom-dark.png +0 -0
- data/docs/gallery/tooltip-bottom-high_contrast.png +0 -0
- data/docs/gallery/tooltip-bottom-light.png +0 -0
- data/docs/gallery/tooltip-left-dark.png +0 -0
- data/docs/gallery/tooltip-left-high_contrast.png +0 -0
- data/docs/gallery/tooltip-left-light.png +0 -0
- data/docs/gallery/tooltip-right-dark.png +0 -0
- data/docs/gallery/tooltip-right-high_contrast.png +0 -0
- data/docs/gallery/tooltip-right-light.png +0 -0
- data/docs/gallery/tooltip-top-dark.png +0 -0
- data/docs/gallery/tooltip-top-high_contrast.png +0 -0
- data/docs/gallery/tooltip-top-light.png +0 -0
- data/docs/index.html +74 -0
- data/docs/layout.md +31 -0
- data/docs/native.md +7 -2
- data/docs/site.css +32 -0
- data/docs/text.md +54 -0
- data/docs/theme.md +50 -0
- data/docs/tui.md +36 -0
- data/examples/gallery.rb +155 -0
- data/examples/native_ime.rb +13 -6
- data/lib/zaniah/accessibility/linux/service.rb +361 -0
- data/lib/zaniah/accessibility/linux.rb +23 -0
- data/lib/zaniah/accessibility/mac.rb +136 -0
- data/lib/zaniah/accessibility/native_tree.rb +53 -0
- data/lib/zaniah/accessibility/node.rb +12 -0
- data/lib/zaniah/accessibility/tree.rb +61 -0
- data/lib/zaniah/accessibility/windows/provider.rb +273 -0
- data/lib/zaniah/accessibility/windows.rb +38 -0
- data/lib/zaniah/accessibility.rb +63 -0
- data/lib/zaniah/animation/animator.rb +95 -0
- data/lib/zaniah/animation/easing.rb +45 -0
- data/lib/zaniah/animation/spring.rb +36 -0
- data/lib/zaniah/animation/transition.rb +5 -0
- data/lib/zaniah/animation.rb +6 -0
- data/lib/zaniah/app.rb +22 -2
- data/lib/zaniah/color.rb +16 -0
- data/lib/zaniah/devtools/hot_reload.rb +40 -0
- data/lib/zaniah/devtools/inspector.rb +111 -0
- data/lib/zaniah/devtools/stats_overlay.rb +16 -0
- data/lib/zaniah/devtools.rb +13 -0
- data/lib/zaniah/element.rb +210 -15
- data/lib/zaniah/frame_context.rb +4 -1
- data/lib/zaniah/gpu/frame_encoder.rb +10 -1
- data/lib/zaniah/gpu/instance_packing.rb +33 -5
- data/lib/zaniah/gpu/metal.rb +26 -10
- data/lib/zaniah/gpu/open_gl.rb +35 -14
- data/lib/zaniah/gpu/software.rb +116 -14
- data/lib/zaniah/gpu/vulkan/scene.frag +51 -0
- data/lib/zaniah/gpu/vulkan/scene.frag.spv +0 -0
- data/lib/zaniah/gpu/vulkan/scene.vert +50 -0
- data/lib/zaniah/gpu/vulkan/scene.vert.spv +0 -0
- data/lib/zaniah/gpu/vulkan.rb +282 -36
- data/lib/zaniah/gpu.rb +8 -3
- data/lib/zaniah/input/dispatcher.rb +96 -12
- data/lib/zaniah/input/focus_handle.rb +13 -4
- data/lib/zaniah/input/focus_tree.rb +77 -0
- data/lib/zaniah/input/keymap.rb +77 -0
- data/lib/zaniah/input.rb +1 -0
- data/lib/zaniah/interactivity.rb +30 -0
- data/lib/zaniah/layout/engine.rb +178 -36
- data/lib/zaniah/layout/grid.rb +134 -0
- data/lib/zaniah/layout/style.rb +16 -1
- data/lib/zaniah/layout.rb +1 -0
- data/lib/zaniah/length.rb +3 -0
- data/lib/zaniah/length_units.rb +7 -0
- data/lib/zaniah/list.rb +27 -15
- data/lib/zaniah/platform/appearance.rb +11 -0
- data/lib/zaniah/platform/headless/window.rb +101 -9
- data/lib/zaniah/platform/linux/appearance_aware.rb +8 -0
- data/lib/zaniah/platform/linux/wayland_window.rb +3 -1
- data/lib/zaniah/platform/linux/window.rb +4 -2
- data/lib/zaniah/platform/mac/app.rb +1 -1
- data/lib/zaniah/platform/mac/core_text.rb +3 -0
- data/lib/zaniah/platform/mac/window.rb +9 -1
- data/lib/zaniah/platform/tui/window.rb +1 -1
- data/lib/zaniah/platform/windows/window.rb +12 -2
- data/lib/zaniah/platform.rb +1 -0
- data/lib/zaniah/scene.rb +137 -28
- data/lib/zaniah/scroll_state.rb +117 -0
- data/lib/zaniah/scroll_view.rb +94 -0
- data/lib/zaniah/style/gradient.rb +28 -0
- data/lib/zaniah/style/ring.rb +13 -0
- data/lib/zaniah/style/shadow.rb +13 -0
- data/lib/zaniah/style/style_set.rb +43 -0
- data/lib/zaniah/style/transform.rb +40 -0
- data/lib/zaniah/svg.rb +19 -0
- data/lib/zaniah/text.rb +499 -7
- data/lib/zaniah/text_buffer.rb +119 -0
- data/lib/zaniah/text_selection.rb +18 -0
- data/lib/zaniah/text_system/atlas_cache.rb +1 -1
- data/lib/zaniah/text_system/fallback.rb +24 -0
- data/lib/zaniah/text_system/font_db.rb +4 -1
- data/lib/zaniah/text_system/kinsoku.rb +28 -0
- data/lib/zaniah/text_system/line_breaker.rb +58 -0
- data/lib/zaniah/text_system/paragraph.rb +246 -0
- data/lib/zaniah/text_system/renderer.rb +13 -2
- data/lib/zaniah/text_system/typesetter.rb +4 -0
- data/lib/zaniah/text_system.rb +3 -0
- data/lib/zaniah/theme.rb +39 -0
- data/lib/zaniah/ui/charts.rb +165 -0
- data/lib/zaniah/ui/choice_fields.rb +134 -0
- data/lib/zaniah/ui/component.rb +73 -0
- data/lib/zaniah/ui/controls.rb +439 -0
- data/lib/zaniah/ui/data.rb +364 -0
- data/lib/zaniah/ui/editors.rb +67 -0
- data/lib/zaniah/ui/forms.rb +131 -0
- data/lib/zaniah/ui/layout_components.rb +205 -0
- data/lib/zaniah/ui/modal.rb +129 -0
- data/lib/zaniah/ui/overlays.rb +282 -0
- data/lib/zaniah/ui/pickers.rb +169 -0
- data/lib/zaniah/ui/primitives.rb +199 -0
- data/lib/zaniah/ui/scrollbar.rb +104 -0
- data/lib/zaniah/ui/structure.rb +224 -0
- data/lib/zaniah/ui/text_inputs.rb +169 -0
- data/lib/zaniah/ui/variants.rb +23 -0
- data/lib/zaniah/ui.rb +18 -0
- data/lib/zaniah/unicode.rb +42 -0
- data/lib/zaniah/uniform_list.rb +27 -6
- data/lib/zaniah/version.rb +1 -1
- data/lib/zaniah.rb +14 -0
- data/sig/accessibility.rbs +34 -0
- data/sig/animation.rbs +54 -0
- data/sig/app.rbs +2 -1
- data/sig/devtools.rbs +37 -0
- data/sig/elements.rbs +108 -6
- data/sig/gpu.rbs +9 -2
- data/sig/input.rbs +31 -5
- data/sig/layout.rbs +2 -1
- data/sig/platform.rbs +24 -4
- data/sig/scene.rbs +15 -2
- data/sig/style.rbs +82 -0
- data/sig/text.rbs +86 -0
- data/sig/theme.rbs +64 -0
- data/sig/ui.rbs +390 -0
- data/sig/zaniah.rbs +56 -3
- data/tools/generate_component_gallery.rb +48 -0
- metadata +151 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f6787d1edc51a6a692859fe62834270cfa2339ade8b00e596e8861632eb59913
|
|
4
|
+
data.tar.gz: 7407abf9f7a64c80fc307843ffeadd9d130cfb45a12673a85f6cbedf2710a3e4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35cdfc811f06f704d21202e60029c2869eb5b01698c4e52cde3ce2b7c0e45eaa0c6c5a60ec46e9e9f4e15fd2e1b7f88a75b71b9ec829423540259238739cf468
|
|
7
|
+
data.tar.gz: beaae799ef7227cf30d354819b4d896ee1957666c1617d4a43a15fd8d0112180b0dcf74dadf930c6df8376eaa0045663c83400cca2f6bf019142ab9cb2af0592
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.4.0 — 2026-09-15
|
|
6
|
+
|
|
7
|
+
- Add inline and block text overlays with wrapping-aware layout, hit testing, and row-local relayout.
|
|
8
|
+
|
|
9
|
+
## 0.3.0 — 2026-09-14
|
|
10
|
+
|
|
11
|
+
- Improve large flex layouts, GPU scene submission, and software-rendered gradients for smoother frames.
|
|
12
|
+
- Add dark, light, and high-contrast themes with immediate hover, active, focus, and disabled styling.
|
|
13
|
+
- Add Grid, ScrollView/ScrollState, sticky and logical layout, spatial focus navigation, and platform cursors.
|
|
14
|
+
- Add gradients, transforms, paths, layered effects, and matching Software, OpenGL, Metal, and Vulkan scene rendering.
|
|
15
|
+
- Add paragraph layout, Japanese kinsoku, font fallback, selection, Unicode-safe editing, and native IME composition.
|
|
16
|
+
- Add the opt-in `zaniah/ui` component library with keyboard and TUI support.
|
|
17
|
+
- Add clock-driven animation, keyed transitions, inertial scrolling, and reduced-motion support.
|
|
18
|
+
- Add virtual data views, charts, validated forms, native screen-reader support on macOS, Windows, and Linux, DevTools, and a three-theme component gallery.
|
|
19
|
+
|
|
3
20
|
## 0.2.0 — 2026-09-11
|
|
4
21
|
|
|
5
22
|
- Add read-only element, hit-region, popup, and frame inspection APIs.
|
data/LICENSE.txt
CHANGED
|
@@ -19,3 +19,21 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
21
|
THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
Bundled icons in assets/icons are derived from Lucide (https://lucide.dev):
|
|
24
|
+
|
|
25
|
+
ISC License
|
|
26
|
+
|
|
27
|
+
Copyright (c) 2020, Lucide Contributors
|
|
28
|
+
|
|
29
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
30
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
31
|
+
copyright notice and this permission notice appear in all copies.
|
|
32
|
+
|
|
33
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
34
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
35
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
36
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
37
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
38
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
39
|
+
PERFORMANCE OF THIS SOFTWARE.
|
data/README.md
CHANGED
|
@@ -33,11 +33,15 @@ the drawing surface beneath the editor.
|
|
|
33
33
|
|
|
34
34
|
## Features
|
|
35
35
|
|
|
36
|
-
- Flex,
|
|
37
|
-
-
|
|
36
|
+
- Flex, Grid, sticky, absolute, wrapping, and baseline-aware layouts
|
|
37
|
+
- Gradients, transforms, paths, SVG, shadows, clipping, and GPU glyph atlases
|
|
38
38
|
- Retained element state, subscriptions, and non-blocking background tasks
|
|
39
|
-
-
|
|
40
|
-
- OpenType
|
|
39
|
+
- Scroll views, inertial input, and uniform or variable-height virtual lists
|
|
40
|
+
- OpenType shaping, font fallback, Japanese wrapping, text overlays, selection, editing, and IME
|
|
41
|
+
- Themes, state styles, keyed animation, springs, and reduced-motion support
|
|
42
|
+
- Opt-in controls, overlays, tables, trees, charts, forms, and terminal fallbacks
|
|
43
|
+
- Spatial keyboard focus and a diffed cross-platform accessibility tree
|
|
44
|
+
- F12 inspector, frame statistics, hot reload, and headless golden-image tests
|
|
41
45
|
- Native input, IME, clipboard, file-drop, display, and filesystem events
|
|
42
46
|
- RBS declarations for the public API
|
|
43
47
|
|
|
@@ -110,6 +114,12 @@ Native backends use the operating system libraries through Ruby's Fiddle. See
|
|
|
110
114
|
- [Native backends](docs/native.md) — windows, displays, file watching, and terminals
|
|
111
115
|
- [Text system](docs/text.md) — font discovery, shaping, rasterization, and caching
|
|
112
116
|
- [SVG and lists](docs/vector_and_list.md) — static vector icons and virtual lists
|
|
117
|
+
- [Layout and scrolling](docs/layout.md) — Grid, ScrollView, sticky positioning, and RTL foundations
|
|
118
|
+
- [Themes](docs/theme.md) — semantic tokens and state styles
|
|
119
|
+
- [Components](docs/components.md) — controls, overlays, data views, charts, and forms
|
|
120
|
+
- [Animation](docs/animation.md) — easing, springs, transitions, and reduced motion
|
|
121
|
+
- [Accessibility](docs/accessibility.md) — semantic trees, diffs, and native bridges
|
|
122
|
+
- [Terminal UI](docs/tui.md) — deterministic component degradation
|
|
113
123
|
- [CPU process workers](docs/process_pool.md) — portable background CPU work
|
|
114
124
|
- [Architecture decisions](docs/adr) — design records and rationale
|
|
115
125
|
- [RBS declarations](sig) — public API signatures
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 6h16M4 12h16M4 18h16"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.7 18 13.7 4a2 2 0 0 0-3.4 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3Z"/><path d="M12 9v4M12 17h.01"/></svg>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Accessibility
|
|
2
|
+
|
|
3
|
+
Every window maintains a backend-neutral `Accessibility::Tree` beside its render
|
|
4
|
+
tree. Components expose role, label, value, bounds, states, children, and actions
|
|
5
|
+
through `Accessibility::Node`. The window publishes a notification only when the
|
|
6
|
+
semantic tree changes.
|
|
7
|
+
|
|
8
|
+
```ruby
|
|
9
|
+
window.accessibility_tree.each do |node, path|
|
|
10
|
+
puts [path, node.role, node.label].inspect
|
|
11
|
+
end
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`window.accessibility_revision` increments after each semantic change, and
|
|
15
|
+
`window.accessibility_tree.changes` contains `added`, `removed`, or `updated`
|
|
16
|
+
records. This makes accessibility assertions deterministic on the headless
|
|
17
|
+
backend without mocking an operating system API.
|
|
18
|
+
|
|
19
|
+
## Component semantics
|
|
20
|
+
|
|
21
|
+
Interactive components publish their current state and supported actions. For
|
|
22
|
+
example, checkboxes expose `checked`, mixed checkboxes expose `mixed`, disabled
|
|
23
|
+
controls omit mutating actions, modal dialogs expose `modal`, and live Toast
|
|
24
|
+
messages use the `status` role. `FormField` marks invalid controls and associates
|
|
25
|
+
the error node through its `describedby` state.
|
|
26
|
+
|
|
27
|
+
Custom components implement the same method:
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
def accessibility_node(_cx)
|
|
31
|
+
Zaniah::Accessibility.node(
|
|
32
|
+
role: :button,
|
|
33
|
+
label: "Refresh",
|
|
34
|
+
states: {busy: @loading},
|
|
35
|
+
actions: @loading ? [] : [:press]
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Decorative content should return `nil`. Container elements without an explicit
|
|
41
|
+
node retain semantic descendants in a generated `group` node.
|
|
42
|
+
|
|
43
|
+
## Native bridges
|
|
44
|
+
|
|
45
|
+
- macOS publishes an `NSAccessibilityElement` hierarchy with roles, labels,
|
|
46
|
+
values, state, bounds, and children, then posts `AXLayoutChanged`.
|
|
47
|
+
- Windows answers `WM_GETOBJECT` with `IRawElementProviderSimple`, fragment,
|
|
48
|
+
fragment-root, and Invoke providers. UI Automation clients can navigate and
|
|
49
|
+
query the semantic hierarchy rather than relying on refresh events alone.
|
|
50
|
+
- Linux registers `Accessible`, `Component`, `Action`, and `Application`
|
|
51
|
+
objects on the AT-SPI D-Bus, embeds the application root in the registry,
|
|
52
|
+
and emits object-change events. Actions route back through the normal input
|
|
53
|
+
dispatcher on every platform.
|
|
54
|
+
|
|
55
|
+
The Linux provider is exercised in CI inside a private D-Bus session. Native
|
|
56
|
+
macOS and Windows objects retain the same `Accessibility::NativeTree` path and
|
|
57
|
+
bounds model used by the headless assertions.
|
|
58
|
+
|
|
59
|
+
The semantic tree remains the authoritative source on every backend. See
|
|
60
|
+
[ADR-008](adr/008-accessibility-bridge.md) for the boundary between components
|
|
61
|
+
and native adapters.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ADR 004: Resolve interaction styles in elements before paint
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-09-12
|
|
5
|
+
- Decision deadline: before M1 implementation
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
State-specific styles need stable layout inputs and same-frame hover feedback. Resolution could live in elements, the frame context, or a separate style object.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
Store variants in `StyleSet`, resolve flags from interaction state during prepaint, and let each element use the resolved style during paint. Keep `FrameContext` as a service carrier rather than a style owner.
|
|
14
|
+
|
|
15
|
+
## Consequences
|
|
16
|
+
|
|
17
|
+
Existing element builders remain compatible and paint stays deterministic. Elements must register hits when they only have state-specific styles.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# ADR 005: Extend the shared GPU instance layout once
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-09-12
|
|
5
|
+
- Decision deadline: before M3 implementation
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Metal, OpenGL, Vulkan, and Software consume the same 24-float instance payload. Gradients and transforms need more fields; changing the stride independently for each feature repeats risky backend work.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
Use this 40-float layout. Quad data uses every field; sprites reuse the edge
|
|
14
|
+
fields for source UVs. Triangle vertices reuse rect and radii fields.
|
|
15
|
+
|
|
16
|
+
| Floats | Quad | Sprite |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| 0–3 | bounds | bounds |
|
|
19
|
+
| 4–7 | primary color | tint |
|
|
20
|
+
| 8–11 | secondary gradient color | unused |
|
|
21
|
+
| 12–15 | corner radii | unused |
|
|
22
|
+
| 16–19 | border color | unused |
|
|
23
|
+
| 20–23 | edge border widths | source UV |
|
|
24
|
+
| 24–27 | gradient kind, stop positions, angle | unused |
|
|
25
|
+
| 28–31 | gradient center, radius, primitive kind | primitive kind |
|
|
26
|
+
| 32–37 | affine transform (`a,b,c,d,tx,ty`) | affine transform |
|
|
27
|
+
| 38–39 | reserved shadow spread / inset or border flags | unused |
|
|
28
|
+
|
|
29
|
+
Opacity is multiplied into both fill and border alpha before packing. Linear
|
|
30
|
+
and radial gradients use exactly two stops; a future multi-stop implementation
|
|
31
|
+
may use a 1D texture without another stride change. Shadows are expanded into
|
|
32
|
+
ordinary quad instances, so the reserved shadow fields remain available.
|
|
33
|
+
|
|
34
|
+
Metal, OpenGL, and Vulkan consume the layout directly, Software consumes the
|
|
35
|
+
equivalent 40-float quad layout, and cached text sprite batches use the same
|
|
36
|
+
stride. Vulkan's bundled SPIR-V shaders render `Scene` quads, sprites, and path
|
|
37
|
+
triangles offscreen; its user-supplied SPIR-V triangle probe remains available.
|
|
38
|
+
|
|
39
|
+
## Consequences
|
|
40
|
+
|
|
41
|
+
The coordinated change avoids multiple format migrations. Shader compilation,
|
|
42
|
+
Software golden tests, instance packing tests, and platform-native capture tests
|
|
43
|
+
are release gates on their available hosts.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ADR 006: Components participate by duck typing
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-09-12
|
|
5
|
+
- Decision deadline: before M6 implementation
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Components can inherit `Element` or wrap an element tree while implementing the existing render protocol. Inheritance exposes low-level mutable state that components do not need.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
Components implement `request_layout`, `layout_node`, `prepaint`, and `paint`, delegating those calls to a built root element.
|
|
14
|
+
|
|
15
|
+
## Consequences
|
|
16
|
+
|
|
17
|
+
The UI layer stays optional and thin. Protocol changes must be reflected in both elements and components.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ADR 007: Start with a String-backed text buffer
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-09-12
|
|
5
|
+
- Decision deadline: before M5 implementation
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Text editing needs Unicode-safe changes and undo. A piece table scales better for very large documents, while a Ruby `String` is substantially simpler for the intended settings and editor examples.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
Use a mutable UTF-8 `String` with byte offsets and grapheme-aware navigation. Revisit a piece table only after representative documents show a measurable problem.
|
|
14
|
+
|
|
15
|
+
## Consequences
|
|
16
|
+
|
|
17
|
+
The first implementation is small and easy to verify. Large edits are linear in buffer size.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# ADR 008: Separate the accessibility tree from OS bridges
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-09-12
|
|
5
|
+
- Decision deadline: before M8 implementation
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
NSAccessibility, UI Automation, and AT-SPI expose different native contracts, but components need one testable semantic model.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
Build a backend-neutral accessibility tree first. Add Fiddle-based adapters for macOS, Windows, and Linux that publish tree differences without changing component APIs.
|
|
14
|
+
|
|
15
|
+
## Consequences
|
|
16
|
+
|
|
17
|
+
Semantics and diffs are tested headlessly. Native adapters publish layout-change
|
|
18
|
+
query providers and notifications through NSAccessibility, Windows UI Automation,
|
|
19
|
+
and AT-SPI's D-Bus interfaces while retaining the same backend-neutral tree.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ADR 009: Implement a bounded grid layout subset
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-09-12
|
|
5
|
+
- Decision deadline: before M2 implementation
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Full CSS Grid is too large for the toolkit's first grid implementation. Applications primarily need explicit tracks, spans, gaps, fractional space, and predictable automatic placement.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
Support explicit rows and columns, row-first auto placement, integer and range placement, `fr`, `minmax`, `auto`, and gaps. Defer named areas and `auto-fit`/`auto-fill`.
|
|
14
|
+
|
|
15
|
+
## Consequences
|
|
16
|
+
|
|
17
|
+
Common application layouts are covered with a tractable engine. Deferred CSS features require an explicit later extension.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# ADR 010: Model text overlays as layout gaps
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-09-15
|
|
5
|
+
- Decision deadline: before text overlay implementation
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Inline hints and block annotations must affect wrapping and pointer mapping without
|
|
10
|
+
becoming editable text. Absolutely painting them over an ordinary paragraph would
|
|
11
|
+
leave wrapping, carets, and selection unaware of their size.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
Represent inline overlays as measured gaps at UTF-8 grapheme boundaries and block
|
|
16
|
+
overlays as measured rows around logical source lines. Cache the wrapped paragraph
|
|
17
|
+
for each explicit source line so changing one inline overlay only reshapes that row.
|
|
18
|
+
Keep overlay elements as ordinary positioned children for painting and input.
|
|
19
|
+
|
|
20
|
+
## Consequences
|
|
21
|
+
|
|
22
|
+
Text offsets remain unchanged, overlay children stay clickable, and coordinate
|
|
23
|
+
conversion accounts for every gap. Layout changes after an overlay row still shift
|
|
24
|
+
later vertical positions, but those rows reuse their shaped and wrapped paragraphs.
|
data/docs/animation.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Animation
|
|
2
|
+
|
|
3
|
+
Zaniah uses one clock-driven `Animator` per window. Rendering stays idle when no
|
|
4
|
+
animation is active, and injected clocks keep headless tests deterministic.
|
|
5
|
+
|
|
6
|
+
```ruby
|
|
7
|
+
window.animator.animate(:progress, from: 0, to: 1,
|
|
8
|
+
duration: 0.18, easing: :ease_out)
|
|
9
|
+
window.animator.value(:progress)
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Available easing values are `linear`, `ease_in`, `ease_out`, and `ease_in_out`.
|
|
13
|
+
`Zaniah::Easing.cubic_bezier(x1, y1, x2, y2)` and
|
|
14
|
+
`window.animator.spring(key, to:, stiffness:, damping:, mass:)` cover custom
|
|
15
|
+
curves and spring motion. Numeric values, `Color`, same-unit `Length`, and
|
|
16
|
+
`Transform` values can be interpolated.
|
|
17
|
+
|
|
18
|
+
## Style transitions
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
Div.new.key(:save).bg(theme.colors.surface)
|
|
22
|
+
.hover(background: theme.colors.surface_hover)
|
|
23
|
+
.transition(:background, duration: theme.motion.duration_base)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Transitions require `key`; without one the new style is applied immediately.
|
|
27
|
+
Keyed children of a stable `Div` or `List` automatically animate additions,
|
|
28
|
+
removals, and position changes. Removed children remain paintable in the
|
|
29
|
+
window's existing element-state store until their exit animation completes.
|
|
30
|
+
|
|
31
|
+
`ScrollView`, `List`, and `UniformList` use the same animator for inertial
|
|
32
|
+
scrolling. Pass `inertia: false` to a standalone `ScrollState` to disable it.
|
|
33
|
+
Overlay scrollbars fade after activity; modal overlays and collapsible content
|
|
34
|
+
animate visibility. Editable text carets, skeletons, and spinners also use the
|
|
35
|
+
window clock.
|
|
36
|
+
|
|
37
|
+
## Reduced motion
|
|
38
|
+
|
|
39
|
+
The macOS, Windows, and Linux backends read the operating-system reduced-motion
|
|
40
|
+
setting. When `theme.motion.reduced?` is true, the animator completes every
|
|
41
|
+
animation immediately. Tests or applications can opt in explicitly:
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
theme = Theme.dark
|
|
45
|
+
app.global(:theme, theme.with(motion: theme.motion.with(reduced: true)))
|
|
46
|
+
```
|
data/docs/components.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Components
|
|
2
|
+
|
|
3
|
+
The optional component layer is loaded with `require "zaniah/ui"`. Components use the
|
|
4
|
+
same `request_layout` / `prepaint` / `paint` protocol as elements and may be placed
|
|
5
|
+
directly in an element tree. Builder methods return the component.
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
require "zaniah/ui"
|
|
9
|
+
|
|
10
|
+
save = Zaniah::UI::Button.new("Save", variant: :primary, size: :md)
|
|
11
|
+
.icon(:check)
|
|
12
|
+
.on_click { |_event, cx| cx.window.request_frame }
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Applications may extend variant tables:
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
Zaniah::UI::Button.variants[:variant][:brand] = ->(theme) {
|
|
19
|
+
{background: theme.colors.success, hover: theme.colors.success,
|
|
20
|
+
foreground: theme.colors.text_inverse, border: theme.colors.success}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Component reference
|
|
25
|
+
|
|
26
|
+
| Layer | Component | Main constructor/options | Variants | Accessibility role |
|
|
27
|
+
| --- | --- | --- | --- | --- |
|
|
28
|
+
| L0 | `Label` | `(text, tone:, size:, wrap:)` | tone: default/muted/inverse; size: xs–xl | text |
|
|
29
|
+
| L0 | `Icon` | `(source, size:, color:, label:)` | bundled: check/close/search/menu/info/warning | image when labeled |
|
|
30
|
+
| L0 | `Divider` | `(axis:)` | horizontal/vertical | separator |
|
|
31
|
+
| L0 | `Spacer` | `(size = nil)` | fixed or flexible | none |
|
|
32
|
+
| L0 | `Card` | `(*children)`, `child` | theme surface | group |
|
|
33
|
+
| L0 | `Badge` | `(text, variant:)` | neutral/accent/success/warning/danger | text |
|
|
34
|
+
| L0 | `Avatar` | `(name, image:, size:)` | initials or PNG | image |
|
|
35
|
+
| L0 | `Skeleton` | `(width:, height:)` | pulsing loading placeholder | progressbar/busy |
|
|
36
|
+
| L0 | `EmptyState` | `(title, message:, icon:, action:)` | compositional | group |
|
|
37
|
+
| L1 | `Button` | `(label, size:, variant:)`; `disabled`, `loading`, `icon`, `on_click` | sm/md/lg × primary/secondary/ghost/danger | button |
|
|
38
|
+
| L1 | `IconButton` | `(icon, label:, ...)` | Button variants | button |
|
|
39
|
+
| L1 | `ToggleButton` | `(label, value:)`; `on_change` | Button variants | button/pressed |
|
|
40
|
+
| L1 | `ButtonGroup` | `(*buttons)`, `child` | horizontal | group |
|
|
41
|
+
| L1 | `Checkbox` | `(label, value:, disabled:)`; `on_change` | true/false/mixed | checkbox |
|
|
42
|
+
| L1 | `Radio` | `(label, value:, disabled:)`; `on_change` | selected/unselected | radio |
|
|
43
|
+
| L1 | `RadioGroup` | `(options, value:)`; `on_change` | one selected value | radiogroup |
|
|
44
|
+
| L1 | `Switch` | `(label, value:, disabled:)`; `on_change` | on/off | switch |
|
|
45
|
+
| L1 | `Slider` | `(value:, min:, max:, step:, label:)`; `on_change` | pointer + arrow/Home/End/Page keys | slider |
|
|
46
|
+
| L1 | `RangeSlider` | `(value: [low, high], ...)` | two thumbs | slider |
|
|
47
|
+
| L1 | `ProgressBar` | `(value:, min:, max:, label:)` | determinate/indeterminate | progressbar |
|
|
48
|
+
| L1 | `Spinner` | `(label:, size:)` | animated loading indicator | progressbar/busy |
|
|
49
|
+
| L1 | `Meter` | `(value:, low:, high:, optimum:)` | thresholds | meter |
|
|
50
|
+
| L2 | `Tooltip` | `(text, anchor:, side:, open:)` | top/bottom/left/right | tooltip |
|
|
51
|
+
| L2 | `Popover` | `(content, anchor:, side:, width:, height:, open:, modal:)` | flipped and viewport-clamped | group |
|
|
52
|
+
| L2 | `ContextMenu`, `Menu` | `(items, anchor:, open:)` | pointer + arrows/Home/End/Enter/Esc | menu/menuitem |
|
|
53
|
+
| L2 | `MenuBar` | `(menus)` | compositional | menubar |
|
|
54
|
+
| L2 | `Dropdown` | `(label, items:, value:)`; `on_change` | menu-backed | button |
|
|
55
|
+
| L2 | `TextField` | `(value, placeholder:, label:, prefix:, suffix:, error:, max_length:, clearable:)` | IME, selection, counter | textbox |
|
|
56
|
+
| L2 | `TextArea` | TextField plus `rows:` | multiline/wrapped | textbox/multiline |
|
|
57
|
+
| L2 | `SearchInput` | TextField options | search + clear icons | searchbox |
|
|
58
|
+
| L2 | `PasswordInput` | TextField options | masked display | textbox |
|
|
59
|
+
| L2 | `NumberInput` | TextField plus `min:`, `max:`, `step:`; `increment`, `decrement` | numeric | textbox |
|
|
60
|
+
| L2 | `TagInput` | `(tags, separator:, ...)`; `on_tags_change` | badge list + editor | textbox |
|
|
61
|
+
| L2 | `Select` | `(items, label:, value:, disabled:)`; `on_change` | single choice | combobox |
|
|
62
|
+
| L2 | `Combobox` | `(items, value:, label:, placeholder:, disabled:)`; `on_change` | editable, filtered choices | combobox |
|
|
63
|
+
| L2 | `MultiSelect` | `(items, value:, label:, disabled:)`; `on_change` | multiple selected badges | listbox |
|
|
64
|
+
| L2 | `DatePicker` | `(value, min:, max:, label:, disabled:)`; `on_change` | ISO date, day/week keyboard steps | combobox |
|
|
65
|
+
| L2 | `TimePicker` | `(value, step:, label:, disabled:)`; `on_change` | 24-hour time, minute/hour keyboard steps | combobox |
|
|
66
|
+
| L2 | `ColorPicker` | `(value, label:, swatches:, disabled:)`; `on_change` | hex input and swatches | combobox |
|
|
67
|
+
| L3 | `Tabs` | `(items, selected:)`; `on_change` | arrows/Home/End | tab/tabpanel |
|
|
68
|
+
| L3 | `ScrollView` | `(axis:, scrollbar:)`; `scroll_to` | vertical/horizontal/both; overlay/always/hidden | child tree |
|
|
69
|
+
| L3 | `Scrollbar` | `(scroll_state, axis:, mode:)` | drag, track paging, arrows/Home/End/Page keys | scrollbar |
|
|
70
|
+
| L3 | `Accordion` | `(items, multiple:, open:)` | single/multiple | group |
|
|
71
|
+
| L3 | `Collapsible` | `(label, content, open:)`; `on_change` | open/closed | button/expanded |
|
|
72
|
+
| L3 | `Breadcrumb` | `(items)` | labels or label/callback pairs | navigation/link |
|
|
73
|
+
| L3 | `Pagination` | `(page:, pages:, window:)`; `on_change` | previous/window/next | navigation |
|
|
74
|
+
| L3 | `Toolbar` | `(*children)`, `child` | horizontal | toolbar |
|
|
75
|
+
| L3 | `StatusBar` | `(*children)`, `child` | horizontal | status |
|
|
76
|
+
| L3 | `Sidebar` | `(*children, width:)`, `child` | vertical | navigation |
|
|
77
|
+
| L3 | `Modal`, `Dialog` | `(content, title:, open:, close_on_scrim:, width:)` | focus trap, scrim, Esc | dialog/modal |
|
|
78
|
+
| L3 | `Drawer` | Modal plus `side:` | left/right | dialog/modal |
|
|
79
|
+
| L3 | `Toast` | `(message, variant:, queue:)`; `dismiss` | info/success/warning/danger | live status |
|
|
80
|
+
| L3 | `CommandPalette` | `(commands, open:, placeholder:)` | searchable modal | dialog/list |
|
|
81
|
+
| L3 | `SplitPane` | `(first, second, orientation:, ratio:, min:, max:)`; `on_change` | horizontal/vertical, draggable separator | group/separator |
|
|
82
|
+
| L3 | `Resizable` | `(content, width:, height:, min_width:, min_height:, max_width:, max_height:)`; `on_resize` | drag or keyboard resize | group/separator |
|
|
83
|
+
| L3 | `DockPanel` | `(center:, top:, right:, bottom:, left:)` | five-region layout | group |
|
|
84
|
+
| L3 | `ListView` | `(items, height:, row_height:, selected:)`; `on_select` | virtual rows and keyboard selection | list/listitem |
|
|
85
|
+
| L4 | `Table`, `DataGrid` | `(rows, columns:, height:, selection:, row_key:)`; `on_sort`, `on_select`, `on_edit` | virtual rows, sorting, resizing, editing | table/row/cell |
|
|
86
|
+
| L4 | `TreeView` | `(items, height:, selected:)`; `expand`, `collapse`, lazy `children` proc | arrows/Home/End | tree/treeitem |
|
|
87
|
+
| L5 | `Sparkline` | `(values, width:, height:, color:, label:)` | line + tooltip | image |
|
|
88
|
+
| L5 | `LineChart`, `BarChart` | `(series, width:, height:, colors:, label:)` | axes, legend, tooltip | image |
|
|
89
|
+
| L5 | `Validation` | `required`, `format`, `length`, `number`, `rule` | composable rules | n/a |
|
|
90
|
+
| L5 | `FormField` | `(name, value:, label:, control:, validation:, hint:)` | errors + describedby | group/control/alert |
|
|
91
|
+
| L5 | `Form` | `field`, `on_change`, `on_submit`, `values`, `valid?` | validates before submit | form |
|
|
92
|
+
| L5 | `CodeEditor` | `(value, language:, line_numbers:, read_only:)`; `on_change` | multiline editor with scrolling | textbox |
|
|
93
|
+
| L5 | `RichText` | `(runs, selectable:)` | styled selectable runs | text |
|
|
94
|
+
|
|
95
|
+
All input components are keyboard operable. Disabled controls remain visible but are
|
|
96
|
+
removed from focus traversal. Overlay components close on Esc; modal overlays restore
|
|
97
|
+
the previous focus. See [TUI](tui.md) for terminal representations.
|
|
98
|
+
|
|
99
|
+
Table columns are hashes with `key`, and optional `label`, `width`, `sortable`,
|
|
100
|
+
`resizable`, `editable`, and `render`. Tree items accept hashes containing `id`,
|
|
101
|
+
`label`, and either an array or lazy proc in `children`.
|
|
102
|
+
|
|
103
|
+
In a table, Up/Down/Home/End/Page keys move and select rows, Shift+Up/Down extends
|
|
104
|
+
a range, and Cmd/Ctrl+A selects every row in multiple-selection mode. Sortable
|
|
105
|
+
headers and resize handles are separate Tab stops; Enter sorts and arrow/Page keys
|
|
106
|
+
resize. Tree views use Up/Down to select and Left/Right to collapse or expand.
|
|
107
|
+
|
|
108
|
+
Run `bundle exec ruby tools/generate_component_gallery.rb` to rebuild the dark,
|
|
109
|
+
light, and high-contrast component sheets plus overlay variants in all three themes.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|