@rip-lang/ui 0.3.29 → 0.3.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +68 -27
  2. package/index.rip +1 -1
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Headless, accessible UI components written in Rip. Zero dependencies.
4
4
  Every widget exposes `$` attributes (compiled to `data-*`) for styling and
5
5
  handles keyboard interactions per WAI-ARIA Authoring Practices. Style with
6
- Tailwind, vanilla CSS, or any methodology you prefer.
6
+ Tailwind using `data-[attr]:` variants.
7
7
 
8
8
  Components are plain `.rip` source files — no build step. The browser compiles
9
9
  them on the fly.
@@ -17,7 +17,7 @@ Add the components directory to your serve middleware:
17
17
  ```coffee
18
18
  use serve
19
19
  dir: dir
20
- components: ['components', '../../../packages/ui']
20
+ bundle: ['components', '../../../packages/ui']
21
21
  ```
22
22
 
23
23
  All widgets become available by name (`Select`, `Dialog`, `Grid`, etc.) in the
@@ -31,8 +31,8 @@ rip server
31
31
  Every widget:
32
32
  - Handles all keyboard interactions per WAI-ARIA Authoring Practices
33
33
  - Sets correct ARIA attributes automatically
34
- - Exposes state via `$` sigil (`$open`, `$selected`) for CSS styling
35
- - Ships no CSS — style with Tailwind or any methodology
34
+ - Exposes state via `$` sigil (`$open`, `$selected`) style with Tailwind's `data-[attr]:` variants
35
+ - Ships no CSS — you bring Tailwind classes
36
36
  - Uses Rip's reactive primitives for all state management
37
37
 
38
38
  ---
@@ -54,6 +54,7 @@ to know to use these widgets:
54
54
  | `ref:` | DOM ref | `ref: "_panel"` — saves DOM element reference |
55
55
  | `slot` | Children | Projects parent-provided content into the component |
56
56
  | `offer` / `accept` | Context | Share reactive state between ancestor and descendant components |
57
+ | `::` | Type | `@variant:: string := "default"` — typed prop (enables IDE completions + diagnostics) |
57
58
 
58
59
  Two-way binding example — React vs Rip:
59
60
 
@@ -79,7 +80,7 @@ input value <=> @name
79
80
  | Component count | ~40 | 54 |
80
81
  | Total source | ShadCN wrappers (~3K LOC) atop Radix (~20K+ LOC) | 5,191 SLOC — everything included |
81
82
  | Build step | Required (Next.js, Vite, etc.) | None — browser compiles `.rip` source |
82
- | Styling | Pre-wired Tailwind (ShadCN) or unstyled (Radix) | Headless — `data-*` contract, style with Tailwind or any CSS |
83
+ | Styling | Pre-wired Tailwind (ShadCN) or unstyled (Radix) | Headless — `data-*` contract, styled with Tailwind |
83
84
  | Controlled components | `value` + `onChange` callback pair | `<=>` two-way binding |
84
85
  | Shared state | React Context + Provider wrappers | `offer` / `accept` keywords |
85
86
  | Reactivity | `useState` + `useEffect` + dependency arrays | `:=` / `~=` / `~>` — language-level |
@@ -105,11 +106,7 @@ development, save and see — SSE-based hot reload.
105
106
  **Source as distribution.** Components are served as `.rip` source files.
106
107
  Read them, understand them, modify them.
107
108
 
108
- ### Why We Build Our Own
109
-
110
- Radix and Base UI implement proven WAI-ARIA patterns, but they require
111
- React. Rip reimplements the same behavioral patterns using its own
112
- primitives:
109
+ ### Component Primitives
113
110
 
114
111
  | Capability | React | Rip |
115
112
  |-----------|-------|-----|
@@ -119,42 +116,86 @@ primitives:
119
116
  | Two-way binding | `value` + `onChange` pair | `<=>` operator |
120
117
  | Reactivity | Hooks + dependency arrays | `:=` / `~=` / `~>` |
121
118
 
122
- This lets Rip use the **right pattern for each widget**: single-component
123
- for data-driven widgets (Select, Combobox, Menu), compositional via
124
- `offer`/`accept` when children contain complex content the parent shouldn't
125
- own.
126
-
127
119
  ---
128
120
 
129
- ## Styling
121
+ ## Styling with Tailwind
122
+
123
+ Widgets are headless — they ship no CSS. Each widget exposes semantic state
124
+ through `$` attributes that compile to `data-*` in HTML. Style them with
125
+ Tailwind's data attribute variants.
126
+
127
+ ### Setup
130
128
 
