@ryanhelsing/ry-ui 1.0.9 → 1.0.11
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/.claude/skills/ry-ui-builder/SKILL.md +186 -0
- package/README.dev.md +302 -0
- package/README.md +462 -187
- package/dist/_redirects +1 -0
- package/dist/app.d.ts +2 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/components/ry-testimonial.d.ts +19 -0
- package/dist/components/ry-testimonial.d.ts.map +1 -0
- package/dist/components/ry-theme-panel.d.ts +25 -0
- package/dist/components/ry-theme-panel.d.ts.map +1 -0
- package/dist/core/ry-icons.d.ts.map +1 -1
- package/dist/core/ry-transform.d.ts.map +1 -1
- package/dist/css/ry-structure.css +122 -3
- package/dist/css/ry-theme.css +133 -0
- package/dist/css/ry-tokens.css +4 -26
- package/dist/css/ry-ui.css +259 -29
- package/dist/pages/components.html +1827 -0
- package/dist/pages/landing.html +229 -0
- package/dist/ry-ui.d.ts +2 -0
- package/dist/ry-ui.d.ts.map +1 -1
- package/dist/ry-ui.js +382 -245
- package/dist/ry-ui.js.map +1 -1
- package/dist/themes/antigravity.css +56 -0
- package/docs/components/forms.md +10 -3
- package/package.json +12 -6
- package/AGENT.md +0 -490
- package/AGENTS.md +0 -57
package/README.md
CHANGED
|
@@ -1,280 +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
|
-
|
|
84
|
-
### Forms
|
|
85
|
-
- `<ry-field>` - Form field wrapper with auto label, error, and hint
|
|
86
|
-
|
|
87
|
-
### Display
|
|
88
|
-
- `<ry-card>` - Card containers
|
|
89
|
-
- `<ry-badge>` - Status badges
|
|
90
|
-
- `<ry-alert>` - Alert messages
|
|
91
|
-
|
|
92
93
|
## Clean Syntax
|
|
93
94
|
|
|
94
|
-
|
|
95
|
+
Wrap markup in `<ry>` to use unprefixed tags:
|
|
95
96
|
|
|
96
97
|
```html
|
|
97
98
|
<ry>
|
|
98
99
|
<accordion>
|
|
99
|
-
<accordion-item title="FAQ" open>
|
|
100
|
-
No ry- prefix needed inside the wrapper.
|
|
101
|
-
</accordion-item>
|
|
100
|
+
<accordion-item title="FAQ" open>No ry- prefix needed.</accordion-item>
|
|
102
101
|
</accordion>
|
|
103
102
|
</ry>
|
|
104
103
|
```
|
|
105
104
|
|
|
106
|
-
|
|
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
|
|
107
197
|
|
|
108
198
|
```html
|
|
109
|
-
|
|
110
|
-
<
|
|
111
|
-
<
|
|
112
|
-
|
|
113
|
-
<!-- Drawer -->
|
|
114
|
-
<ry-button drawer="menu">Open</ry-button>
|
|
115
|
-
<ry-drawer id="menu" side="left">Menu content</ry-drawer>
|
|
116
|
-
|
|
117
|
-
<!-- Select -->
|
|
118
|
-
<ry-select placeholder="Country" name="country">
|
|
119
|
-
<ry-option value="us">United States</ry-option>
|
|
120
|
-
<ry-option value="uk">United Kingdom</ry-option>
|
|
121
|
-
</ry-select>
|
|
122
|
-
|
|
123
|
-
<!-- Split Panel (resizable, persistent) -->
|
|
124
|
-
<ry-split resizable persist="sidebar">
|
|
125
|
-
<main>Main content</main>
|
|
126
|
-
<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>
|
|
127
202
|
</ry-split>
|
|
203
|
+
```
|
|
128
204
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
|
134
210
|
|
|
135
|
-
|
|
136
|
-
<ry-field label="Email"
|
|
137
|
-
<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">
|
|
138
214
|
</ry-field>
|
|
139
215
|
|
|
140
|
-
|
|
141
|
-
<
|
|
142
|
-
|
|
143
|
-
RyToast.error('Failed');
|
|
144
|
-
</script>
|
|
216
|
+
<ry-field label="Password" error="Must be at least 8 characters">
|
|
217
|
+
<input type="password">
|
|
218
|
+
</ry-field>
|
|
145
219
|
```
|
|
146
220
|
|
|
147
|
-
|
|
221
|
+
Error hides hint automatically. Set `error=""` to clear.
|
|
222
|
+
|
|
223
|
+
### Button Group
|
|
148
224
|
|
|
149
225
|
```html
|
|
150
|
-
<
|
|
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>
|
|
151
230
|
```
|
|
152
231
|
|
|
153
|
-
|
|
232
|
+
### Button Variants
|
|
154
233
|
|
|
155
|
-
|
|
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>
|
|
244
|
+
```
|
|
156
245
|
|
|
157
|
-
|
|
246
|
+
### Modal & Drawer
|
|
158
247
|
|
|
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>
|
|
159
262
|
```
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
263
|
+
|
|
264
|
+
### Nav Bar
|
|
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>
|
|
164
281
|
```
|
|
165
282
|
|
|
166
|
-
###
|
|
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
|
+
```
|
|
167
295
|
|
|
168
|
-
|
|
296
|
+
### Pricing
|
|
169
297
|
|
|
170
298
|
```html
|
|
171
|
-
|
|
172
|
-
<
|
|
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
|
+
```
|
|
173
320
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
<
|
|
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>
|
|
178
330
|
```
|
|
179
331
|
|
|
180
|
-
|
|
181
|
-
- Display modes, positioning, flexbox, grid
|
|
182
|
-
- Sizing, padding, margins, gaps
|
|
183
|
-
- State transitions (opacity, visibility, transform)
|
|
332
|
+
### Dropdown Menu
|
|
184
333
|
|
|
185
|
-
|
|
186
|
-
-
|
|
187
|
-
-
|
|
188
|
-
-
|
|
189
|
-
-
|
|
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
|
+
```
|
|
190
344
|
|
|
191
345
|
---
|
|
192
346
|
|
|
193
|
-
##
|
|
347
|
+
## Events
|
|
194
348
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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', () => {});
|
|
200
356
|
```
|
|
201
357
|
|
|
202
|
-
|
|
358
|
+
### Programmatic Control
|
|
203
359
|
|
|
204
|
-
```
|
|
205
|
-
|
|
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';
|
|
206
365
|
```
|
|
207
366
|
|
|
208
|
-
|
|
367
|
+
---
|
|
209
368
|
|
|
210
|
-
##
|
|
369
|
+
## CSS Token System
|
|
211
370
|
|
|
212
|
-
|
|
371
|
+
All visual properties use CSS custom properties. Override in your own CSS to customize.
|
|
213
372
|
|
|
214
|
-
###
|
|
215
|
-
We use plain class syntax with private fields (`#field`) instead of decorators. The code reads like standard JavaScript with type annotations.
|
|
373
|
+
### Colors
|
|
216
374
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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 |
|
|
222
388
|
|
|
223
|
-
|
|
224
|
-
}
|
|
389
|
+
Each color also has `-bg` and `-text` variants for alert/badge backgrounds.
|
|
225
390
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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">
|
|
232
448
|
```
|
|
233
449
|
|
|
234
|
-
###
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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;
|
|
240
459
|
}
|
|
241
460
|
```
|
|
242
461
|
|
|
243
|
-
###
|
|
462
|
+
### Themes & Modes
|
|
244
463
|
|
|
245
|
-
|
|
246
|
-
```typescript
|
|
247
|
-
get value(): string { return this.getAttribute('value') ?? ''; }
|
|
248
|
-
emit<T = void>(name: string, detail?: T): boolean { ... }
|
|
249
|
-
```
|
|
464
|
+
Theme and mode are independent:
|
|
250
465
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
type ToastVariant = 'info' | 'success' | 'warning' | 'error';
|
|
254
|
-
static observedAttributes = ['value', 'disabled'] as const;
|
|
466
|
+
```html
|
|
467
|
+
<html data-ry-theme="ocean" data-ry-mode="dark">
|
|
255
468
|
```
|
|
256
469
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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'));
|
|
262
492
|
}
|
|
263
493
|
}
|
|
264
494
|
```
|
|
265
495
|
|
|
266
|
-
|
|
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';
|
|
267
502
|
|
|
268
|
-
|
|
503
|
+
registerIcon('custom', '<svg>...</svg>');
|
|
504
|
+
registerIcons({ 'app-logo': '<svg>...</svg>' });
|
|
269
505
|
```
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
|
274
514
|
```
|
|
275
515
|
|
|
276
|
-
|
|
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
|
+
```
|
|
277
520
|
|
|
278
521
|
---
|
|
279
522
|
|
|
280
|
-
|
|
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
|