@ryanhelsing/ry-ui 1.0.10 → 1.0.12
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/README.dev.md +302 -0
- package/README.md +460 -199
- package/dist/themes/antigravity.css +56 -0
- package/package.json +3 -5
- package/AGENT.md +0 -492
- package/AGENTS.md +0 -57
- package/examples/starter-local.html +0 -252
- package/examples/starter-minimal.html +0 -252
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/LICENSE.txt +0 -21
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/README.md +0 -7
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/dist/index.html +0 -23
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/dist/style.css +0 -126
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/src/index.html +0 -5
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/src/style.scss +0 -161
- package/examples/themes/skeuomorphic/led-controls/LICENSE.txt +0 -21
- package/examples/themes/skeuomorphic/led-controls/README.md +0 -7
- package/examples/themes/skeuomorphic/led-controls/dist/index.html +0 -17
- package/examples/themes/skeuomorphic/led-controls/dist/script.js +0 -27
- package/examples/themes/skeuomorphic/led-controls/dist/style.css +0 -135
- package/examples/themes/skeuomorphic/led-controls/src/index.html +0 -1
- package/examples/themes/skeuomorphic/led-controls/src/script.ts +0 -59
- package/examples/themes/skeuomorphic/led-controls/src/style.scss +0 -253
- package/llms.txt +0 -346
package/README.md
CHANGED
|
@@ -1,294 +1,555 @@
|
|
|
1
1
|
# ry-ui
|
|
2
2
|
|
|
3
|
-
Framework-agnostic, Light DOM web components. CSS is the source of truth.
|
|
3
|
+
Framework-agnostic, Light DOM web components. Zero dependencies. CSS is the source of truth.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Setup (2 lines)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
ry-ui normalizes this. No decisions to make. No architecture to debate. An LLM can leverage these primitives to build any app, anywhere, with a structure that is grokkable, dumb, and repeatable. Over-engineering becomes irrelevant when there's nothing left to over-engineer.
|
|
7
|
+
```html
|
|
8
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ryanhelsing/ry-ui/dist/css/ry-ui.css">
|
|
9
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@ryanhelsing/ry-ui/dist/ry-ui.js"></script>
|
|
10
|
+
```
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
```bash
|
|
13
|
+
# or npm
|
|
14
|
+
npm install @ryanhelsing/ry-ui
|
|
15
|
+
```
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
Set theme: `<html data-ry-theme="light">` — `light` | `dark` | omit for OS preference
|
|
18
|
+
Set body: `<body style="background: var(--ry-color-bg); color: var(--ry-color-text);">`
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
## DON'T / DO
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- **THEME** (Visual CSS) — Appearance. `ry-theme.css`. Colors, shadows, borders, typography, focus rings. Entirely swappable.
|
|
22
|
+
DON'T write flexbox/grid CSS for page layout.
|
|
23
|
+
DO: `<ry-page><ry-header>H</ry-header><ry-main>M</ry-main><ry-footer>F</ry-footer></ry-page>`
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
DON'T write a custom modal with backdrop, focus trap, escape handling.
|
|
26
|
+
DO: `<ry-button modal="m">Open</ry-button><ry-modal id="m" title="T">Content</ry-modal>`
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
DON'T write a slide-out drawer with CSS transforms.
|
|
29
|
+
DO: `<ry-button drawer="d">Open</ry-button><ry-drawer id="d" side="left">Content</ry-drawer>`
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
-
|
|
31
|
+
DON'T write tab switching logic or CSS.
|
|
32
|
+
DO: `<ry-tabs><ry-tab title="A" active>A</ry-tab><ry-tab title="B">B</ry-tab></ry-tabs>`
|
|
29
33
|
|
|
30
|
-
|
|
34
|
+
DON'T write a custom select dropdown with keyboard navigation.
|
|
35
|
+
DO: `<ry-select placeholder="Pick"><ry-option value="a">A</ry-option></ry-select>`
|
|
31
36
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
- [ ] **Menu / Context Menu** — right-click menus, nested submenus. Required for any desktop-targeting app.
|
|
35
|
-
- [ ] **Command Palette** — Cmd+K pattern. Table stakes for power-user apps and ry-os.
|
|
36
|
-
- [ ] **Toast stacking** — ry-toast exists but needs positioning, stacking multiple toasts, auto-dismiss timers, queue behavior.
|
|
37
|
-
- [ ] **Breadcrumb, Pagination, Stepper** — navigation patterns for any multi-page app.
|
|
37
|
+
DON'T write CSS variables for colors, spacing, shadows.
|
|
38
|
+
DO: Use `--ry-color-*`, `--ry-space-*`, `--ry-radius-*`, `--ry-shadow-*` tokens.
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
DON'T write button styles with hover/active/focus states.
|
|
41
|
+
DO: `<ry-button variant="primary">Click</ry-button>`
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
DON'T write toast/notification CSS and JS.
|
|
44
|
+
DO: `RyToast.success('Saved!')` / `RyToast.error('Failed')`
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
DON'T write accordion expand/collapse logic.
|
|
47
|
+
DO: `<ry-accordion><ry-accordion-item title="Q" open>A</ry-accordion-item></ry-accordion>`
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
- [ ] animation system with GSAP (see `docs/plans/animation-system.md`)
|
|
48
|
-
- [ ] could use to write apps on ry-os lol.. rust based linux DE with html/js/css -> Dioxus -> rust apps / with an llm on device
|
|
49
|
-
- [ ] https://github.com/GrapheneOS — hardened Android, good reference for security-first OS/DE design patterns
|
|
49
|
+
DON'T write a toggle switch from scratch.
|
|
50
|
+
DO: `<ry-switch name="notify" checked></ry-switch>`
|
|
50
51
|
|
|
51
|
-
##
|
|
52
|
+
## Full Page Template
|
|
52
53
|
|
|
53
54
|
```html
|
|
54
|
-
|
|
55
|
-
<
|
|
55
|
+
<!DOCTYPE html>
|
|
56
|
+
<html lang="en" data-ry-theme="light">
|
|
57
|
+
<head>
|
|
58
|
+
<meta charset="UTF-8">
|
|
59
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
60
|
+
<title>My App</title>
|
|
61
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ryanhelsing/ry-ui/dist/css/ry-ui.css">
|
|
62
|
+
</head>
|
|
63
|
+
<body style="background: var(--ry-color-bg); color: var(--ry-color-text);">
|
|
64
|
+
<ry-page>
|
|
65
|
+
<ry-header sticky>
|
|
66
|
+
<ry-cluster>
|
|
67
|
+
<strong>My App</strong>
|
|
68
|
+
<ry-nav>
|
|
69
|
+
<a href="/" aria-current="page">Home</a>
|
|
70
|
+
<a href="/about">About</a>
|
|
71
|
+
</ry-nav>
|
|
72
|
+
</ry-cluster>
|
|
73
|
+
<ry-actions>
|
|
74
|
+
<ry-theme-toggle themes="light,dark"></ry-theme-toggle>
|
|
75
|
+
</ry-actions>
|
|
76
|
+
</ry-header>
|
|
77
|
+
|
|
78
|
+
<ry-main>
|
|
79
|
+
<ry-section>
|
|
80
|
+
<h1>Hello World</h1>
|
|
81
|
+
<p>Your content here.</p>
|
|
82
|
+
</ry-section>
|
|
83
|
+
</ry-main>
|
|
84
|
+
|
|
85
|
+
<ry-footer>Built with ry-ui</ry-footer>
|
|
86
|
+
</ry-page>
|
|
87
|
+
|
|
88
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@ryanhelsing/ry-ui/dist/ry-ui.js"></script>
|
|
89
|
+
</body>
|
|
90
|
+
</html>
|
|
56
91
|
```
|
|
57
92
|
|
|
58
|
-
## Components
|
|
59
|
-
|
|
60
|
-
### Layout (CSS-only)
|
|
61
|
-
- `<ry-page>` - Page container
|
|
62
|
-
- `<ry-header>` / `<ry-footer>` - Page sections
|
|
63
|
-
- `<ry-main>` / `<ry-section>` - Content areas
|
|
64
|
-
- `<ry-grid cols="3">` - Responsive grid
|
|
65
|
-
- `<ry-stack>` / `<ry-cluster>` - Flex layouts
|
|
66
|
-
|
|
67
|
-
### Layout
|
|
68
|
-
- `<ry-split>` - Resizable two-column layout with optional `persist` for localStorage-backed width
|
|
69
|
-
|
|
70
|
-
### Interactive
|
|
71
|
-
- `<ry-button>` - Buttons with variants
|
|
72
|
-
- `<ry-button-group>` - Segmented control / radio button group
|
|
73
|
-
- `<ry-modal>` - Modal dialogs
|
|
74
|
-
- `<ry-drawer>` - Slide-out panels
|
|
75
|
-
- `<ry-accordion>` - Collapsible sections
|
|
76
|
-
- `<ry-tabs>` - Tabbed content
|
|
77
|
-
- `<ry-dropdown>` - Dropdown menus
|
|
78
|
-
- `<ry-select>` - Custom select
|
|
79
|
-
- `<ry-combobox>` - Searchable dropdown
|
|
80
|
-
- `<ry-switch>` - Toggle switch
|
|
81
|
-
- `<ry-tooltip>` - Hover tooltips
|
|
82
|
-
- `<ry-toast>` - Notifications
|
|
83
|
-
- `<ry-theme-panel>` - Floating theme/mode selector (none, default, ocean + light/dark)
|
|
84
|
-
- `<ry-testimonial>` - Customer testimonial / quote card with avatar and star rating
|
|
85
|
-
|
|
86
|
-
### Forms
|
|
87
|
-
- `<ry-field>` - Form field wrapper with auto label, error, and hint
|
|
88
|
-
|
|
89
|
-
### Display
|
|
90
|
-
- `<ry-card>` - Card containers
|
|
91
|
-
- `<ry-badge>` - Status badges
|
|
92
|
-
- `<ry-alert>` - Alert messages
|
|
93
|
-
|
|
94
93
|
## Clean Syntax
|
|
95
94
|
|
|
96
|
-
|
|
95
|
+
Wrap markup in `<ry>` to use unprefixed tags:
|
|
97
96
|
|
|
98
97
|
```html
|
|
99
98
|
<ry>
|
|
100
99
|
<accordion>
|
|
101
|
-
<accordion-item title="FAQ" open>
|
|
102
|
-
No ry- prefix needed inside the wrapper.
|
|
103
|
-
</accordion-item>
|
|
100
|
+
<accordion-item title="FAQ" open>No ry- prefix needed.</accordion-item>
|
|
104
101
|
</accordion>
|
|
105
102
|
</ry>
|
|
106
103
|
```
|
|
107
104
|
|
|
108
|
-
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Component Catalog
|
|
108
|
+
|
|
109
|
+
### Layout (CSS-only, no JS)
|
|
110
|
+
|
|
111
|
+
| Component | Attributes | Description |
|
|
112
|
+
|-----------|-----------|-------------|
|
|
113
|
+
| `<ry-page>` | — | Root page container, flex column, min-height 100dvh |
|
|
114
|
+
| `<ry-header>` | `sticky` | Flex row, space-between. `sticky` pins to top |
|
|
115
|
+
| `<ry-main>` | — | Content area, max-width 1200px, centered |
|
|
116
|
+
| `<ry-footer>` | — | Footer with border-top |
|
|
117
|
+
| `<ry-section>` | — | Block section with bottom margin |
|
|
118
|
+
| `<ry-grid>` | `cols="1-6\|auto-fit\|auto-fill"`, `cols-sm`, `cols-md`, `cols-lg` | CSS grid. [Details](docs/components/layout.md) |
|
|
119
|
+
| `<ry-stack>` | `gap="sm\|md\|lg\|xl"` | Vertical flex column |
|
|
120
|
+
| `<ry-cluster>` | `gap="sm\|md\|lg"` | Horizontal flex row, wraps |
|
|
121
|
+
| `<ry-split>` | `resizable`, `persist="key"` | Two-column with drag resize. [Details](docs/components/layout.md) |
|
|
122
|
+
| `<ry-center>` | — | Flex center (both axes) |
|
|
123
|
+
| `<ry-nav>` | — | Horizontal nav links. Active: `a[aria-current="page"]` |
|
|
124
|
+
| `<ry-logo>` | — | Inline-flex, bold text |
|
|
125
|
+
| `<ry-actions>` | — | Flex row for action buttons |
|
|
126
|
+
| `<ry-divider>` | `vertical` | Horizontal line; `vertical` for inline separator |
|
|
127
|
+
| `<ry-aside>` | — | Sidebar content area |
|
|
128
|
+
|
|
129
|
+
### Interactive Components
|
|
130
|
+
|
|
131
|
+
| Component | Key Attributes | Events |
|
|
132
|
+
|-----------|---------------|--------|
|
|
133
|
+
| `<ry-button>` | `variant="primary\|secondary\|outline\|ghost\|danger\|accent"`, `size="sm\|lg"`, `disabled`, `pressed`, `modal="id"`, `drawer="id"` | `ry:click` |
|
|
134
|
+
| `<ry-button-group>` | `name`, `value` | `ry:change` `{value}` |
|
|
135
|
+
| `<ry-toggle-button>` | `pressed`, `name`, `value`, `size`, `icon`, `disabled` | `ry:change` `{pressed, value}` |
|
|
136
|
+
| `<ry-modal>` | `id`, `title` | Trigger: `<ry-button modal="id">`. [Details](docs/components/modal.md) |
|
|
137
|
+
| `<ry-drawer>` | `id`, `position="left\|right"`, `size` | Trigger: `<ry-button drawer="id">`. [Details](docs/components/drawer.md) |
|
|
138
|
+
| `<ry-accordion>` | — | Container for accordion-items. [Details](docs/components/accordion.md) |
|
|
139
|
+
| `<ry-accordion-item>` | `title`, `open` | Collapsible section |
|
|
140
|
+
| `<ry-tabs>` | — | Children: `<ry-tab title="..." active>`. [Details](docs/components/tabs.md) |
|
|
141
|
+
| `<ry-dropdown>` | — | [Details](docs/components/dropdown.md) |
|
|
142
|
+
| `<ry-select>` | `placeholder`, `name`, `value`, `disabled` | `ry:change` `{value}`. Children: `<ry-option>` |
|
|
143
|
+
| `<ry-combobox>` | `placeholder`, `name`, `value`, `disabled` | `ry:change` `{value, label}`, `ry:input` — searchable dropdown |
|
|
144
|
+
| `<ry-switch>` | `checked`, `disabled`, `name` | `ry:change` `{value, label}` — value is `"true"`/`"false"` string |
|
|
145
|
+
| `<ry-tooltip>` | `content`, `position` | [Details](docs/components/tooltip.md) |
|
|
146
|
+
| `<ry-toast>` | — | `RyToast.success()`, `.error()`, `.warning()`, `.info()`. [Details](docs/components/toast.md) |
|
|
147
|
+
| `<ry-slider>` | `min`, `max`, `step`, `value`, `color`, `disabled` | `ry:change` `{value}`. [Details](docs/components/slider.md) |
|
|
148
|
+
| `<ry-knob>` | `min`, `max`, `step`, `value`, `color`, `size` | `ry:change` `{value}`. [Details](docs/components/knob.md) |
|
|
149
|
+
| `<ry-number-select>` | `min`, `max`, `step`, `value`, `arrows`, `prefix`, `suffix` | `ry:change` `{value}`. [Details](docs/components/number-select.md) |
|
|
150
|
+
| `<ry-color-picker>` | `value`, `format` | `ry:change` `{value}`. [Details](docs/components/color.md) |
|
|
151
|
+
| `<ry-color-input>` | `value`, `format` | `ry:change` `{value}` |
|
|
152
|
+
| `<ry-gradient-picker>` | `value` | `ry:change` `{value}` |
|
|
153
|
+
| `<ry-tree>` | `data` (JSON) | `ry:select`, `ry:move`. [Details](docs/components/tree.md) |
|
|
154
|
+
| `<ry-tag>` | `removable` | `ry:remove` |
|
|
155
|
+
| `<ry-tag-input>` | `name`, `value`, `placeholder` | `ry:change` `{tags}` |
|
|
156
|
+
| `<ry-carousel>` | `autoplay`, `interval` | `ry:change` `{index}` |
|
|
157
|
+
| `<ry-theme-toggle>` | `themes="light,dark"` | Cycles through themes |
|
|
158
|
+
| `<ry-theme-panel>` | `theme`, `mode` | Floating theme/mode selector. Persists to localStorage |
|
|
159
|
+
| `<ry-testimonial>` | `stars` | Quote card with avatar, name, role slots |
|
|
160
|
+
|
|
161
|
+
### Display Components
|
|
162
|
+
|
|
163
|
+
| Component | Key Attributes | Description |
|
|
164
|
+
|-----------|---------------|-------------|
|
|
165
|
+
| `<ry-card>` | `interactive`, `href` | Card container. `interactive` adds click/keyboard. `href` navigates |
|
|
166
|
+
| `<ry-badge>` | `variant="primary\|success\|warning\|danger\|accent"` | Pill badge. Custom: `style="--ry-badge-color: #8B5CF6"` |
|
|
167
|
+
| `<ry-alert>` | `type="info\|success\|warning\|danger"` | Alert box with optional `[slot="title"]` |
|
|
168
|
+
| `<ry-field>` | `label`, `error`, `hint` | Form field wrapper. [Details](docs/components/forms.md) |
|
|
169
|
+
| `<ry-icon>` | `name` | SVG icon from registry |
|
|
170
|
+
| `<ry-code>` | `language`, `title` | Syntax-highlighted code block |
|
|
171
|
+
| `<ry-hero>` | `size="sm\|lg"`, `full-bleed`, `align="left"` | Marketing hero section |
|
|
172
|
+
| `<ry-stat>` | `size="sm\|lg"` | Stat card with `slot="value"`, `slot="label"` |
|
|
173
|
+
| `<ry-feature>` | `icon` | Feature card with icon |
|
|
174
|
+
| `<ry-feature-grid>` | `cols="2\|3\|4"` | Responsive grid for feature cards |
|
|
175
|
+
| `<ry-pricing>` | — | Container for pricing cards |
|
|
176
|
+
| `<ry-pricing-card>` | `featured` | Pricing tier. `featured` scales up with bold border |
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Patterns
|
|
181
|
+
|
|
182
|
+
### Grid
|
|
183
|
+
|
|
184
|
+
```html
|
|
185
|
+
<!-- Fixed columns (auto-responsive: 3-6 → 2 at ≤1024px → 1 at ≤640px) -->
|
|
186
|
+
<ry-grid cols="3">...</ry-grid>
|
|
187
|
+
|
|
188
|
+
<!-- Explicit per-breakpoint -->
|
|
189
|
+
<ry-grid cols="5" cols-md="3" cols-sm="1">...</ry-grid>
|
|
190
|
+
|
|
191
|
+
<!-- Fluid auto-fit -->
|
|
192
|
+
<ry-grid cols="auto-fit">...</ry-grid>
|
|
193
|
+
<ry-grid cols="auto-fit" style="--ry-grid-min: 240px">...</ry-grid>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Split Layout
|
|
109
197
|
|
|
110
198
|
```html
|
|
111
|
-
|
|
112
|
-
<
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
<!-- Drawer -->
|
|
116
|
-
<ry-button drawer="menu">Open</ry-button>
|
|
117
|
-
<ry-drawer id="menu" side="left">Menu content</ry-drawer>
|
|
118
|
-
|
|
119
|
-
<!-- Select -->
|
|
120
|
-
<ry-select placeholder="Country" name="country">
|
|
121
|
-
<ry-option value="us">United States</ry-option>
|
|
122
|
-
<ry-option value="uk">United Kingdom</ry-option>
|
|
123
|
-
</ry-select>
|
|
124
|
-
|
|
125
|
-
<!-- Split Panel (resizable, persistent) -->
|
|
126
|
-
<ry-split resizable persist="sidebar">
|
|
127
|
-
<main>Main content</main>
|
|
128
|
-
<aside>Sidebar</aside>
|
|
199
|
+
<ry-split resizable persist="sidebar" style="--ry-split-width: 400px">
|
|
200
|
+
<div>Main content</div>
|
|
201
|
+
<div>Resizable sidebar — drag, arrow keys, double-click to reset</div>
|
|
129
202
|
</ry-split>
|
|
203
|
+
```
|
|
130
204
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
205
|
+
CSS vars: `--ry-split-width`, `--ry-split-min-width`, `--ry-split-max-width`
|
|
206
|
+
Keyboard: Arrow (±10px), Shift+Arrow (±50px), Home/End, double-click reset
|
|
207
|
+
Event: `ry:resize` `{ width }`
|
|
208
|
+
|
|
209
|
+
### Forms
|
|
136
210
|
|
|
137
|
-
|
|
138
|
-
<ry-field label="Email"
|
|
139
|
-
<input type="email"
|
|
211
|
+
```html
|
|
212
|
+
<ry-field label="Email" hint="We'll never share your email">
|
|
213
|
+
<input type="email" placeholder="you@example.com">
|
|
140
214
|
</ry-field>
|
|
141
215
|
|
|
142
|
-
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
RyToast.error('Failed');
|
|
146
|
-
</script>
|
|
216
|
+
<ry-field label="Password" error="Must be at least 8 characters">
|
|
217
|
+
<input type="password">
|
|
218
|
+
</ry-field>
|
|
147
219
|
```
|
|
148
220
|
|
|
149
|
-
|
|
221
|
+
Error hides hint automatically. Set `error=""` to clear.
|
|
150
222
|
|
|
151
|
-
|
|
223
|
+
### Button Group
|
|
152
224
|
|
|
153
225
|
```html
|
|
154
|
-
|
|
155
|
-
<
|
|
226
|
+
<ry-button-group name="billing" value="monthly">
|
|
227
|
+
<ry-button value="monthly">Monthly</ry-button>
|
|
228
|
+
<ry-button value="annually">Annually</ry-button>
|
|
229
|
+
</ry-button-group>
|
|
230
|
+
```
|
|
156
231
|
|
|
157
|
-
|
|
158
|
-
<html data-ry-mode="dark">
|
|
232
|
+
### Button Variants
|
|
159
233
|
|
|
160
|
-
|
|
161
|
-
<
|
|
234
|
+
```html
|
|
235
|
+
<ry-button>Default</ry-button>
|
|
236
|
+
<ry-button variant="primary">Primary</ry-button>
|
|
237
|
+
<ry-button variant="secondary">Secondary</ry-button>
|
|
238
|
+
<ry-button variant="outline">Outline</ry-button>
|
|
239
|
+
<ry-button variant="ghost">Ghost</ry-button>
|
|
240
|
+
<ry-button variant="danger">Danger</ry-button>
|
|
241
|
+
<ry-button variant="accent">Accent</ry-button>
|
|
242
|
+
<ry-button size="sm">Small</ry-button>
|
|
243
|
+
<ry-button size="lg">Large</ry-button>
|
|
162
244
|
```
|
|
163
245
|
|
|
164
|
-
|
|
165
|
-
Available modes: `auto` (OS preference), `light`, `dark`
|
|
166
|
-
|
|
167
|
-
Use `<ry-theme-panel>` for an interactive floating selector.
|
|
246
|
+
### Modal & Drawer
|
|
168
247
|
|
|
169
|
-
|
|
248
|
+
```html
|
|
249
|
+
<ry-button modal="confirm">Open Modal</ry-button>
|
|
250
|
+
<ry-modal id="confirm" title="Confirm Action">
|
|
251
|
+
<p>Are you sure?</p>
|
|
252
|
+
<ry-cluster>
|
|
253
|
+
<ry-button variant="danger">Delete</ry-button>
|
|
254
|
+
<ry-button variant="ghost">Cancel</ry-button>
|
|
255
|
+
</ry-cluster>
|
|
256
|
+
</ry-modal>
|
|
257
|
+
|
|
258
|
+
<ry-button drawer="settings">Settings</ry-button>
|
|
259
|
+
<ry-drawer id="settings" position="right" size="400px">
|
|
260
|
+
<h3>Settings</h3>
|
|
261
|
+
</ry-drawer>
|
|
262
|
+
```
|
|
170
263
|
|
|
171
|
-
|
|
264
|
+
### Nav Bar
|
|
172
265
|
|
|
266
|
+
```html
|
|
267
|
+
<ry-header sticky>
|
|
268
|
+
<ry-cluster>
|
|
269
|
+
<ry-logo>MyApp</ry-logo>
|
|
270
|
+
<ry-divider vertical></ry-divider>
|
|
271
|
+
<ry-nav>
|
|
272
|
+
<a href="/" aria-current="page">Home</a>
|
|
273
|
+
<a href="/docs">Docs</a>
|
|
274
|
+
</ry-nav>
|
|
275
|
+
</ry-cluster>
|
|
276
|
+
<ry-actions>
|
|
277
|
+
<ry-button variant="ghost" size="sm">Login</ry-button>
|
|
278
|
+
<ry-button size="sm">Sign Up</ry-button>
|
|
279
|
+
</ry-actions>
|
|
280
|
+
</ry-header>
|
|
173
281
|
```
|
|
174
|
-
ry-tokens.css # Design tokens (CSS variables)
|
|
175
|
-
ry-structure.css # Pure layout - no colors, shadows, or borders
|
|
176
|
-
ry-theme.css # All visual styling
|
|
177
|
-
ry-ui.css # Bundled (all three combined)
|
|
178
|
-
```
|
|
179
282
|
|
|
180
|
-
###
|
|
283
|
+
### Hero
|
|
284
|
+
|
|
285
|
+
```html
|
|
286
|
+
<ry-hero>
|
|
287
|
+
<h1>Build faster with ry-ui</h1>
|
|
288
|
+
<p>Framework-agnostic components for any app.</p>
|
|
289
|
+
<ry-cluster>
|
|
290
|
+
<ry-button size="lg">Get Started</ry-button>
|
|
291
|
+
<ry-button variant="outline" size="lg">View Docs</ry-button>
|
|
292
|
+
</ry-cluster>
|
|
293
|
+
</ry-hero>
|
|
294
|
+
```
|
|
181
295
|
|
|
182
|
-
|
|
296
|
+
### Pricing
|
|
183
297
|
|
|
184
298
|
```html
|
|
185
|
-
|
|
186
|
-
<
|
|
299
|
+
<ry-pricing>
|
|
300
|
+
<ry-pricing-card>
|
|
301
|
+
<h3>Free</h3>
|
|
302
|
+
<div class="ry-pricing__price">$0<span>/mo</span></div>
|
|
303
|
+
<ul class="ry-check-list">
|
|
304
|
+
<li>3 projects</li>
|
|
305
|
+
<li>Basic support</li>
|
|
306
|
+
</ul>
|
|
307
|
+
<ry-button variant="outline">Get Started</ry-button>
|
|
308
|
+
</ry-pricing-card>
|
|
309
|
+
<ry-pricing-card featured>
|
|
310
|
+
<h3>Pro</h3>
|
|
311
|
+
<div class="ry-pricing__price">$19<span>/mo</span></div>
|
|
312
|
+
<ul class="ry-check-list">
|
|
313
|
+
<li>Unlimited projects</li>
|
|
314
|
+
<li>Priority support</li>
|
|
315
|
+
</ul>
|
|
316
|
+
<ry-button>Upgrade</ry-button>
|
|
317
|
+
</ry-pricing-card>
|
|
318
|
+
</ry-pricing>
|
|
319
|
+
```
|
|
187
320
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
<
|
|
321
|
+
### Interactive Card Grid
|
|
322
|
+
|
|
323
|
+
```html
|
|
324
|
+
<ry-grid cols="3">
|
|
325
|
+
<ry-card interactive href="/feature-a">
|
|
326
|
+
<h3>Feature A</h3>
|
|
327
|
+
<p>Description</p>
|
|
328
|
+
</ry-card>
|
|
329
|
+
</ry-grid>
|
|
192
330
|
```
|
|
193
331
|
|
|
194
|
-
|
|
195
|
-
- Display modes, positioning, flexbox, grid
|
|
196
|
-
- Sizing, padding, margins, gaps
|
|
197
|
-
- State transitions (opacity, visibility, transform)
|
|
332
|
+
### Dropdown Menu
|
|
198
333
|
|
|
199
|
-
|
|
200
|
-
-
|
|
201
|
-
-
|
|
202
|
-
-
|
|
203
|
-
-
|
|
334
|
+
```html
|
|
335
|
+
<ry-dropdown>
|
|
336
|
+
<ry-button slot="trigger">Actions</ry-button>
|
|
337
|
+
<ry-menu>
|
|
338
|
+
<ry-menu-item>Edit</ry-menu-item>
|
|
339
|
+
<ry-menu-item>Duplicate</ry-menu-item>
|
|
340
|
+
<ry-menu-item>Delete</ry-menu-item>
|
|
341
|
+
</ry-menu>
|
|
342
|
+
</ry-dropdown>
|
|
343
|
+
```
|
|
204
344
|
|
|
205
345
|
---
|
|
206
346
|
|
|
207
|
-
##
|
|
347
|
+
## Events
|
|
208
348
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
349
|
+
All events prefixed with `ry:`:
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
element.addEventListener('ry:change', (e) => console.log(e.detail));
|
|
353
|
+
element.addEventListener('ry:open', () => {});
|
|
354
|
+
element.addEventListener('ry:close', () => {});
|
|
355
|
+
element.addEventListener('ry:click', () => {});
|
|
214
356
|
```
|
|
215
357
|
|
|
216
|
-
|
|
358
|
+
### Programmatic Control
|
|
217
359
|
|
|
218
|
-
```
|
|
219
|
-
|
|
360
|
+
```javascript
|
|
361
|
+
document.querySelector('ry-modal').open();
|
|
362
|
+
document.querySelector('ry-modal').close();
|
|
363
|
+
document.querySelector('ry-drawer').toggle();
|
|
364
|
+
document.querySelector('ry-select').value = 'new-value';
|
|
220
365
|
```
|
|
221
366
|
|
|
222
|
-
|
|
367
|
+
---
|
|
223
368
|
|
|
224
|
-
##
|
|
369
|
+
## CSS Token System
|
|
225
370
|
|
|
226
|
-
|
|
371
|
+
All visual properties use CSS custom properties. Override in your own CSS to customize.
|
|
227
372
|
|
|
228
|
-
###
|
|
229
|
-
We use plain class syntax with private fields (`#field`) instead of decorators. The code reads like standard JavaScript with type annotations.
|
|
373
|
+
### Colors
|
|
230
374
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
375
|
+
| Token | Purpose |
|
|
376
|
+
|-------|---------|
|
|
377
|
+
| `--ry-color-primary` / `-hover` / `-active` | Primary action color |
|
|
378
|
+
| `--ry-color-secondary` / `-hover` / `-active` | Secondary muted color |
|
|
379
|
+
| `--ry-color-accent` / `-hover` / `-active` | Accent/highlight color |
|
|
380
|
+
| `--ry-color-success` | Green for positive states |
|
|
381
|
+
| `--ry-color-warning` | Yellow/orange for caution |
|
|
382
|
+
| `--ry-color-danger` / `-hover` | Red for destructive actions |
|
|
383
|
+
| `--ry-color-info` | Blue for informational |
|
|
384
|
+
| `--ry-color-text` / `-muted` / `-inverse` | Text colors |
|
|
385
|
+
| `--ry-color-bg` / `-subtle` / `-muted` | Background colors |
|
|
386
|
+
| `--ry-color-border` / `-strong` | Border colors |
|
|
387
|
+
| `--ry-color-overlay` | Modal/drawer backdrop |
|
|
236
388
|
|
|
237
|
-
|
|
238
|
-
}
|
|
389
|
+
Each color also has `-bg` and `-text` variants for alert/badge backgrounds.
|
|
239
390
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
391
|
+
### Spacing
|
|
392
|
+
|
|
393
|
+
`--ry-space-{0,1,2,3,4,5,6,8,10,12,16,20}` — 0 to 5rem
|
|
394
|
+
|
|
395
|
+
### Typography
|
|
396
|
+
|
|
397
|
+
| Token | Value |
|
|
398
|
+
|-------|-------|
|
|
399
|
+
| `--ry-font-sans` | system-ui stack |
|
|
400
|
+
| `--ry-font-mono` | ui-monospace stack |
|
|
401
|
+
| `--ry-text-{xs,sm,base,lg,xl,2xl,3xl,4xl}` | 0.75rem to 2.25rem |
|
|
402
|
+
| `--ry-font-{normal,medium,semibold,bold}` | 400 to 700 |
|
|
403
|
+
|
|
404
|
+
### Borders & Shadows
|
|
405
|
+
|
|
406
|
+
| Token | Value |
|
|
407
|
+
|-------|-------|
|
|
408
|
+
| `--ry-radius-{none,sm,md,lg,xl,2xl,full}` | 0 to 9999px |
|
|
409
|
+
| `--ry-shadow-{sm,md,lg,xl}` | Elevation shadows |
|
|
410
|
+
| `--ry-border-width` | 1px |
|
|
411
|
+
|
|
412
|
+
### Transitions
|
|
413
|
+
|
|
414
|
+
| Token | Value |
|
|
415
|
+
|-------|-------|
|
|
416
|
+
| `--ry-duration-{fast,normal,slow}` | 100ms, 200ms, 300ms |
|
|
417
|
+
| `--ry-ease` / `-in` / `-out` | Cubic bezier easing |
|
|
418
|
+
|
|
419
|
+
### Z-Index
|
|
420
|
+
|
|
421
|
+
| Token | Value |
|
|
422
|
+
|-------|-------|
|
|
423
|
+
| `--ry-z-dropdown` | 1000 |
|
|
424
|
+
| `--ry-z-sticky` | 1020 |
|
|
425
|
+
| `--ry-z-modal-backdrop` | 1040 |
|
|
426
|
+
| `--ry-z-modal` | 1050 |
|
|
427
|
+
| `--ry-z-tooltip` | 1070 |
|
|
428
|
+
| `--ry-z-toast` | 1080 |
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## Theming
|
|
433
|
+
|
|
434
|
+
Three CSS layers, loaded in order:
|
|
435
|
+
|
|
436
|
+
1. **ry-tokens.css** — CSS custom properties (colors, spacing, etc.)
|
|
437
|
+
2. **ry-structure.css** — Pure layout (no colors)
|
|
438
|
+
3. **ry-theme.css** — All visual styling (colors, shadows, borders)
|
|
439
|
+
|
|
440
|
+
### Custom Theme
|
|
441
|
+
|
|
442
|
+
Load structure-only and bring your own:
|
|
443
|
+
|
|
444
|
+
```html
|
|
445
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ryanhelsing/ry-ui/dist/css/ry-structure.css">
|
|
446
|
+
<link rel="stylesheet" href="your-tokens.css">
|
|
447
|
+
<link rel="stylesheet" href="your-theme.css">
|
|
246
448
|
```
|
|
247
449
|
|
|
248
|
-
###
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
450
|
+
### Override Tokens
|
|
451
|
+
|
|
452
|
+
No build step needed:
|
|
453
|
+
|
|
454
|
+
```css
|
|
455
|
+
:root {
|
|
456
|
+
--ry-color-primary: oklch(0.541 0.218 293);
|
|
457
|
+
--ry-color-primary-hover: oklch(0.491 0.234 292);
|
|
458
|
+
--ry-radius-md: 0;
|
|
254
459
|
}
|
|
255
460
|
```
|
|
256
461
|
|
|
257
|
-
###
|
|
462
|
+
### Themes & Modes
|
|
258
463
|
|
|
259
|
-
|
|
260
|
-
```typescript
|
|
261
|
-
get value(): string { return this.getAttribute('value') ?? ''; }
|
|
262
|
-
emit<T = void>(name: string, detail?: T): boolean { ... }
|
|
263
|
-
```
|
|
464
|
+
Theme and mode are independent:
|
|
264
465
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
type ToastVariant = 'info' | 'success' | 'warning' | 'error';
|
|
268
|
-
static observedAttributes = ['value', 'disabled'] as const;
|
|
466
|
+
```html
|
|
467
|
+
<html data-ry-theme="ocean" data-ry-mode="dark">
|
|
269
468
|
```
|
|
270
469
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
470
|
+
Themes: `default`, `ocean`, `none` (structure only)
|
|
471
|
+
Modes: `auto` (OS preference), `light`, `dark`
|
|
472
|
+
|
|
473
|
+
Use `<ry-theme-panel>` for an interactive floating selector.
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## TypeScript
|
|
478
|
+
|
|
479
|
+
```ts
|
|
480
|
+
import { RyElement, RyButton, RyToast } from '@ryanhelsing/ry-ui';
|
|
481
|
+
|
|
482
|
+
RyToast.success('Saved!');
|
|
483
|
+
|
|
484
|
+
document.querySelector('ry-select')?.addEventListener('ry:change', (e: CustomEvent) => {
|
|
485
|
+
console.log(e.detail.value);
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
// Extend components
|
|
489
|
+
class MyWidget extends RyElement {
|
|
490
|
+
setup() {
|
|
491
|
+
this.on(this, 'click', () => this.emit('activate'));
|
|
276
492
|
}
|
|
277
493
|
}
|
|
278
494
|
```
|
|
279
495
|
|
|
280
|
-
|
|
496
|
+
## Icon Registry
|
|
497
|
+
|
|
498
|
+
Built-in: `settings`, `heart`, `star`, `chevron-up`, `chevron-down`, `chevron-left`, `chevron-right`, `check`, `x`, `plus`, `minus`, `search`, `sun`, `moon`, `copy`, `trash`, `edit`, `eye`, `folder`, `file`, `drag`
|
|
499
|
+
|
|
500
|
+
```ts
|
|
501
|
+
import { registerIcon, registerIcons } from '@ryanhelsing/ry-ui';
|
|
281
502
|
|
|
282
|
-
|
|
503
|
+
registerIcon('custom', '<svg>...</svg>');
|
|
504
|
+
registerIcons({ 'app-logo': '<svg>...</svg>' });
|
|
283
505
|
```
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
506
|
+
|
|
507
|
+
## Vendoring
|
|
508
|
+
|
|
509
|
+
Copy into your project instead of using CDN:
|
|
510
|
+
|
|
511
|
+
```bash
|
|
512
|
+
npm pack @ryanhelsing/ry-ui && tar -xf ryanhelsing-ry-ui-*.tgz
|
|
513
|
+
cp -r package/dist ./vendor/ry-ui && rm -rf package ryanhelsing-ry-ui-*.tgz
|
|
288
514
|
```
|
|
289
515
|
|
|
290
|
-
|
|
516
|
+
```html
|
|
517
|
+
<link rel="stylesheet" href="/vendor/ry-ui/css/ry-ui.css">
|
|
518
|
+
<script type="module" src="/vendor/ry-ui/ry-ui.js"></script>
|
|
519
|
+
```
|
|
291
520
|
|
|
292
521
|
---
|
|
293
522
|
|
|
294
|
-
|
|
523
|
+
## Detailed Docs
|
|
524
|
+
|
|
525
|
+
Per-component docs with full attributes, events, and examples:
|
|
526
|
+
|
|
527
|
+
| Doc | Components |
|
|
528
|
+
|-----|-----------|
|
|
529
|
+
| [layout](docs/components/layout.md) | page, header, main, footer, section, grid, stack, cluster, split, center, card, nav, divider |
|
|
530
|
+
| [button](docs/components/button.md) | button, toggle-button |
|
|
531
|
+
| [button-group](docs/components/button-group.md) | button-group |
|
|
532
|
+
| [accordion](docs/components/accordion.md) | accordion, accordion-item |
|
|
533
|
+
| [tabs](docs/components/tabs.md) | tabs, tab |
|
|
534
|
+
| [modal](docs/components/modal.md) | modal |
|
|
535
|
+
| [drawer](docs/components/drawer.md) | drawer |
|
|
536
|
+
| [dropdown](docs/components/dropdown.md) | dropdown, menu, menu-item |
|
|
537
|
+
| [tooltip](docs/components/tooltip.md) | tooltip |
|
|
538
|
+
| [toast](docs/components/toast.md) | toast |
|
|
539
|
+
| [forms](docs/components/forms.md) | field, select, switch |
|
|
540
|
+
| [slider](docs/components/slider.md) | slider |
|
|
541
|
+
| [knob](docs/components/knob.md) | knob |
|
|
542
|
+
| [number-select](docs/components/number-select.md) | number-select |
|
|
543
|
+
| [color](docs/components/color.md) | color-picker, color-input, gradient-picker |
|
|
544
|
+
| [tree](docs/components/tree.md) | tree |
|
|
545
|
+
| [display](docs/components/display.md) | badge, alert, icon, code |
|
|
546
|
+
| [theme-toggle](docs/components/theme-toggle.md) | theme-toggle |
|
|
547
|
+
| [theming](docs/theming.md) | tokens, custom themes, structure-only loading |
|
|
548
|
+
|
|
549
|
+
## AI-Friendly
|
|
550
|
+
|
|
551
|
+
This package includes a `.claude/skills/ry-ui-builder` skill so Claude Code can build with these components automatically. The detailed docs above serve as the complete agent reference.
|
|
552
|
+
|
|
553
|
+
## License
|
|
554
|
+
|
|
555
|
+
MIT
|