131
- All widgets are headless — they ship no CSS. The contract between behavior
132
- and styling is `data-*` attributes:
129
+ ```html
130
+ <script src="https://cdn.tailwindcss.com"></script>
131
+ ```
132
+
133
+ ### The `data-*` Contract
134
+
135
+ Widgets set `data-*` attributes to reflect their state. Tailwind targets
136
+ these with `data-[attr]:` variants:
133
137
 
134
138
  ```coffee
135
- # Widget exposes semantic state
139
+ # Widget source behavior only, zero styling
136
140
  button $open: open?!, $disabled: @disabled?!
141
+ div $highlighted: (idx is highlightedIndex)?!
142
+ div $selected: (@value is current)?!
143
+ ```
144
+
145
+ ```html
146
+ <!-- Your markup — Tailwind classes -->
147
+ <button class="border border-gray-300 rounded-lg px-4 py-2
148
+ data-[open]:border-blue-500 data-[open]:ring-2 data-[open]:ring-blue-200
149
+ data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed">
137
150
  ```
138
151
 
139
- Style with Tailwind's data attribute variants:
152
+ ### Common Patterns
153
+
154
+ **Button:**
140
155
 
141
156
  ```html
142
- <button class="data-[open]:border-blue-500 data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed">
157
+ <button class="inline-flex items-center gap-2 px-4 py-2 rounded-lg
158
+ bg-blue-600 text-white font-medium
159
+ hover:bg-blue-700 active:scale-[0.98] transition
160
+ data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed">
143
161
  ```
144
162
 
145
- Or vanilla CSS:
163
+ **Select trigger:**
146
164
 
147
- ```css
148
- [data-open] { border-color: theme('colors.blue.500'); }
149
- [data-disabled] { opacity: 0.5; cursor: not-allowed; }
165
+ ```html
166
+ <button class="inline-flex items-center justify-between w-full px-3 py-2
167
+ border border-gray-300 rounded-lg bg-white
168
+ data-[open]:border-blue-500 data-[open]:ring-2 data-[open]:ring-blue-200">
150
169
  ```
151
170
 
152
- Add Tailwind via CDN — no build step needed:
171
+ **Select option:**
153
172
 
154
173
  ```html
155
- <script src="https://cdn.tailwindcss.com"></script>
174
+ <div class="px-3 py-2 rounded cursor-pointer
175
+ data-[highlighted]:bg-gray-100
176
+ data-[selected]:font-semibold data-[selected]:text-blue-600">
177
+ ```
178
+
179
+ **Dialog overlay:**
180
+
181
+ ```html
182
+ <div class="fixed inset-0 bg-black/50 flex items-center justify-center">
183
+ <div class="bg-white rounded-xl shadow-xl p-6 max-w-md w-full">
156
184
  ```
157
185
 
186
+ ### Dark Mode
187
+
188
+ Use Tailwind's `dark:` variant with a class-based toggle:
189
+
190
+ ```html
191
+ <html class="dark">
192
+ <!-- dark:bg-gray-900 dark:text-gray-100 etc. -->
193
+ ```
194
+
195
+ Or define semantic color tokens in your Tailwind config and reference them
196
+ throughout — `bg-surface`, `text-primary`, `border-muted` — so dark mode
197
+ is a single token swap, not per-element `dark:` classes.
198
+
158
199
  ---
159
200
 
160
201
  ## Code Density
package/index.rip CHANGED
@@ -5,7 +5,7 @@ import { serve } from '@rip-lang/server/middleware'
5
5
 
6
6
  dir = import.meta.dir
7
7
 
8
- use serve dir: dir, components: ['.'], watch: true
8
+ use serve dir: dir, bundle: ['.'], watch: true
9
9
 
10
10
  get '/*.rip', -> @send "#{dir}/#{@req.path.slice(1)}"
11
11
  get '/*.css', -> @send "#{dir}/#{@req.path.slice(1)}", 'text/css; charset=UTF-8'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rip-lang/ui",
3
- "version": "0.3.29",
3
+ "version": "0.3.30",
4
4
  "description": "Headless, accessible UI components written in Rip — zero CSS, zero dependencies",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -31,7 +31,7 @@
31
31
  "author": "Steve Shreeve <steve.shreeve@gmail.com>",
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
- "rip-lang": ">=3.13.84"
34
+ "rip-lang": ">=3.13.85"
35
35
  },
36
36
  "files": [
37
37
  "*.rip",