rip-lang 3.13.71 → 3.13.72
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.md +1 -1
- package/docs/dist/rip.js +25 -2
- package/docs/dist/rip.min.js +2 -2
- package/docs/dist/rip.min.js.br +0 -0
- package/docs/ui/alert-dialog.rip +96 -0
- package/docs/ui/badge.rip +15 -0
- package/docs/ui/breadcrumb.rip +46 -0
- package/docs/ui/button-group.rip +26 -0
- package/docs/ui/card.rip +25 -0
- package/docs/ui/carousel.rip +110 -0
- package/docs/ui/collapsible.rip +50 -0
- package/docs/ui/hljs-rip.js +209 -0
- package/docs/ui/index.css +412 -19
- package/docs/ui/index.html +690 -354
- package/docs/ui/input-group.rip +28 -0
- package/docs/ui/label.rip +16 -0
- package/docs/ui/native-select.rip +32 -0
- package/docs/ui/pagination.rip +123 -0
- package/docs/ui/resizable.rip +123 -0
- package/docs/ui/skeleton.rip +22 -0
- package/docs/ui/spinner.rip +17 -0
- package/docs/ui/table.rip +27 -0
- package/docs/ui/textarea.rip +48 -0
- package/package.json +1 -1
- package/src/browser.js +23 -0
package/docs/ui/index.html
CHANGED
|
@@ -48,6 +48,22 @@
|
|
|
48
48
|
popover.rip
|
|
49
49
|
accordion.rip
|
|
50
50
|
grid.rip
|
|
51
|
+
badge.rip
|
|
52
|
+
skeleton.rip
|
|
53
|
+
spinner.rip
|
|
54
|
+
card.rip
|
|
55
|
+
label.rip
|
|
56
|
+
textarea.rip
|
|
57
|
+
native-select.rip
|
|
58
|
+
input-group.rip
|
|
59
|
+
button-group.rip
|
|
60
|
+
alert-dialog.rip
|
|
61
|
+
breadcrumb.rip
|
|
62
|
+
table.rip
|
|
63
|
+
collapsible.rip
|
|
64
|
+
pagination.rip
|
|
65
|
+
carousel.rip
|
|
66
|
+
resizable.rip
|
|
51
67
|
" data-mount="WidgetGallery">
|
|
52
68
|
</script>
|
|
53
69
|
</head>
|
|
@@ -58,7 +74,26 @@ do ->
|
|
|
58
74
|
orig = HTMLElement::focus
|
|
59
75
|
HTMLElement::focus = (o) -> orig.call this, { preventScroll: true, ...o }
|
|
60
76
|
|
|
77
|
+
export SectionHead = component
|
|
78
|
+
accept _gallery
|
|
79
|
+
@tag := ''
|
|
80
|
+
@name := ''
|
|
81
|
+
@lines := 0
|
|
82
|
+
|
|
83
|
+
render
|
|
84
|
+
.section-title
|
|
85
|
+
= @name
|
|
86
|
+
if @lines > 0
|
|
87
|
+
span.badge @click: (=> _gallery._viewSource(@tag)), "#{@lines} lines ❐"
|
|
88
|
+
else
|
|
89
|
+
span.badge "pattern"
|
|
90
|
+
.section-nav
|
|
91
|
+
a @click: (=> _gallery._navSection(@tag, 'prev')), "‹"
|
|
92
|
+
a @click: (=> _gallery._navSection(@tag, 'home')), "⌂"
|
|
93
|
+
a @click: (=> _gallery._navSection(@tag, 'next')), "›"
|
|
94
|
+
|
|
61
95
|
export WidgetGallery = component
|
|
96
|
+
offer _gallery := this
|
|
62
97
|
|
|
63
98
|
# ---- State ----
|
|
64
99
|
check1 := false
|
|
@@ -96,6 +131,11 @@ export WidgetGallery = component
|
|
|
96
131
|
pickedDate := null
|
|
97
132
|
dateRange := null
|
|
98
133
|
darkMode := false
|
|
134
|
+
showAlertDialog := false
|
|
135
|
+
textareaVal := ''
|
|
136
|
+
nativeSelectVal := ''
|
|
137
|
+
collapsibleOpen := false
|
|
138
|
+
currentPage := 1
|
|
99
139
|
sourceCode := null
|
|
100
140
|
sourceName := ''
|
|
101
141
|
sourceLines := 0
|
|
@@ -104,12 +144,13 @@ export WidgetGallery = component
|
|
|
104
144
|
tocGroups := [
|
|
105
145
|
{ label: 'Selection', ids: ['select', 'combobox', 'multi-select', 'autocomplete'] }
|
|
106
146
|
{ label: 'Toggle', ids: ['checkbox', 'toggle', 'toggle-group', 'radio-group', 'checkbox-group'] }
|
|
107
|
-
{ label: 'Input', ids: ['input', 'number-field', 'slider', 'otp-field', 'date-picker', 'editable-value'] }
|
|
108
|
-
{ label: 'Navigation', ids: ['tabs', 'menu', 'context-menu', 'menubar', 'nav-menu', 'toolbar'] }
|
|
109
|
-
{ label: 'Overlay', ids: ['dialog', 'drawer', 'popover', 'tooltip', 'preview-card', 'toast'] }
|
|
110
|
-
{ label: 'Display', ids: ['button', 'separator', 'progress', 'meter', 'avatar', 'scroll-area'] }
|
|
111
|
-
{ label: 'Form', ids: ['field', 'fieldset', 'form'] }
|
|
112
|
-
{ label: 'Data', ids: ['grid', 'accordion'] }
|
|
147
|
+
{ label: 'Input', ids: ['input', 'textarea', 'native-select', 'number-field', 'slider', 'otp-field', 'date-picker', 'editable-value', 'input-group'] }
|
|
148
|
+
{ label: 'Navigation', ids: ['tabs', 'menu', 'context-menu', 'menubar', 'nav-menu', 'toolbar', 'breadcrumb'] }
|
|
149
|
+
{ label: 'Overlay', ids: ['dialog', 'alert-dialog', 'drawer', 'popover', 'tooltip', 'preview-card', 'toast'] }
|
|
150
|
+
{ label: 'Display', ids: ['button', 'badge', 'card', 'separator', 'progress', 'meter', 'spinner', 'skeleton', 'avatar', 'label', 'scroll-area'] }
|
|
151
|
+
{ label: 'Form', ids: ['field', 'fieldset', 'form', 'button-group'] }
|
|
152
|
+
{ label: 'Data', ids: ['grid', 'accordion', 'table', 'collapsible'] }
|
|
153
|
+
{ label: 'Interactive', ids: ['pagination', 'carousel', 'resizable'] }
|
|
113
154
|
]
|
|
114
155
|
_nameFor: (id) -> (tocData.find((c) -> c.id is id))?.name or id
|
|
115
156
|
_viewSource: (id) ->
|
|
@@ -128,7 +169,11 @@ export WidgetGallery = component
|
|
|
128
169
|
document.head.appendChild(link)
|
|
129
170
|
script = document.createElement('script')
|
|
130
171
|
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js'
|
|
131
|
-
script.onload =
|
|
172
|
+
script.onload = =>
|
|
173
|
+
fetch('hljs-rip.js').then((r) -> r.text()).then (src) =>
|
|
174
|
+
fn = new Function('return ' + src.replace(/[\s\S]*export default /, ''))()
|
|
175
|
+
hljs.registerLanguage 'rip', fn
|
|
176
|
+
cb()
|
|
132
177
|
document.head.appendChild(script)
|
|
133
178
|
_onFilter: (e) -> tocFilter = e.target.value
|
|
134
179
|
_getVisibleLinks: -> Array.from(document.querySelectorAll('.toc-nav .toc-group a:not([data-hidden])') or [])
|
|
@@ -235,44 +280,60 @@ export WidgetGallery = component
|
|
|
235
280
|
if visible.length is 1
|
|
236
281
|
tocActive = visible[0].getAttribute('href')?.slice(1)
|
|
237
282
|
tocData := [
|
|
238
|
-
{ id: 'select', name: 'Select', lines:
|
|
239
|
-
{ id: 'combobox', name: 'Combobox', lines:
|
|
240
|
-
{ id: 'multi-select', name: 'MultiSelect', lines:
|
|
241
|
-
{ id: 'autocomplete', name: 'Autocomplete', lines:
|
|
242
|
-
{ id: 'checkbox', name: 'Checkbox', lines:
|
|
243
|
-
{ id: 'toggle', name: 'Toggle', lines:
|
|
244
|
-
{ id: 'toggle-group', name: 'ToggleGroup', lines:
|
|
245
|
-
{ id: 'radio-group', name: 'RadioGroup', lines:
|
|
246
|
-
{ id: 'checkbox-group', name: 'CheckboxGroup', lines:
|
|
247
|
-
{ id: 'input', name: 'Input', lines:
|
|
248
|
-
{ id: 'number-field', name: 'NumberField', lines:
|
|
249
|
-
{ id: 'slider', name: 'Slider', lines:
|
|
250
|
-
{ id: 'otp-field', name: 'OTPField', lines:
|
|
251
|
-
{ id: 'date-picker', name: 'DatePicker', lines:
|
|
252
|
-
{ id: 'editable-value', name: 'EditableValue', lines:
|
|
253
|
-
{ id: 'tabs', name: 'Tabs', lines:
|
|
254
|
-
{ id: 'menu', name: 'Menu', lines:
|
|
255
|
-
{ id: 'context-menu', name: 'ContextMenu', lines:
|
|
256
|
-
{ id: 'menubar', name: 'Menubar', lines:
|
|
257
|
-
{ id: 'nav-menu', name: 'NavMenu', lines:
|
|
258
|
-
{ id: 'toolbar', name: 'Toolbar', lines:
|
|
259
|
-
{ id: 'dialog', name: 'Dialog', lines:
|
|
260
|
-
{ id: 'drawer', name: 'Drawer', lines:
|
|
261
|
-
{ id: 'popover', name: 'Popover', lines:
|
|
262
|
-
{ id: 'tooltip', name: 'Tooltip', lines:
|
|
263
|
-
{ id: 'preview-card', name: 'PreviewCard', lines:
|
|
264
|
-
{ id: 'toast', name: 'Toast', lines:
|
|
265
|
-
{ id: 'button', name: 'Button', lines:
|
|
266
|
-
{ id: 'separator', name: 'Separator', lines:
|
|
267
|
-
{ id: 'progress', name: 'Progress', lines:
|
|
268
|
-
{ id: 'meter', name: 'Meter', lines:
|
|
269
|
-
{ id: 'avatar', name: 'Avatar', lines:
|
|
270
|
-
{ id: 'scroll-area', name: 'ScrollArea', lines:
|
|
271
|
-
{ id: 'field', name: 'Field', lines:
|
|
272
|
-
{ id: 'fieldset', name: 'Fieldset', lines:
|
|
273
|
-
{ id: 'form', name: 'Form', lines:
|
|
274
|
-
{ id: 'grid', name: 'Grid', lines:
|
|
275
|
-
{ id: 'accordion', name: 'Accordion', lines:
|
|
283
|
+
{ id: 'select', name: 'Select', lines: 147, desc: 'Dropdown with typeahead, keyboard nav, ARIA listbox.', props: ['@value', '@placeholder', '@disabled'], events: ['change'], keys: ['↕', 'Enter', 'Space', 'Esc', 'Home', 'End', 'type-ahead'], attrs: ['$open', '$placeholder', '$disabled', '$value', '$highlighted', '$selected'] }
|
|
284
|
+
{ id: 'combobox', name: 'Combobox', lines: 124, desc: 'Filterable input + listbox for search-as-you-type.', props: ['@query', '@items', '@placeholder', '@disabled', '@autoHighlight'], events: ['filter', 'select'], keys: ['↕', 'Enter', 'Esc', 'Tab'], attrs: ['$open', '$disabled', '$clear', '$value', '$highlighted', '$empty'] }
|
|
285
|
+
{ id: 'multi-select', name: 'MultiSelect', lines: 130, desc: 'Multi-select with chips, filtering, and keyboard nav.', props: ['@value', '@items', '@placeholder', '@disabled'], events: ['change'], keys: ['↕', 'Enter', 'Esc', 'Backspace', 'Tab'], attrs: ['$open', '$disabled', '$chips', '$chip', '$remove', '$clear', '$highlighted', '$selected'] }
|
|
286
|
+
{ id: 'autocomplete', name: 'Autocomplete', lines: 115, desc: 'Suggestion input — type to filter, select to fill.', props: ['@value', '@items', '@placeholder', '@disabled'], events: ['select'], keys: ['↕', 'Enter', 'Esc', 'Tab'], attrs: ['$open', '$disabled', '$clear'] }
|
|
287
|
+
{ id: 'checkbox', name: 'Checkbox', lines: 18, desc: 'Toggle with checkbox or switch semantics.', props: ['@checked', '@disabled', '@indeterminate', '@switch'], events: ['change'], keys: [], attrs: ['$checked', '$indeterminate', '$disabled'] }
|
|
288
|
+
{ id: 'toggle', name: 'Toggle', lines: 13, desc: 'Two-state toggle button with pressed state.', props: ['@pressed', '@disabled'], events: ['change'], keys: [], attrs: ['$pressed', '$disabled'] }
|
|
289
|
+
{ id: 'toggle-group', name: 'ToggleGroup', lines: 59, desc: 'Single or multi-select toggle buttons.', props: ['@value', '@disabled', '@multiple', '@orientation'], events: ['change'], keys: ['← →', '↕', 'Home', 'End'], attrs: ['$orientation', '$disabled', '$pressed', '$value'] }
|
|
290
|
+
{ id: 'radio-group', name: 'RadioGroup', lines: 50, desc: 'Exactly one option selected with arrow key nav.', props: ['@value', '@disabled', '@orientation', '@name'], events: ['change'], keys: ['← →', '↕', 'Home', 'End'], attrs: ['$orientation', '$disabled', '$checked', '$value'] }
|
|
291
|
+
{ id: 'checkbox-group', name: 'CheckboxGroup', lines: 46, desc: 'Multiple options checked independently.', props: ['@value', '@disabled', '@orientation', '@label'], events: ['change'], keys: ['← →', '↕'], attrs: ['$orientation', '$disabled', '$checked', '$value'] }
|
|
292
|
+
{ id: 'input', name: 'Input', lines: 24, desc: 'Headless input tracking focus, touch, and validation.', props: ['@value', '@placeholder', '@type', '@disabled', '@required'], events: [], keys: [], attrs: ['$disabled', '$focused', '$touched'] }
|
|
293
|
+
{ id: 'number-field', name: 'NumberField', lines: 132, desc: 'Number input with stepper buttons and hold-to-repeat.', props: ['@value', '@min', '@max', '@step', '@disabled', '@readOnly'], events: ['input', 'change'], keys: ['↕', 'PgUp', 'PgDn', 'Home', 'End'], attrs: ['$disabled', '$readonly', '$decrement', '$increment'] }
|
|
294
|
+
{ id: 'slider', name: 'Slider', lines: 130, desc: 'Draggable range input with pointer capture and keyboard.', props: ['@value', '@min', '@max', '@step', '@orientation', '@disabled'], events: ['input', 'change'], keys: ['← →', '↕', 'PgUp', 'PgDn', 'Home', 'End'], attrs: ['$orientation', '$disabled', '$dragging', '$track', '$indicator', '$thumb', '$active'] }
|
|
295
|
+
{ id: 'otp-field', name: 'OTPField', lines: 72, desc: 'Multi-digit code input with auto-advance and paste.', props: ['@length', '@value', '@disabled', '@mask'], events: ['input', 'complete'], keys: ['← →', 'Backspace', 'Home', 'End', 'paste'], attrs: ['$disabled', '$complete', '$filled'] }
|
|
296
|
+
{ id: 'date-picker', name: 'DatePicker', lines: 172, desc: 'Calendar dropdown for single date or range selection.', props: ['@value', '@placeholder', '@disabled', '@range', '@firstDayOfWeek'], events: ['change'], keys: ['Esc', 'Enter', 'Space'], attrs: ['$open', '$disabled', '$range', '$calendar', '$selected', '$today', '$in-range'] }
|
|
297
|
+
{ id: 'editable-value', name: 'EditableValue', lines: 58, desc: 'Click-to-edit inline value with popover form.', props: ['@disabled'], events: ['save'], keys: ['Esc', 'Enter'], attrs: ['$editing', '$disabled', '$saving', '$edit-trigger'] }
|
|
298
|
+
{ id: 'tabs', name: 'Tabs', lines: 91, desc: 'Tab panel with roving tabindex and arrow key nav.', props: ['@active', '@orientation', '@activation'], events: ['change'], keys: ['← →', '↕', 'Home', 'End', 'Enter', 'Space'], attrs: ['$tab', '$panel', '$active', '$disabled'] }
|
|
299
|
+
{ id: 'menu', name: 'Menu', lines: 133, desc: 'Dropdown action menu with keyboard navigation.', props: ['@disabled'], events: ['select'], keys: ['↕', 'Home', 'End', 'Enter', 'Space', 'Esc', 'Tab', 'type-ahead'], attrs: ['$open', '$disabled', '$highlighted', '$value'] }
|
|
300
|
+
{ id: 'context-menu', name: 'ContextMenu', lines: 80, desc: 'Right-click context menu with keyboard navigation.', props: ['@disabled'], events: ['select'], keys: ['↕', 'Home', 'End', 'Enter', 'Space', 'Esc', 'Tab'], attrs: ['$open', '$highlighted', '$disabled', '$value'] }
|
|
301
|
+
{ id: 'menubar', name: 'Menubar', lines: 125, desc: 'Horizontal menu bar with dropdown menus.', props: ['@disabled'], events: ['select'], keys: ['← →', '↕', 'Enter', 'Space', 'Esc', 'Tab'], attrs: ['$disabled', '$open', '$highlighted', '$value'] }
|
|
302
|
+
{ id: 'nav-menu', name: 'NavMenu', lines: 99, desc: 'Site navigation with hover/click dropdown panels.', props: ['@orientation', '@hoverDelay', '@hoverCloseDelay'], events: [], keys: ['← →', '↓', 'Esc'], attrs: ['$orientation', '$open'] }
|
|
303
|
+
{ id: 'toolbar', name: 'Toolbar', lines: 31, desc: 'Groups controls with roving tabindex keyboard nav.', props: ['@orientation', '@label'], events: [], keys: ['← →', '↕', 'Home', 'End'], attrs: ['$orientation'] }
|
|
304
|
+
{ id: 'dialog', name: 'Dialog', lines: 83, desc: 'Modal with focus trap, scroll lock, escape dismiss.', props: ['@open', '@dismissable', '@initialFocus'], events: ['close'], keys: ['Esc', 'Tab'], attrs: ['$open'] }
|
|
305
|
+
{ id: 'drawer', name: 'Drawer', lines: 60, desc: 'Slide-out panel with focus trap and scroll lock.', props: ['@open', '@side', '@dismissable'], events: ['close'], keys: ['Esc', 'Tab'], attrs: ['$open', '$side'] }
|
|
306
|
+
{ id: 'popover', name: 'Popover', lines: 117, desc: 'Anchored floating content with flip/shift positioning.', props: ['@placement', '@offset', '@disabled', '@openOnHover', '@hoverDelay', '@hoverCloseDelay'], events: [], keys: ['Esc', 'Enter', 'Space', '↓'], attrs: ['$open', '$placement'] }
|
|
307
|
+
{ id: 'tooltip', name: 'Tooltip', lines: 92, desc: 'Hover/focus tooltip with delay and positioning.', props: ['@text', '@placement', '@delay', '@offset', '@hoverable'], events: [], keys: [], attrs: ['$open', '$entering', '$exiting', '$placement'] }
|
|
308
|
+
{ id: 'preview-card', name: 'PreviewCard', lines: 56, desc: 'Hover/focus preview card with delay.', props: ['@delay', '@closeDelay'], events: [], keys: [], attrs: ['$open'] }
|
|
309
|
+
{ id: 'toast', name: 'Toast', lines: 56, desc: 'Auto-dismiss notification with ARIA live region.', props: ['@toasts', '@toast', '@placement'], events: ['dismiss'], keys: [], attrs: ['$placement', '$type', '$leaving'] }
|
|
310
|
+
{ id: 'button', name: 'Button', lines: 10, desc: 'Accessible button with disabled-but-focusable pattern.', props: ['@disabled'], events: ['press'], keys: [], attrs: ['$disabled'] }
|
|
311
|
+
{ id: 'separator', name: 'Separator', lines: 7, desc: 'Decorative or semantic divider between sections.', props: ['@orientation', '@decorative'], events: [], keys: [], attrs: ['$orientation'] }
|
|
312
|
+
{ id: 'progress', name: 'Progress', lines: 14, desc: 'Progress bar with CSS custom property for value.', props: ['@value', '@max', '@label'], events: [], keys: [], attrs: ['$complete'] }
|
|
313
|
+
{ id: 'meter', name: 'Meter', lines: 23, desc: 'Gauge for known-range measurements with thresholds.', props: ['@value', '@min', '@max', '@low', '@high', '@optimum', '@label'], events: [], keys: [], attrs: ['$level'] }
|
|
314
|
+
{ id: 'avatar', name: 'Avatar', lines: 23, desc: 'Image with fallback to initials or placeholder.', props: ['@src', '@alt', '@fallback'], events: [], keys: [], attrs: ['$status', '$initials', '$placeholder'] }
|
|
315
|
+
{ id: 'scroll-area', name: 'ScrollArea', lines: 115, desc: 'Custom scrollbar with draggable thumb and auto-hide.', props: ['@orientation'], events: [], keys: [], attrs: ['$orientation', '$hovering', '$scrolling', '$dragging', '$viewport', '$scrollbar', '$thumb'] }
|
|
316
|
+
{ id: 'field', name: 'Field', lines: 39, desc: 'Form field wrapper with label, description, and error.', props: ['@label', '@description', '@error', '@disabled', '@required'], events: [], keys: [], attrs: ['$disabled', '$invalid', '$label', '$required', '$description', '$error'] }
|
|
317
|
+
{ id: 'fieldset', name: 'Fieldset', lines: 9, desc: 'Grouped fields with legend and cascading disable.', props: ['@legend', '@disabled'], events: [], keys: [], attrs: ['$disabled', '$legend'] }
|
|
318
|
+
{ id: 'form', name: 'Form', lines: 21, desc: 'Form wrapper with submit handling and validation state.', props: ['@disabled'], events: ['submit'], keys: [], attrs: ['$disabled', '$submitting', '$submitted'] }
|
|
319
|
+
{ id: 'grid', name: 'Grid', lines: 799, desc: 'Virtual-scrolling data grid — 100K+ rows at 60fps.', props: ['@data', '@columns', '@rowHeight', '@overscan', '@striped', '@beforeEdit', '@afterEdit'], events: [], keys: ['Arrows', 'Tab', 'Enter', 'F2', 'Esc', 'Home', 'End', 'PgUp', 'PgDn', 'Ctrl+A', 'Ctrl+C', 'Ctrl+V', 'Ctrl+X'], attrs: ['$editing', '$selecting', '$sorted'] }
|
|
320
|
+
{ id: 'accordion', name: 'Accordion', lines: 86, desc: 'Expand/collapse sections, single or multiple mode.', props: ['@multiple'], events: ['change'], keys: ['Enter', 'Space', '↕', 'Home', 'End'], attrs: ['$item', '$trigger', '$content', '$open', '$disabled'] }
|
|
321
|
+
{ id: 'badge', name: 'Badge', lines: 5, desc: 'Inline label with variant (solid/outline/subtle).', props: ['@variant'], events: [], keys: [], attrs: ['$variant'] }
|
|
322
|
+
{ id: 'skeleton', name: 'Skeleton', lines: 10, desc: 'Loading placeholder with shimmer animation.', props: ['@width', '@height', '@circle', '@label'], events: [], keys: [], attrs: ['$circle'] }
|
|
323
|
+
{ id: 'spinner', name: 'Spinner', lines: 6, desc: 'Loading indicator with accessible status.', props: ['@label', '@size'], events: [], keys: [], attrs: [] }
|
|
324
|
+
{ id: 'card', name: 'Card', lines: 6, desc: 'Structured container with header/content/footer.', props: ['@interactive'], events: [], keys: [], attrs: ['$interactive'] }
|
|
325
|
+
{ id: 'label', name: 'Label', lines: 6, desc: 'Standalone accessible form label.', props: ['@for', '@required'], events: [], keys: [], attrs: ['$required'] }
|
|
326
|
+
{ id: 'textarea', name: 'Textarea', lines: 33, desc: 'Auto-resizing text area with focus and validation tracking.', props: ['@value', '@placeholder', '@disabled', '@required', '@rows', '@autoResize'], events: [], keys: [], attrs: ['$disabled', '$focused', '$touched'] }
|
|
327
|
+
{ id: 'native-select', name: 'NativeSelect', lines: 18, desc: 'Styled native select element with state tracking.', props: ['@value', '@disabled', '@required'], events: ['change'], keys: [], attrs: ['$disabled', '$focused'] }
|
|
328
|
+
{ id: 'input-group', name: 'InputGroup', lines: 11, desc: 'Input with prefix/suffix addon elements.', props: ['@disabled'], events: [], keys: [], attrs: ['$disabled', '$focused'] }
|
|
329
|
+
{ id: 'button-group', name: 'ButtonGroup', lines: 11, desc: 'Grouped buttons with ARIA group semantics.', props: ['@orientation', '@disabled', '@label'], events: [], keys: [], attrs: ['$orientation', '$disabled'] }
|
|
330
|
+
{ id: 'alert-dialog', name: 'AlertDialog', lines: 74, desc: 'Non-dismissable modal requiring explicit user action.', props: ['@open', '@initialFocus'], events: ['close'], keys: ['Tab'], attrs: ['$open'] }
|
|
331
|
+
{ id: 'breadcrumb', name: 'Breadcrumb', lines: 25, desc: 'Navigation trail with separator and current page.', props: ['@separator', '@label'], events: [], keys: [], attrs: ['$current'] }
|
|
332
|
+
{ id: 'table', name: 'Table', lines: 9, desc: 'Semantic table wrapper with optional caption and striped rows.', props: ['@caption', '@striped'], events: [], keys: [], attrs: ['$striped'] }
|
|
333
|
+
{ id: 'collapsible', name: 'Collapsible', lines: 33, desc: 'Single open/close section with animated expand.', props: ['@open', '@disabled'], events: ['change'], keys: ['Enter', 'Space'], attrs: ['$open', '$disabled'] }
|
|
334
|
+
{ id: 'pagination', name: 'Pagination', lines: 96, desc: 'Page navigation with prev/next and ellipsis gaps.', props: ['@page', '@total', '@perPage', '@siblingCount'], events: ['change'], keys: ['← →', 'Home', 'End'], attrs: ['$active', '$disabled', '$ellipsis'] }
|
|
335
|
+
{ id: 'carousel', name: 'Carousel', lines: 78, desc: 'Slide carousel with autoplay, loop, and keyboard nav.', props: ['@orientation', '@loop', '@autoplay', '@interval', '@label'], events: ['change'], keys: ['← →', '↕', 'Home', 'End'], attrs: ['$orientation', '$active', '$prev', '$next'] }
|
|
336
|
+
{ id: 'resizable', name: 'Resizable', lines: 89, desc: 'Draggable resize handles between panels.', props: ['@orientation', '@minSize', '@maxSize'], events: ['resize'], keys: ['← →', '↕'], attrs: ['$orientation', '$dragging'] }
|
|
276
337
|
]
|
|
277
338
|
_infoName := ''
|
|
278
339
|
_infoDesc := ''
|
|
@@ -304,6 +365,7 @@ export WidgetGallery = component
|
|
|
304
365
|
lines = text.split('\n')
|
|
305
366
|
gutterEl.textContent = lines.map((_, i) -> String(i + 1)).join('\n') if gutterEl
|
|
306
367
|
codeEl.textContent = text
|
|
368
|
+
codeEl.className = 'source-code language-rip'
|
|
307
369
|
@_ensureHljs =>
|
|
308
370
|
hljs.highlightElement(codeEl) if window.hljs
|
|
309
371
|
, 0
|
|
@@ -350,13 +412,12 @@ export WidgetGallery = component
|
|
|
350
412
|
gridCellRef := ''
|
|
351
413
|
|
|
352
414
|
_updateGridRef: ->
|
|
353
|
-
cell = document.querySelector('.grid-container [data-active]')
|
|
415
|
+
cell = document.querySelector('.grid-container td[data-active]')
|
|
354
416
|
if cell
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
gridCellRef = "R#{ri + 1}:C#{ci + 1}" if ri >= 0 and ci >= 0
|
|
417
|
+
tr = cell.parentElement
|
|
418
|
+
rowNum = tr?.firstElementChild?.textContent?.trim()
|
|
419
|
+
ci = Array.from(tr.children).indexOf(cell)
|
|
420
|
+
gridCellRef = if rowNum then "R#{rowNum}:C#{ci + 1}" else ''
|
|
360
421
|
else
|
|
361
422
|
gridCellRef = ''
|
|
362
423
|
|
|
@@ -395,7 +456,7 @@ export WidgetGallery = component
|
|
|
395
456
|
{ _row: 12, name: 'Leo Martin', role: 'Engineer', age: 24, city: 'Boston' },
|
|
396
457
|
]
|
|
397
458
|
|
|
398
|
-
sectionIds =! ['select', 'combobox', 'multi-select', 'autocomplete', 'checkbox', 'toggle', 'toggle-group', 'radio-group', 'checkbox-group', 'input', 'number-field', 'slider', 'otp-field', 'date-picker', 'editable-value', 'tabs', 'menu', 'context-menu', 'menubar', 'nav-menu', 'toolbar', 'dialog', 'drawer', 'popover', 'tooltip', 'preview-card', 'toast', 'button', 'separator', 'progress', 'meter', 'avatar', 'scroll-area', 'field', 'form', 'grid', 'accordion']
|
|
459
|
+
sectionIds =! ['select', 'combobox', 'multi-select', 'autocomplete', 'checkbox', 'toggle', 'toggle-group', 'radio-group', 'checkbox-group', 'input', 'textarea', 'native-select', 'number-field', 'slider', 'otp-field', 'date-picker', 'editable-value', 'input-group', 'tabs', 'menu', 'context-menu', 'menubar', 'nav-menu', 'toolbar', 'breadcrumb', 'dialog', 'alert-dialog', 'drawer', 'popover', 'tooltip', 'preview-card', 'toast', 'button', 'badge', 'card', 'separator', 'progress', 'meter', 'spinner', 'skeleton', 'avatar', 'label', 'scroll-area', 'field', 'form', 'button-group', 'grid', 'accordion', 'table', 'collapsible', 'pagination', 'carousel', 'resizable']
|
|
399
460
|
|
|
400
461
|
_fadeTo: (el) ->
|
|
401
462
|
return unless el
|
|
@@ -438,7 +499,7 @@ export WidgetGallery = component
|
|
|
438
499
|
h1 "Rip UI"
|
|
439
500
|
button.theme-toggle @click: (=> @_toggleDark())
|
|
440
501
|
if darkMode then "☀" else "☾"
|
|
441
|
-
p "
|
|
502
|
+
p "54 headless, accessible components. Zero CSS, zero dependencies."
|
|
442
503
|
|
|
443
504
|
.toc
|
|
444
505
|
.toc-nav @keydown: @_onTocKeydown
|
|
@@ -459,11 +520,14 @@ export WidgetGallery = component
|
|
|
459
520
|
.toc-group
|
|
460
521
|
.toc-label "Input"
|
|
461
522
|
a @mouseenter: (=> tocActive = 'input'), @click: (=> tocActive = 'input'), href: "#input", $active: (tocActive is 'input')?!, "Input"
|
|
523
|
+
a @mouseenter: (=> tocActive = 'textarea'), @click: (=> tocActive = 'textarea'), href: "#textarea", $active: (tocActive is 'textarea')?!, "Textarea"
|
|
524
|
+
a @mouseenter: (=> tocActive = 'native-select'), @click: (=> tocActive = 'native-select'), href: "#native-select", $active: (tocActive is 'native-select')?!, "NativeSelect"
|
|
462
525
|
a @mouseenter: (=> tocActive = 'number-field'), @click: (=> tocActive = 'number-field'), href: "#number-field", $active: (tocActive is 'number-field')?!, "NumberField"
|
|
463
526
|
a @mouseenter: (=> tocActive = 'slider'), @click: (=> tocActive = 'slider'), href: "#slider", $active: (tocActive is 'slider')?!, "Slider"
|
|
464
527
|
a @mouseenter: (=> tocActive = 'otp-field'), @click: (=> tocActive = 'otp-field'), href: "#otp-field", $active: (tocActive is 'otp-field')?!, "OTPField"
|
|
465
528
|
a @mouseenter: (=> tocActive = 'date-picker'), @click: (=> tocActive = 'date-picker'), href: "#date-picker", $active: (tocActive is 'date-picker')?!, "DatePicker"
|
|
466
529
|
a @mouseenter: (=> tocActive = 'editable-value'), @click: (=> tocActive = 'editable-value'), href: "#editable-value", $active: (tocActive is 'editable-value')?!, "EditableValue"
|
|
530
|
+
a @mouseenter: (=> tocActive = 'input-group'), @click: (=> tocActive = 'input-group'), href: "#input-group", $active: (tocActive is 'input-group')?!, "InputGroup"
|
|
467
531
|
.toc-group
|
|
468
532
|
.toc-label "Navigation"
|
|
469
533
|
a @mouseenter: (=> tocActive = 'tabs'), @click: (=> tocActive = 'tabs'), href: "#tabs", $active: (tocActive is 'tabs')?!, "Tabs"
|
|
@@ -472,9 +536,11 @@ export WidgetGallery = component
|
|
|
472
536
|
a @mouseenter: (=> tocActive = 'menubar'), @click: (=> tocActive = 'menubar'), href: "#menubar", $active: (tocActive is 'menubar')?!, "Menubar"
|
|
473
537
|
a @mouseenter: (=> tocActive = 'nav-menu'), @click: (=> tocActive = 'nav-menu'), href: "#nav-menu", $active: (tocActive is 'nav-menu')?!, "NavMenu"
|
|
474
538
|
a @mouseenter: (=> tocActive = 'toolbar'), @click: (=> tocActive = 'toolbar'), href: "#toolbar", $active: (tocActive is 'toolbar')?!, "Toolbar"
|
|
539
|
+
a @mouseenter: (=> tocActive = 'breadcrumb'), @click: (=> tocActive = 'breadcrumb'), href: "#breadcrumb", $active: (tocActive is 'breadcrumb')?!, "Breadcrumb"
|
|
475
540
|
.toc-group
|
|
476
541
|
.toc-label "Overlay"
|
|
477
542
|
a @mouseenter: (=> tocActive = 'dialog'), @click: (=> tocActive = 'dialog'), href: "#dialog", $active: (tocActive is 'dialog')?!, "Dialog"
|
|
543
|
+
a @mouseenter: (=> tocActive = 'alert-dialog'), @click: (=> tocActive = 'alert-dialog'), href: "#alert-dialog", $active: (tocActive is 'alert-dialog')?!, "AlertDialog"
|
|
478
544
|
a @mouseenter: (=> tocActive = 'drawer'), @click: (=> tocActive = 'drawer'), href: "#drawer", $active: (tocActive is 'drawer')?!, "Drawer"
|
|
479
545
|
a @mouseenter: (=> tocActive = 'popover'), @click: (=> tocActive = 'popover'), href: "#popover", $active: (tocActive is 'popover')?!, "Popover"
|
|
480
546
|
a @mouseenter: (=> tocActive = 'tooltip'), @click: (=> tocActive = 'tooltip'), href: "#tooltip", $active: (tocActive is 'tooltip')?!, "Tooltip"
|
|
@@ -483,20 +549,33 @@ export WidgetGallery = component
|
|
|
483
549
|
.toc-group
|
|
484
550
|
.toc-label "Display"
|
|
485
551
|
a @mouseenter: (=> tocActive = 'button'), @click: (=> tocActive = 'button'), href: "#button", $active: (tocActive is 'button')?!, "Button"
|
|
552
|
+
a @mouseenter: (=> tocActive = 'badge'), @click: (=> tocActive = 'badge'), href: "#badge", $active: (tocActive is 'badge')?!, "Badge"
|
|
553
|
+
a @mouseenter: (=> tocActive = 'card'), @click: (=> tocActive = 'card'), href: "#card", $active: (tocActive is 'card')?!, "Card"
|
|
486
554
|
a @mouseenter: (=> tocActive = 'separator'), @click: (=> tocActive = 'separator'), href: "#separator", $active: (tocActive is 'separator')?!, "Separator"
|
|
487
555
|
a @mouseenter: (=> tocActive = 'progress'), @click: (=> tocActive = 'progress'), href: "#progress", $active: (tocActive is 'progress')?!, "Progress"
|
|
488
556
|
a @mouseenter: (=> tocActive = 'meter'), @click: (=> tocActive = 'meter'), href: "#meter", $active: (tocActive is 'meter')?!, "Meter"
|
|
557
|
+
a @mouseenter: (=> tocActive = 'spinner'), @click: (=> tocActive = 'spinner'), href: "#spinner", $active: (tocActive is 'spinner')?!, "Spinner"
|
|
558
|
+
a @mouseenter: (=> tocActive = 'skeleton'), @click: (=> tocActive = 'skeleton'), href: "#skeleton", $active: (tocActive is 'skeleton')?!, "Skeleton"
|
|
489
559
|
a @mouseenter: (=> tocActive = 'avatar'), @click: (=> tocActive = 'avatar'), href: "#avatar", $active: (tocActive is 'avatar')?!, "Avatar"
|
|
560
|
+
a @mouseenter: (=> tocActive = 'label'), @click: (=> tocActive = 'label'), href: "#label", $active: (tocActive is 'label')?!, "Label"
|
|
490
561
|
a @mouseenter: (=> tocActive = 'scroll-area'), @click: (=> tocActive = 'scroll-area'), href: "#scroll-area", $active: (tocActive is 'scroll-area')?!, "ScrollArea"
|
|
491
562
|
.toc-group
|
|
492
563
|
.toc-label "Form"
|
|
493
564
|
a @mouseenter: (=> tocActive = 'field'), @click: (=> tocActive = 'field'), href: "#field", $active: (tocActive is 'field')?!, "Field"
|
|
494
565
|
a @mouseenter: (=> tocActive = 'fieldset'), @click: (=> tocActive = 'fieldset'), href: "#fieldset", $active: (tocActive is 'fieldset')?!, "Fieldset"
|
|
495
566
|
a @mouseenter: (=> tocActive = 'form'), @click: (=> tocActive = 'form'), href: "#form", $active: (tocActive is 'form')?!, "Form"
|
|
567
|
+
a @mouseenter: (=> tocActive = 'button-group'), @click: (=> tocActive = 'button-group'), href: "#button-group", $active: (tocActive is 'button-group')?!, "ButtonGroup"
|
|
496
568
|
.toc-group
|
|
497
569
|
.toc-label "Data"
|
|
498
570
|
a @mouseenter: (=> tocActive = 'grid'), @click: (=> tocActive = 'grid'), href: "#grid", $active: (tocActive is 'grid')?!, "Grid"
|
|
499
571
|
a @mouseenter: (=> tocActive = 'accordion'), @click: (=> tocActive = 'accordion'), href: "#accordion", $active: (tocActive is 'accordion')?!, "Accordion"
|
|
572
|
+
a @mouseenter: (=> tocActive = 'table'), @click: (=> tocActive = 'table'), href: "#table", $active: (tocActive is 'table')?!, "Table"
|
|
573
|
+
a @mouseenter: (=> tocActive = 'collapsible'), @click: (=> tocActive = 'collapsible'), href: "#collapsible", $active: (tocActive is 'collapsible')?!, "Collapsible"
|
|
574
|
+
.toc-group
|
|
575
|
+
.toc-label "Interactive"
|
|
576
|
+
a @mouseenter: (=> tocActive = 'pagination'), @click: (=> tocActive = 'pagination'), href: "#pagination", $active: (tocActive is 'pagination')?!, "Pagination"
|
|
577
|
+
a @mouseenter: (=> tocActive = 'carousel'), @click: (=> tocActive = 'carousel'), href: "#carousel", $active: (tocActive is 'carousel')?!, "Carousel"
|
|
578
|
+
a @mouseenter: (=> tocActive = 'resizable'), @click: (=> tocActive = 'resizable'), href: "#resizable", $active: (tocActive is 'resizable')?!, "Resizable"
|
|
500
579
|
.toc-detail
|
|
501
580
|
if tocActive
|
|
502
581
|
.
|
|
@@ -529,16 +608,11 @@ export WidgetGallery = component
|
|
|
529
608
|
else
|
|
530
609
|
.toc-empty "← Hover a component to see its API"
|
|
531
610
|
|
|
532
|
-
#
|
|
611
|
+
# ========================================================================
|
|
533
612
|
# SELECT
|
|
534
|
-
#
|
|
613
|
+
# ========================================================================
|
|
535
614
|
.section id: "select"
|
|
536
|
-
|
|
537
|
-
span.badge @click: (=> @_viewSource('select')), "184 lines ❐"
|
|
538
|
-
.section-nav
|
|
539
|
-
a @click: (=> @_navSection('select', 'prev')), "‹"
|
|
540
|
-
a @click: (=> @_navSection('select', 'home')), "⌂"
|
|
541
|
-
a @click: (=> @_navSection('select', 'next')), "›"
|
|
615
|
+
SectionHead tag: "select", name: "Select", lines: 147
|
|
542
616
|
.section-desc "Dropdown with typeahead, keyboard nav, ARIA listbox."
|
|
543
617
|
.demo-row
|
|
544
618
|
.demo-label "Basic select"
|
|
@@ -582,16 +656,11 @@ export WidgetGallery = component
|
|
|
582
656
|
code "$highlighted"
|
|
583
657
|
code "$selected"
|
|
584
658
|
|
|
585
|
-
#
|
|
659
|
+
# ========================================================================
|
|
586
660
|
# COMBOBOX
|
|
587
|
-
#
|
|
661
|
+
# ========================================================================
|
|
588
662
|
.section id: "combobox"
|
|
589
|
-
|
|
590
|
-
span.badge @click: (=> @_viewSource('combobox')), "153 lines ❐"
|
|
591
|
-
.section-nav
|
|
592
|
-
a @click: (=> @_navSection('combobox', 'prev')), "‹"
|
|
593
|
-
a @click: (=> @_navSection('combobox', 'home')), "⌂"
|
|
594
|
-
a @click: (=> @_navSection('combobox', 'next')), "›"
|
|
663
|
+
SectionHead tag: "combobox", name: "Combobox", lines: 124
|
|
595
664
|
.section-desc "Filterable input + listbox for search-as-you-type."
|
|
596
665
|
.demo-row
|
|
597
666
|
.demo-label "Search fruits"
|
|
@@ -627,16 +696,11 @@ export WidgetGallery = component
|
|
|
627
696
|
code "$highlighted"
|
|
628
697
|
code "$empty"
|
|
629
698
|
|
|
630
|
-
#
|
|
699
|
+
# ========================================================================
|
|
631
700
|
# MULTI-SELECT
|
|
632
|
-
#
|
|
701
|
+
# ========================================================================
|
|
633
702
|
.section id: "multi-select"
|
|
634
|
-
|
|
635
|
-
span.badge @click: (=> @_viewSource('multi-select')), "158 lines ❐"
|
|
636
|
-
.section-nav
|
|
637
|
-
a @click: (=> @_navSection('multi-select', 'prev')), "‹"
|
|
638
|
-
a @click: (=> @_navSection('multi-select', 'home')), "⌂"
|
|
639
|
-
a @click: (=> @_navSection('multi-select', 'next')), "›"
|
|
703
|
+
SectionHead tag: "multi-select", name: "MultiSelect", lines: 130
|
|
640
704
|
.section-desc "Multi-select with chips, filtering, and keyboard navigation."
|
|
641
705
|
.demo-row
|
|
642
706
|
.demo-label "Pick colors"
|
|
@@ -671,16 +735,11 @@ export WidgetGallery = component
|
|
|
671
735
|
code "$highlighted"
|
|
672
736
|
code "$selected"
|
|
673
737
|
|
|
674
|
-
#
|
|
738
|
+
# ========================================================================
|
|
675
739
|
# AUTOCOMPLETE
|
|
676
|
-
#
|
|
740
|
+
# ========================================================================
|
|
677
741
|
.section id: "autocomplete"
|
|
678
|
-
|
|
679
|
-
span.badge @click: (=> @_viewSource('autocomplete')), "141 lines ❐"
|
|
680
|
-
.section-nav
|
|
681
|
-
a @click: (=> @_navSection('autocomplete', 'prev')), "‹"
|
|
682
|
-
a @click: (=> @_navSection('autocomplete', 'home')), "⌂"
|
|
683
|
-
a @click: (=> @_navSection('autocomplete', 'next')), "›"
|
|
742
|
+
SectionHead tag: "autocomplete", name: "Autocomplete", lines: 115
|
|
684
743
|
.section-desc "Suggestion input — type to filter, select to fill."
|
|
685
744
|
.demo-row
|
|
686
745
|
.demo-label "Search cities"
|
|
@@ -709,16 +768,11 @@ export WidgetGallery = component
|
|
|
709
768
|
code "$disabled"
|
|
710
769
|
code "$clear"
|
|
711
770
|
|
|
712
|
-
#
|
|
771
|
+
# ========================================================================
|
|
713
772
|
# CHECKBOX
|
|
714
|
-
#
|
|
773
|
+
# ========================================================================
|
|
715
774
|
.section id: "checkbox"
|
|
716
|
-
|
|
717
|
-
span.badge @click: (=> @_viewSource('checkbox')), "33 lines ❐"
|
|
718
|
-
.section-nav
|
|
719
|
-
a @click: (=> @_navSection('checkbox', 'prev')), "‹"
|
|
720
|
-
a @click: (=> @_navSection('checkbox', 'home')), "⌂"
|
|
721
|
-
a @click: (=> @_navSection('checkbox', 'next')), "›"
|
|
775
|
+
SectionHead tag: "checkbox", name: "Checkbox", lines: 18
|
|
722
776
|
.section-desc "Toggle with checkbox or switch semantics. Supports indeterminate."
|
|
723
777
|
.demo-row
|
|
724
778
|
.demo-label "Checkbox (unchecked)"
|
|
@@ -752,16 +806,11 @@ export WidgetGallery = component
|
|
|
752
806
|
code "$indeterminate"
|
|
753
807
|
code "$disabled"
|
|
754
808
|
|
|
755
|
-
#
|
|
809
|
+
# ========================================================================
|
|
756
810
|
# TOGGLE
|
|
757
|
-
#
|
|
811
|
+
# ========================================================================
|
|
758
812
|
.section id: "toggle"
|
|
759
|
-
|
|
760
|
-
span.badge @click: (=> @_viewSource('toggle')), "24 lines ❐"
|
|
761
|
-
.section-nav
|
|
762
|
-
a @click: (=> @_navSection('toggle', 'prev')), "‹"
|
|
763
|
-
a @click: (=> @_navSection('toggle', 'home')), "⌂"
|
|
764
|
-
a @click: (=> @_navSection('toggle', 'next')), "›"
|
|
813
|
+
SectionHead tag: "toggle", name: "Toggle", lines: 13
|
|
765
814
|
.section-desc "Stateful toggle button with pressed state."
|
|
766
815
|
.demo-row
|
|
767
816
|
.demo-label "Tap to toggle"
|
|
@@ -782,16 +831,11 @@ export WidgetGallery = component
|
|
|
782
831
|
code "$pressed"
|
|
783
832
|
code "$disabled"
|
|
784
833
|
|
|
785
|
-
#
|
|
834
|
+
# ========================================================================
|
|
786
835
|
# TOGGLE GROUP
|
|
787
|
-
#
|
|
836
|
+
# ========================================================================
|
|
788
837
|
.section id: "toggle-group"
|
|
789
|
-
|
|
790
|
-
span.badge @click: (=> @_viewSource('toggle-group')), "78 lines ❐"
|
|
791
|
-
.section-nav
|
|
792
|
-
a @click: (=> @_navSection('toggle-group', 'prev')), "‹"
|
|
793
|
-
a @click: (=> @_navSection('toggle-group', 'home')), "⌂"
|
|
794
|
-
a @click: (=> @_navSection('toggle-group', 'next')), "›"
|
|
838
|
+
SectionHead tag: "toggle-group", name: "ToggleGroup", lines: 59
|
|
795
839
|
.section-desc "Single or multi-select toggle buttons."
|
|
796
840
|
.demo-row
|
|
797
841
|
.demo-label "Text alignment"
|
|
@@ -831,16 +875,11 @@ export WidgetGallery = component
|
|
|
831
875
|
code "$pressed"
|
|
832
876
|
code "$value"
|
|
833
877
|
|
|
834
|
-
#
|
|
878
|
+
# ========================================================================
|
|
835
879
|
# RADIO GROUP
|
|
836
|
-
#
|
|
880
|
+
# ========================================================================
|
|
837
881
|
.section id: "radio-group"
|
|
838
|
-
|
|
839
|
-
span.badge @click: (=> @_viewSource('radio-group')), "67 lines ❐"
|
|
840
|
-
.section-nav
|
|
841
|
-
a @click: (=> @_navSection('radio-group', 'prev')), "‹"
|
|
842
|
-
a @click: (=> @_navSection('radio-group', 'home')), "⌂"
|
|
843
|
-
a @click: (=> @_navSection('radio-group', 'next')), "›"
|
|
882
|
+
SectionHead tag: "radio-group", name: "RadioGroup", lines: 50
|
|
844
883
|
.section-desc "Exactly one option selected. Arrow keys move focus and selection."
|
|
845
884
|
.demo-row
|
|
846
885
|
.demo-label "Font size"
|
|
@@ -873,16 +912,11 @@ export WidgetGallery = component
|
|
|
873
912
|
code "$checked"
|
|
874
913
|
code "$value"
|
|
875
914
|
|
|
876
|
-
#
|
|
915
|
+
# ========================================================================
|
|
877
916
|
# CHECKBOX GROUP
|
|
878
|
-
#
|
|
917
|
+
# ========================================================================
|
|
879
918
|
.section id: "checkbox-group"
|
|
880
|
-
|
|
881
|
-
span.badge @click: (=> @_viewSource('checkbox-group')), "65 lines ❐"
|
|
882
|
-
.section-nav
|
|
883
|
-
a @click: (=> @_navSection('checkbox-group', 'prev')), "‹"
|
|
884
|
-
a @click: (=> @_navSection('checkbox-group', 'home')), "⌂"
|
|
885
|
-
a @click: (=> @_navSection('checkbox-group', 'next')), "›"
|
|
919
|
+
SectionHead tag: "checkbox-group", name: "CheckboxGroup", lines: 46
|
|
886
920
|
.section-desc "Multiple options checked independently."
|
|
887
921
|
.demo-row
|
|
888
922
|
.demo-label "Toppings"
|
|
@@ -914,16 +948,11 @@ export WidgetGallery = component
|
|
|
914
948
|
code "$checked"
|
|
915
949
|
code "$value"
|
|
916
950
|
|
|
917
|
-
#
|
|
951
|
+
# ========================================================================
|
|
918
952
|
# INPUT
|
|
919
|
-
#
|
|
953
|
+
# ========================================================================
|
|
920
954
|
.section id: "input"
|
|
921
|
-
|
|
922
|
-
span.badge @click: (=> @_viewSource('input')), "35 lines ❐"
|
|
923
|
-
.section-nav
|
|
924
|
-
a @click: (=> @_navSection('input', 'prev')), "‹"
|
|
925
|
-
a @click: (=> @_navSection('input', 'home')), "⌂"
|
|
926
|
-
a @click: (=> @_navSection('input', 'next')), "›"
|
|
955
|
+
SectionHead tag: "input", name: "Input", lines: 24
|
|
927
956
|
.section-desc "Headless input tracking focus, touch, and validation state."
|
|
928
957
|
.demo-row
|
|
929
958
|
.demo-label "Text input"
|
|
@@ -944,16 +973,11 @@ export WidgetGallery = component
|
|
|
944
973
|
code "$focused"
|
|
945
974
|
code "$touched"
|
|
946
975
|
|
|
947
|
-
#
|
|
976
|
+
# ========================================================================
|
|
948
977
|
# NUMBER FIELD
|
|
949
|
-
#
|
|
978
|
+
# ========================================================================
|
|
950
979
|
.section id: "number-field"
|
|
951
|
-
|
|
952
|
-
span.badge @click: (=> @_viewSource('number-field')), "162 lines ❐"
|
|
953
|
-
.section-nav
|
|
954
|
-
a @click: (=> @_navSection('number-field', 'prev')), "‹"
|
|
955
|
-
a @click: (=> @_navSection('number-field', 'home')), "⌂"
|
|
956
|
-
a @click: (=> @_navSection('number-field', 'next')), "›"
|
|
980
|
+
SectionHead tag: "number-field", name: "NumberField", lines: 132
|
|
957
981
|
.section-desc "Number input with increment/decrement buttons, hold-to-repeat, and keyboard stepping."
|
|
958
982
|
.demo-row
|
|
959
983
|
.demo-label "Quantity (1-99)"
|
|
@@ -993,16 +1017,11 @@ export WidgetGallery = component
|
|
|
993
1017
|
code "$decrement"
|
|
994
1018
|
code "$increment"
|
|
995
1019
|
|
|
996
|
-
#
|
|
1020
|
+
# ========================================================================
|
|
997
1021
|
# SLIDER
|
|
998
|
-
#
|
|
1022
|
+
# ========================================================================
|
|
999
1023
|
.section id: "slider"
|
|
1000
|
-
|
|
1001
|
-
span.badge @click: (=> @_viewSource('slider')), "165 lines ❐"
|
|
1002
|
-
.section-nav
|
|
1003
|
-
a @click: (=> @_navSection('slider', 'prev')), "‹"
|
|
1004
|
-
a @click: (=> @_navSection('slider', 'home')), "⌂"
|
|
1005
|
-
a @click: (=> @_navSection('slider', 'next')), "›"
|
|
1024
|
+
SectionHead tag: "slider", name: "Slider", lines: 130
|
|
1006
1025
|
.section-desc "Draggable range input with pointer capture and keyboard stepping."
|
|
1007
1026
|
.demo-row
|
|
1008
1027
|
.demo-label "Single thumb"
|
|
@@ -1046,16 +1065,11 @@ export WidgetGallery = component
|
|
|
1046
1065
|
code "$thumb"
|
|
1047
1066
|
code "$active"
|
|
1048
1067
|
|
|
1049
|
-
#
|
|
1068
|
+
# ========================================================================
|
|
1050
1069
|
# OTP FIELD
|
|
1051
|
-
#
|
|
1070
|
+
# ========================================================================
|
|
1052
1071
|
.section id: "otp-field"
|
|
1053
|
-
|
|
1054
|
-
span.badge @click: (=> @_viewSource('otp-field')), "89 lines ❐"
|
|
1055
|
-
.section-nav
|
|
1056
|
-
a @click: (=> @_navSection('otp-field', 'prev')), "‹"
|
|
1057
|
-
a @click: (=> @_navSection('otp-field', 'home')), "⌂"
|
|
1058
|
-
a @click: (=> @_navSection('otp-field', 'next')), "›"
|
|
1072
|
+
SectionHead tag: "otp-field", name: "OTPField", lines: 72
|
|
1059
1073
|
.section-desc "Multi-digit code input with auto-advance, backspace nav, and paste."
|
|
1060
1074
|
.demo-row
|
|
1061
1075
|
.demo-label "6-digit code"
|
|
@@ -1089,16 +1103,11 @@ export WidgetGallery = component
|
|
|
1089
1103
|
code "$complete"
|
|
1090
1104
|
code "$filled"
|
|
1091
1105
|
|
|
1092
|
-
#
|
|
1106
|
+
# ========================================================================
|
|
1093
1107
|
# DATE PICKER
|
|
1094
|
-
#
|
|
1108
|
+
# ========================================================================
|
|
1095
1109
|
.section id: "date-picker"
|
|
1096
|
-
|
|
1097
|
-
span.badge @click: (=> @_viewSource('date-picker')), "214 lines ❐"
|
|
1098
|
-
.section-nav
|
|
1099
|
-
a @click: (=> @_navSection('date-picker', 'prev')), "‹"
|
|
1100
|
-
a @click: (=> @_navSection('date-picker', 'home')), "⌂"
|
|
1101
|
-
a @click: (=> @_navSection('date-picker', 'next')), "›"
|
|
1110
|
+
SectionHead tag: "date-picker", name: "DatePicker", lines: 172
|
|
1102
1111
|
.section-desc "Calendar dropdown for single date or range selection."
|
|
1103
1112
|
.demo-row
|
|
1104
1113
|
.demo-label "Single date"
|
|
@@ -1135,16 +1144,11 @@ export WidgetGallery = component
|
|
|
1135
1144
|
code "$today"
|
|
1136
1145
|
code "$in-range"
|
|
1137
1146
|
|
|
1138
|
-
#
|
|
1147
|
+
# ========================================================================
|
|
1139
1148
|
# EDITABLE VALUE
|
|
1140
|
-
#
|
|
1149
|
+
# ========================================================================
|
|
1141
1150
|
.section id: "editable-value"
|
|
1142
|
-
|
|
1143
|
-
span.badge @click: (=> @_viewSource('editable-value')), "80 lines ❐"
|
|
1144
|
-
.section-nav
|
|
1145
|
-
a @click: (=> @_navSection('editable-value', 'prev')), "‹"
|
|
1146
|
-
a @click: (=> @_navSection('editable-value', 'home')), "⌂"
|
|
1147
|
-
a @click: (=> @_navSection('editable-value', 'next')), "›"
|
|
1151
|
+
SectionHead tag: "editable-value", name: "EditableValue", lines: 58
|
|
1148
1152
|
.section-desc "Click the edit icon to modify the value inline."
|
|
1149
1153
|
.demo-row
|
|
1150
1154
|
EditableValue @save: (=> editName = editName)
|
|
@@ -1172,16 +1176,92 @@ export WidgetGallery = component
|
|
|
1172
1176
|
code "$saving"
|
|
1173
1177
|
code "$edit-trigger"
|
|
1174
1178
|
|
|
1175
|
-
#
|
|
1179
|
+
# ========================================================================
|
|
1180
|
+
# TEXTAREA
|
|
1181
|
+
# ========================================================================
|
|
1182
|
+
.section id: "textarea"
|
|
1183
|
+
SectionHead tag: "textarea", name: "Textarea", lines: 33
|
|
1184
|
+
.section-desc "Auto-resizing text area with focus and validation tracking."
|
|
1185
|
+
.demo-row
|
|
1186
|
+
.demo-label "Auto-resize textarea"
|
|
1187
|
+
Textarea value <=> textareaVal, placeholder: "Type something...", autoResize: true
|
|
1188
|
+
.status "length: #{textareaVal.length}"
|
|
1189
|
+
.api
|
|
1190
|
+
dl
|
|
1191
|
+
dt "Props"
|
|
1192
|
+
dd
|
|
1193
|
+
code "@value"
|
|
1194
|
+
code "@placeholder"
|
|
1195
|
+
code "@disabled"
|
|
1196
|
+
code "@required"
|
|
1197
|
+
code "@rows"
|
|
1198
|
+
code "@autoResize"
|
|
1199
|
+
dt "Data"
|
|
1200
|
+
dd
|
|
1201
|
+
code "$disabled"
|
|
1202
|
+
code "$focused"
|
|
1203
|
+
code "$touched"
|
|
1204
|
+
|
|
1205
|
+
# ========================================================================
|
|
1206
|
+
# NATIVE SELECT
|
|
1207
|
+
# ========================================================================
|
|
1208
|
+
.section id: "native-select"
|
|
1209
|
+
SectionHead tag: "native-select", name: "NativeSelect", lines: 18
|
|
1210
|
+
.section-desc "Native browser select element with state tracking."
|
|
1211
|
+
.demo-row.native-select-demo
|
|
1212
|
+
.demo-label "Choose a color"
|
|
1213
|
+
NativeSelect value <=> nativeSelectVal
|
|
1214
|
+
option value: "", "Pick one..."
|
|
1215
|
+
option value: "red", "Red"
|
|
1216
|
+
option value: "green", "Green"
|
|
1217
|
+
option value: "blue", "Blue"
|
|
1218
|
+
.status "value: '#{nativeSelectVal}'"
|
|
1219
|
+
.api
|
|
1220
|
+
dl
|
|
1221
|
+
dt "Props"
|
|
1222
|
+
dd
|
|
1223
|
+
code "@value"
|
|
1224
|
+
code "@disabled"
|
|
1225
|
+
code "@required"
|
|
1226
|
+
dt "Events"
|
|
1227
|
+
dd
|
|
1228
|
+
code "change"
|
|
1229
|
+
dt "Data"
|
|
1230
|
+
dd
|
|
1231
|
+
code "$disabled"
|
|
1232
|
+
code "$focused"
|
|
1233
|
+
|
|
1234
|
+
# ========================================================================
|
|
1235
|
+
# INPUT GROUP
|
|
1236
|
+
# ========================================================================
|
|
1237
|
+
.section id: "input-group"
|
|
1238
|
+
SectionHead tag: "input-group", name: "InputGroup", lines: 11
|
|
1239
|
+
.section-desc "Input with prefix/suffix addon elements."
|
|
1240
|
+
.demo-row.input-group-demo
|
|
1241
|
+
.demo-label "With prefix"
|
|
1242
|
+
InputGroup
|
|
1243
|
+
span $prefix: true, "$"
|
|
1244
|
+
input type: "text", placeholder: "Amount"
|
|
1245
|
+
.demo-row.input-group-demo
|
|
1246
|
+
.demo-label "With suffix"
|
|
1247
|
+
InputGroup
|
|
1248
|
+
input type: "text", placeholder: "Search..."
|
|
1249
|
+
button $suffix: true, "Go"
|
|
1250
|
+
.api
|
|
1251
|
+
dl
|
|
1252
|
+
dt "Props"
|
|
1253
|
+
dd
|
|
1254
|
+
code "@disabled"
|
|
1255
|
+
dt "Data"
|
|
1256
|
+
dd
|
|
1257
|
+
code "$disabled"
|
|
1258
|
+
code "$focused"
|
|
1259
|
+
|
|
1260
|
+
# ========================================================================
|
|
1176
1261
|
# TABS
|
|
1177
|
-
#
|
|
1262
|
+
# ========================================================================
|
|
1178
1263
|
.section id: "tabs"
|
|
1179
|
-
|
|
1180
|
-
span.badge @click: (=> @_viewSource('tabs')), "124 lines ❐"
|
|
1181
|
-
.section-nav
|
|
1182
|
-
a @click: (=> @_navSection('tabs', 'prev')), "‹"
|
|
1183
|
-
a @click: (=> @_navSection('tabs', 'home')), "⌂"
|
|
1184
|
-
a @click: (=> @_navSection('tabs', 'next')), "›"
|
|
1264
|
+
SectionHead tag: "tabs", name: "Tabs", lines: 91
|
|
1185
1265
|
.section-desc "Tab panel with roving tabindex and arrow key navigation."
|
|
1186
1266
|
.demo-row
|
|
1187
1267
|
.demo-label "Basic tabs"
|
|
@@ -1221,16 +1301,11 @@ export WidgetGallery = component
|
|
|
1221
1301
|
code "$active"
|
|
1222
1302
|
code "$disabled"
|
|
1223
1303
|
|
|
1224
|
-
#
|
|
1304
|
+
# ========================================================================
|
|
1225
1305
|
# MENU
|
|
1226
|
-
#
|
|
1306
|
+
# ========================================================================
|
|
1227
1307
|
.section id: "menu"
|
|
1228
|
-
|
|
1229
|
-
span.badge @click: (=> @_viewSource('menu')), "162 lines ❐"
|
|
1230
|
-
.section-nav
|
|
1231
|
-
a @click: (=> @_navSection('menu', 'prev')), "‹"
|
|
1232
|
-
a @click: (=> @_navSection('menu', 'home')), "⌂"
|
|
1233
|
-
a @click: (=> @_navSection('menu', 'next')), "›"
|
|
1308
|
+
SectionHead tag: "menu", name: "Menu", lines: 133
|
|
1234
1309
|
.section-desc "Dropdown action menu with keyboard navigation."
|
|
1235
1310
|
.demo-row
|
|
1236
1311
|
.demo-label "Click to open menu"
|
|
@@ -1266,16 +1341,11 @@ export WidgetGallery = component
|
|
|
1266
1341
|
code "$highlighted"
|
|
1267
1342
|
code "$value"
|
|
1268
1343
|
|
|
1269
|
-
#
|
|
1344
|
+
# ========================================================================
|
|
1270
1345
|
# CONTEXT MENU
|
|
1271
|
-
#
|
|
1346
|
+
# ========================================================================
|
|
1272
1347
|
.section id: "context-menu"
|
|
1273
|
-
|
|
1274
|
-
span.badge @click: (=> @_viewSource('context-menu')), "98 lines ❐"
|
|
1275
|
-
.section-nav
|
|
1276
|
-
a @click: (=> @_navSection('context-menu', 'prev')), "‹"
|
|
1277
|
-
a @click: (=> @_navSection('context-menu', 'home')), "⌂"
|
|
1278
|
-
a @click: (=> @_navSection('context-menu', 'next')), "›"
|
|
1348
|
+
SectionHead tag: "context-menu", name: "ContextMenu", lines: 80
|
|
1279
1349
|
.section-desc "Right-click the dashed area to open a context menu."
|
|
1280
1350
|
ContextMenu
|
|
1281
1351
|
div $trigger: true
|
|
@@ -1308,16 +1378,11 @@ export WidgetGallery = component
|
|
|
1308
1378
|
code "$disabled"
|
|
1309
1379
|
code "$value"
|
|
1310
1380
|
|
|
1311
|
-
#
|
|
1381
|
+
# ========================================================================
|
|
1312
1382
|
# MENUBAR
|
|
1313
|
-
#
|
|
1383
|
+
# ========================================================================
|
|
1314
1384
|
.section id: "menubar"
|
|
1315
|
-
|
|
1316
|
-
span.badge @click: (=> @_viewSource('menubar')), "155 lines ❐"
|
|
1317
|
-
.section-nav
|
|
1318
|
-
a @click: (=> @_navSection('menubar', 'prev')), "‹"
|
|
1319
|
-
a @click: (=> @_navSection('menubar', 'home')), "⌂"
|
|
1320
|
-
a @click: (=> @_navSection('menubar', 'next')), "›"
|
|
1385
|
+
SectionHead tag: "menubar", name: "Menubar", lines: 125
|
|
1321
1386
|
.section-desc "Horizontal menu bar with dropdown menus."
|
|
1322
1387
|
.demo-row
|
|
1323
1388
|
Menubar
|
|
@@ -1355,16 +1420,11 @@ export WidgetGallery = component
|
|
|
1355
1420
|
code "$highlighted"
|
|
1356
1421
|
code "$value"
|
|
1357
1422
|
|
|
1358
|
-
#
|
|
1423
|
+
# ========================================================================
|
|
1359
1424
|
# NAVIGATION MENU
|
|
1360
|
-
#
|
|
1425
|
+
# ========================================================================
|
|
1361
1426
|
.section id: "nav-menu"
|
|
1362
|
-
|
|
1363
|
-
span.badge @click: (=> @_viewSource('nav-menu')), "132 lines ❐"
|
|
1364
|
-
.section-nav
|
|
1365
|
-
a @click: (=> @_navSection('nav-menu', 'prev')), "‹"
|
|
1366
|
-
a @click: (=> @_navSection('nav-menu', 'home')), "⌂"
|
|
1367
|
-
a @click: (=> @_navSection('nav-menu', 'next')), "›"
|
|
1427
|
+
SectionHead tag: "nav-menu", name: "NavigationMenu", lines: 99
|
|
1368
1428
|
.section-desc "Site navigation with dropdown panels."
|
|
1369
1429
|
.demo-row
|
|
1370
1430
|
NavigationMenu
|
|
@@ -1399,16 +1459,11 @@ export WidgetGallery = component
|
|
|
1399
1459
|
code "$orientation"
|
|
1400
1460
|
code "$open"
|
|
1401
1461
|
|
|
1402
|
-
#
|
|
1462
|
+
# ========================================================================
|
|
1403
1463
|
# TOOLBAR
|
|
1404
|
-
#
|
|
1464
|
+
# ========================================================================
|
|
1405
1465
|
.section id: "toolbar"
|
|
1406
|
-
|
|
1407
|
-
span.badge @click: (=> @_viewSource('toolbar')), "46 lines ❐"
|
|
1408
|
-
.section-nav
|
|
1409
|
-
a @click: (=> @_navSection('toolbar', 'prev')), "‹"
|
|
1410
|
-
a @click: (=> @_navSection('toolbar', 'home')), "⌂"
|
|
1411
|
-
a @click: (=> @_navSection('toolbar', 'next')), "›"
|
|
1466
|
+
SectionHead tag: "toolbar", name: "Toolbar", lines: 31
|
|
1412
1467
|
.section-desc "Groups controls with roving tabindex keyboard navigation."
|
|
1413
1468
|
.demo-row
|
|
1414
1469
|
.demo-label "Text"
|
|
@@ -1462,17 +1517,35 @@ export WidgetGallery = component
|
|
|
1462
1517
|
dd
|
|
1463
1518
|
code "$orientation"
|
|
1464
1519
|
|
|
1465
|
-
#
|
|
1520
|
+
# ========================================================================
|
|
1521
|
+
# BREADCRUMB
|
|
1522
|
+
# ========================================================================
|
|
1523
|
+
.section id: "breadcrumb"
|
|
1524
|
+
SectionHead tag: "breadcrumb", name: "Breadcrumb", lines: 25
|
|
1525
|
+
.section-desc "Navigation trail with separator and current page."
|
|
1526
|
+
.demo-row
|
|
1527
|
+
.demo-label "Basic breadcrumb"
|
|
1528
|
+
Breadcrumb
|
|
1529
|
+
a $item: true, href: "#breadcrumb", "Home"
|
|
1530
|
+
a $item: true, href: "#breadcrumb", "Products"
|
|
1531
|
+
a $item: true, href: "#breadcrumb", "Widgets"
|
|
1532
|
+
span $item: true, "Widget Pro"
|
|
1533
|
+
.api
|
|
1534
|
+
dl
|
|
1535
|
+
dt "Props"
|
|
1536
|
+
dd
|
|
1537
|
+
code "@separator"
|
|
1538
|
+
code "@label"
|
|
1539
|
+
dt "Data"
|
|
1540
|
+
dd
|
|
1541
|
+
code "$current"
|
|
1542
|
+
|
|
1543
|
+
# ========================================================================
|
|
1466
1544
|
# DIALOG
|
|
1467
|
-
#
|
|
1545
|
+
# ========================================================================
|
|
1468
1546
|
.section id: "dialog"
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
.section-nav
|
|
1472
|
-
a @click: (=> @_navSection('dialog', 'prev')), "‹"
|
|
1473
|
-
a @click: (=> @_navSection('dialog', 'home')), "⌂"
|
|
1474
|
-
a @click: (=> @_navSection('dialog', 'next')), "›"
|
|
1475
|
-
.section-desc "Modal with focus trap, scroll lock, escape/click-outside dismiss."
|
|
1547
|
+
SectionHead tag: "dialog", name: "Dialog", lines: 83
|
|
1548
|
+
.section-desc "Modal with focus trap and scroll lock. Press Escape or click outside to dismiss."
|
|
1476
1549
|
.demo-row
|
|
1477
1550
|
.demo-label "Click to open"
|
|
1478
1551
|
button.demo-btn @click: (=> showDialog = true)
|
|
@@ -1505,16 +1578,47 @@ export WidgetGallery = component
|
|
|
1505
1578
|
dd
|
|
1506
1579
|
code "$open"
|
|
1507
1580
|
|
|
1508
|
-
#
|
|
1581
|
+
# ========================================================================
|
|
1582
|
+
# ALERT DIALOG
|
|
1583
|
+
# ========================================================================
|
|
1584
|
+
.section id: "alert-dialog"
|
|
1585
|
+
SectionHead tag: "alert-dialog", name: "AlertDialog", lines: 74
|
|
1586
|
+
.section-desc "Non-dismissable modal — Escape and click-outside are blocked. User must choose an action."
|
|
1587
|
+
.demo-row
|
|
1588
|
+
.demo-label "Requires explicit action"
|
|
1589
|
+
button.demo-btn @click: (=> showAlertDialog = true)
|
|
1590
|
+
"Delete Account"
|
|
1591
|
+
.status "open: #{showAlertDialog}"
|
|
1592
|
+
AlertDialog open <=> showAlertDialog
|
|
1593
|
+
.dialog-panel
|
|
1594
|
+
h2 style: "font-size:18px;font-weight:600;margin-bottom:8px", "Delete Account?"
|
|
1595
|
+
p.dialog-desc "This action is permanent and cannot be undone."
|
|
1596
|
+
. style: "display:flex;gap:8px;justify-content:flex-end"
|
|
1597
|
+
button.demo-btn @click: (=> showAlertDialog = false)
|
|
1598
|
+
"Cancel"
|
|
1599
|
+
button style: "padding:6px 16px;border:none;border-radius:6px;background:#dc2626;color:white;font-weight:600", @click: (=> showAlertDialog = false)
|
|
1600
|
+
"Delete"
|
|
1601
|
+
.api
|
|
1602
|
+
dl
|
|
1603
|
+
dt "Props"
|
|
1604
|
+
dd
|
|
1605
|
+
code "@open"
|
|
1606
|
+
code "@initialFocus"
|
|
1607
|
+
dt "Events"
|
|
1608
|
+
dd
|
|
1609
|
+
code "close"
|
|
1610
|
+
dt "Keyboard"
|
|
1611
|
+
dd
|
|
1612
|
+
kbd "Tab"
|
|
1613
|
+
dt "Data"
|
|
1614
|
+
dd
|
|
1615
|
+
code "$open"
|
|
1616
|
+
|
|
1617
|
+
# ========================================================================
|
|
1509
1618
|
# DRAWER
|
|
1510
|
-
#
|
|
1619
|
+
# ========================================================================
|
|
1511
1620
|
.section id: "drawer"
|
|
1512
|
-
|
|
1513
|
-
span.badge @click: (=> @_viewSource('drawer')), "79 lines ❐"
|
|
1514
|
-
.section-nav
|
|
1515
|
-
a @click: (=> @_navSection('drawer', 'prev')), "‹"
|
|
1516
|
-
a @click: (=> @_navSection('drawer', 'home')), "⌂"
|
|
1517
|
-
a @click: (=> @_navSection('drawer', 'next')), "›"
|
|
1621
|
+
SectionHead tag: "drawer", name: "Drawer", lines: 60
|
|
1518
1622
|
.section-desc "Slide-out panel from edge of screen with focus trap and scroll lock."
|
|
1519
1623
|
.demo-row
|
|
1520
1624
|
.demo-label "Open from right"
|
|
@@ -1548,16 +1652,11 @@ export WidgetGallery = component
|
|
|
1548
1652
|
code "$open"
|
|
1549
1653
|
code "$side"
|
|
1550
1654
|
|
|
1551
|
-
#
|
|
1655
|
+
# ========================================================================
|
|
1552
1656
|
# POPOVER
|
|
1553
|
-
#
|
|
1657
|
+
# ========================================================================
|
|
1554
1658
|
.section id: "popover"
|
|
1555
|
-
|
|
1556
|
-
span.badge @click: (=> @_viewSource('popover')), "143 lines ❐"
|
|
1557
|
-
.section-nav
|
|
1558
|
-
a @click: (=> @_navSection('popover', 'prev')), "‹"
|
|
1559
|
-
a @click: (=> @_navSection('popover', 'home')), "⌂"
|
|
1560
|
-
a @click: (=> @_navSection('popover', 'next')), "›"
|
|
1659
|
+
SectionHead tag: "popover", name: "Popover", lines: 117
|
|
1561
1660
|
.section-desc "Anchored floating content with flip/shift positioning."
|
|
1562
1661
|
.demo-row
|
|
1563
1662
|
.demo-label "Click to toggle"
|
|
@@ -1588,16 +1687,11 @@ export WidgetGallery = component
|
|
|
1588
1687
|
code "$open"
|
|
1589
1688
|
code "$placement"
|
|
1590
1689
|
|
|
1591
|
-
#
|
|
1690
|
+
# ========================================================================
|
|
1592
1691
|
# TOOLTIP
|
|
1593
|
-
#
|
|
1692
|
+
# ========================================================================
|
|
1594
1693
|
.section id: "tooltip"
|
|
1595
|
-
|
|
1596
|
-
span.badge @click: (=> @_viewSource('tooltip')), "115 lines ❐"
|
|
1597
|
-
.section-nav
|
|
1598
|
-
a @click: (=> @_navSection('tooltip', 'prev')), "‹"
|
|
1599
|
-
a @click: (=> @_navSection('tooltip', 'home')), "⌂"
|
|
1600
|
-
a @click: (=> @_navSection('tooltip', 'next')), "›"
|
|
1694
|
+
SectionHead tag: "tooltip", name: "Tooltip", lines: 92
|
|
1601
1695
|
.section-desc "Hover/focus tooltip with delay and positioning."
|
|
1602
1696
|
.demo-row
|
|
1603
1697
|
.demo-label "Hover the buttons"
|
|
@@ -1624,16 +1718,11 @@ export WidgetGallery = component
|
|
|
1624
1718
|
code "$exiting"
|
|
1625
1719
|
code "$placement"
|
|
1626
1720
|
|
|
1627
|
-
#
|
|
1721
|
+
# ========================================================================
|
|
1628
1722
|
# PREVIEW CARD
|
|
1629
|
-
#
|
|
1723
|
+
# ========================================================================
|
|
1630
1724
|
.section id: "preview-card"
|
|
1631
|
-
|
|
1632
|
-
span.badge @click: (=> @_viewSource('preview-card')), "73 lines ❐"
|
|
1633
|
-
.section-nav
|
|
1634
|
-
a @click: (=> @_navSection('preview-card', 'prev')), "‹"
|
|
1635
|
-
a @click: (=> @_navSection('preview-card', 'home')), "⌂"
|
|
1636
|
-
a @click: (=> @_navSection('preview-card', 'next')), "›"
|
|
1725
|
+
SectionHead tag: "preview-card", name: "PreviewCard", lines: 56
|
|
1637
1726
|
.section-desc "Hover or focus the link to see a preview card."
|
|
1638
1727
|
.demo-row
|
|
1639
1728
|
PreviewCard delay: 300
|
|
@@ -1653,16 +1742,11 @@ export WidgetGallery = component
|
|
|
1653
1742
|
dd
|
|
1654
1743
|
code "$open"
|
|
1655
1744
|
|
|
1656
|
-
#
|
|
1745
|
+
# ========================================================================
|
|
1657
1746
|
# TOAST
|
|
1658
|
-
#
|
|
1747
|
+
# ========================================================================
|
|
1659
1748
|
.section id: "toast"
|
|
1660
|
-
|
|
1661
|
-
span.badge @click: (=> @_viewSource('toast')), "88 lines ❐"
|
|
1662
|
-
.section-nav
|
|
1663
|
-
a @click: (=> @_navSection('toast', 'prev')), "‹"
|
|
1664
|
-
a @click: (=> @_navSection('toast', 'home')), "⌂"
|
|
1665
|
-
a @click: (=> @_navSection('toast', 'next')), "›"
|
|
1749
|
+
SectionHead tag: "toast", name: "Toast", lines: 56
|
|
1666
1750
|
.section-desc "Auto-dismiss notification with ARIA live region."
|
|
1667
1751
|
.demo-row
|
|
1668
1752
|
.demo-label "Click to show toasts"
|
|
@@ -1688,16 +1772,11 @@ export WidgetGallery = component
|
|
|
1688
1772
|
code "$type"
|
|
1689
1773
|
code "$leaving"
|
|
1690
1774
|
|
|
1691
|
-
#
|
|
1775
|
+
# ========================================================================
|
|
1692
1776
|
# BUTTON
|
|
1693
|
-
#
|
|
1777
|
+
# ========================================================================
|
|
1694
1778
|
.section id: "button"
|
|
1695
|
-
|
|
1696
|
-
span.badge @click: (=> @_viewSource('button')), "23 lines ❐"
|
|
1697
|
-
.section-nav
|
|
1698
|
-
a @click: (=> @_navSection('button', 'prev')), "‹"
|
|
1699
|
-
a @click: (=> @_navSection('button', 'home')), "⌂"
|
|
1700
|
-
a @click: (=> @_navSection('button', 'next')), "›"
|
|
1779
|
+
SectionHead tag: "button", name: "Button", lines: 10
|
|
1701
1780
|
.section-desc "Headless button with disabled-but-focusable pattern."
|
|
1702
1781
|
.demo-row.btn-demo
|
|
1703
1782
|
.demo-label "Normal, primary, and disabled"
|
|
@@ -1720,16 +1799,55 @@ export WidgetGallery = component
|
|
|
1720
1799
|
dd
|
|
1721
1800
|
code "$disabled"
|
|
1722
1801
|
|
|
1723
|
-
#
|
|
1802
|
+
# ========================================================================
|
|
1803
|
+
# BADGE
|
|
1804
|
+
# ========================================================================
|
|
1805
|
+
.section id: "badge"
|
|
1806
|
+
SectionHead tag: "badge", name: "Badge", lines: 5
|
|
1807
|
+
.section-desc "Inline label with variant styles."
|
|
1808
|
+
.demo-row
|
|
1809
|
+
.demo-label "Variants"
|
|
1810
|
+
. style: "display:flex;gap:8px;align-items:center"
|
|
1811
|
+
Badge "Solid"
|
|
1812
|
+
Badge variant: "outline", "Outline"
|
|
1813
|
+
Badge variant: "subtle", "Subtle"
|
|
1814
|
+
.api
|
|
1815
|
+
dl
|
|
1816
|
+
dt "Props"
|
|
1817
|
+
dd
|
|
1818
|
+
code "@variant"
|
|
1819
|
+
dt "Data"
|
|
1820
|
+
dd
|
|
1821
|
+
code "$variant"
|
|
1822
|
+
|
|
1823
|
+
# ========================================================================
|
|
1824
|
+
# CARD
|
|
1825
|
+
# ========================================================================
|
|
1826
|
+
.section id: "card"
|
|
1827
|
+
SectionHead tag: "card", name: "Card", lines: 6
|
|
1828
|
+
.section-desc "Structured container with header, content, and footer."
|
|
1829
|
+
.demo-row.card-demo
|
|
1830
|
+
Card
|
|
1831
|
+
div $header: true
|
|
1832
|
+
h3 "Card Title"
|
|
1833
|
+
div $content: true
|
|
1834
|
+
"This is the card body. Cards can contain any content."
|
|
1835
|
+
div $footer: true
|
|
1836
|
+
button.demo-btn @click: (=> toasts = [...toasts, { message: 'Card action clicked!', type: 'success' }]), "Action"
|
|
1837
|
+
.api
|
|
1838
|
+
dl
|
|
1839
|
+
dt "Props"
|
|
1840
|
+
dd
|
|
1841
|
+
code "@interactive"
|
|
1842
|
+
dt "Data"
|
|
1843
|
+
dd
|
|
1844
|
+
code "$interactive"
|
|
1845
|
+
|
|
1846
|
+
# ========================================================================
|
|
1724
1847
|
# SEPARATOR
|
|
1725
|
-
#
|
|
1848
|
+
# ========================================================================
|
|
1726
1849
|
.section id: "separator"
|
|
1727
|
-
|
|
1728
|
-
span.badge @click: (=> @_viewSource('separator')), "17 lines ❐"
|
|
1729
|
-
.section-nav
|
|
1730
|
-
a @click: (=> @_navSection('separator', 'prev')), "‹"
|
|
1731
|
-
a @click: (=> @_navSection('separator', 'home')), "⌂"
|
|
1732
|
-
a @click: (=> @_navSection('separator', 'next')), "›"
|
|
1850
|
+
SectionHead tag: "separator", name: "Separator", lines: 7
|
|
1733
1851
|
.section-desc "Decorative or semantic divider between sections."
|
|
1734
1852
|
.demo-row
|
|
1735
1853
|
.demo-label "Horizontal (default)"
|
|
@@ -1753,16 +1871,11 @@ export WidgetGallery = component
|
|
|
1753
1871
|
dd
|
|
1754
1872
|
code "$orientation"
|
|
1755
1873
|
|
|
1756
|
-
#
|
|
1874
|
+
# ========================================================================
|
|
1757
1875
|
# PROGRESS
|
|
1758
|
-
#
|
|
1876
|
+
# ========================================================================
|
|
1759
1877
|
.section id: "progress"
|
|
1760
|
-
|
|
1761
|
-
span.badge @click: (=> @_viewSource('progress')), "25 lines ❐"
|
|
1762
|
-
.section-nav
|
|
1763
|
-
a @click: (=> @_navSection('progress', 'prev')), "‹"
|
|
1764
|
-
a @click: (=> @_navSection('progress', 'home')), "⌂"
|
|
1765
|
-
a @click: (=> @_navSection('progress', 'next')), "›"
|
|
1878
|
+
SectionHead tag: "progress", name: "Progress", lines: 14
|
|
1766
1879
|
.section-desc "Progress bar with value exposed as CSS custom property."
|
|
1767
1880
|
.demo-row
|
|
1768
1881
|
.demo-label "65% complete"
|
|
@@ -1780,16 +1893,11 @@ export WidgetGallery = component
|
|
|
1780
1893
|
dd
|
|
1781
1894
|
code "$complete"
|
|
1782
1895
|
|
|
1783
|
-
#
|
|
1896
|
+
# ========================================================================
|
|
1784
1897
|
# METER
|
|
1785
|
-
#
|
|
1898
|
+
# ========================================================================
|
|
1786
1899
|
.section id: "meter"
|
|
1787
|
-
|
|
1788
|
-
span.badge @click: (=> @_viewSource('meter')), "36 lines ❐"
|
|
1789
|
-
.section-nav
|
|
1790
|
-
a @click: (=> @_navSection('meter', 'prev')), "‹"
|
|
1791
|
-
a @click: (=> @_navSection('meter', 'home')), "⌂"
|
|
1792
|
-
a @click: (=> @_navSection('meter', 'next')), "›"
|
|
1900
|
+
SectionHead tag: "meter", name: "Meter", lines: 23
|
|
1793
1901
|
.section-desc "Gauge for known-range measurements with low/high/optimum thresholds."
|
|
1794
1902
|
.demo-row
|
|
1795
1903
|
.demo-label "Score: 72/100"
|
|
@@ -1809,16 +1917,55 @@ export WidgetGallery = component
|
|
|
1809
1917
|
dd
|
|
1810
1918
|
code "$level"
|
|
1811
1919
|
|
|
1812
|
-
#
|
|
1920
|
+
# ========================================================================
|
|
1921
|
+
# SPINNER
|
|
1922
|
+
# ========================================================================
|
|
1923
|
+
.section id: "spinner"
|
|
1924
|
+
SectionHead tag: "spinner", name: "Spinner", lines: 6
|
|
1925
|
+
.section-desc "Loading indicator with accessible status."
|
|
1926
|
+
.demo-row.spinner-demo
|
|
1927
|
+
.demo-label "Default"
|
|
1928
|
+
. style: "display:flex;gap:16px;align-items:center"
|
|
1929
|
+
Spinner
|
|
1930
|
+
Spinner size: "32px"
|
|
1931
|
+
Spinner label: "Saving...", size: "20px"
|
|
1932
|
+
.api
|
|
1933
|
+
dl
|
|
1934
|
+
dt "Props"
|
|
1935
|
+
dd
|
|
1936
|
+
code "@label"
|
|
1937
|
+
code "@size"
|
|
1938
|
+
|
|
1939
|
+
# ========================================================================
|
|
1940
|
+
# SKELETON
|
|
1941
|
+
# ========================================================================
|
|
1942
|
+
.section id: "skeleton"
|
|
1943
|
+
SectionHead tag: "skeleton", name: "Skeleton", lines: 10
|
|
1944
|
+
.section-desc "Loading placeholder with shimmer animation."
|
|
1945
|
+
.demo-row
|
|
1946
|
+
.demo-label "Shapes"
|
|
1947
|
+
. style: "display:flex;gap:12px;align-items:center"
|
|
1948
|
+
Skeleton circle: true, width: "40px", height: "40px"
|
|
1949
|
+
. style: "display:flex;flex-direction:column;gap:6px"
|
|
1950
|
+
Skeleton width: "200px", height: "14px"
|
|
1951
|
+
Skeleton width: "150px", height: "14px"
|
|
1952
|
+
.api
|
|
1953
|
+
dl
|
|
1954
|
+
dt "Props"
|
|
1955
|
+
dd
|
|
1956
|
+
code "@width"
|
|
1957
|
+
code "@height"
|
|
1958
|
+
code "@circle"
|
|
1959
|
+
code "@label"
|
|
1960
|
+
dt "Data"
|
|
1961
|
+
dd
|
|
1962
|
+
code "$circle"
|
|
1963
|
+
|
|
1964
|
+
# ========================================================================
|
|
1813
1965
|
# AVATAR
|
|
1814
|
-
#
|
|
1966
|
+
# ========================================================================
|
|
1815
1967
|
.section id: "avatar"
|
|
1816
|
-
|
|
1817
|
-
span.badge @click: (=> @_viewSource('avatar')), "37 lines ❐"
|
|
1818
|
-
.section-nav
|
|
1819
|
-
a @click: (=> @_navSection('avatar', 'prev')), "‹"
|
|
1820
|
-
a @click: (=> @_navSection('avatar', 'home')), "⌂"
|
|
1821
|
-
a @click: (=> @_navSection('avatar', 'next')), "›"
|
|
1968
|
+
SectionHead tag: "avatar", name: "Avatar", lines: 23
|
|
1822
1969
|
.section-desc "Image with fallback to initials or placeholder."
|
|
1823
1970
|
.demo-row
|
|
1824
1971
|
.demo-label "With image"
|
|
@@ -1842,16 +1989,31 @@ export WidgetGallery = component
|
|
|
1842
1989
|
code "$initials"
|
|
1843
1990
|
code "$placeholder"
|
|
1844
1991
|
|
|
1845
|
-
#
|
|
1992
|
+
# ========================================================================
|
|
1993
|
+
# LABEL
|
|
1994
|
+
# ========================================================================
|
|
1995
|
+
.section id: "label"
|
|
1996
|
+
SectionHead tag: "label", name: "Label", lines: 6
|
|
1997
|
+
.section-desc "Standalone accessible form label."
|
|
1998
|
+
.demo-row
|
|
1999
|
+
.demo-label "With required indicator"
|
|
2000
|
+
Label required: true
|
|
2001
|
+
"Email address"
|
|
2002
|
+
.api
|
|
2003
|
+
dl
|
|
2004
|
+
dt "Props"
|
|
2005
|
+
dd
|
|
2006
|
+
code "@for"
|
|
2007
|
+
code "@required"
|
|
2008
|
+
dt "Data"
|
|
2009
|
+
dd
|
|
2010
|
+
code "$required"
|
|
2011
|
+
|
|
2012
|
+
# ========================================================================
|
|
1846
2013
|
# SCROLL AREA
|
|
1847
|
-
#
|
|
2014
|
+
# ========================================================================
|
|
1848
2015
|
.section id: "scroll-area"
|
|
1849
|
-
|
|
1850
|
-
span.badge @click: (=> @_viewSource('scroll-area')), "145 lines ❐"
|
|
1851
|
-
.section-nav
|
|
1852
|
-
a @click: (=> @_navSection('scroll-area', 'prev')), "‹"
|
|
1853
|
-
a @click: (=> @_navSection('scroll-area', 'home')), "⌂"
|
|
1854
|
-
a @click: (=> @_navSection('scroll-area', 'next')), "›"
|
|
2016
|
+
SectionHead tag: "scroll-area", name: "ScrollArea", lines: 115
|
|
1855
2017
|
.section-desc "Custom scrollbar with draggable thumb and auto-hide."
|
|
1856
2018
|
.demo-row
|
|
1857
2019
|
.demo-label "Scrollable content"
|
|
@@ -1888,16 +2050,11 @@ export WidgetGallery = component
|
|
|
1888
2050
|
code "$scrollbar"
|
|
1889
2051
|
code "$thumb"
|
|
1890
2052
|
|
|
1891
|
-
#
|
|
2053
|
+
# ========================================================================
|
|
1892
2054
|
# FIELD + FIELDSET
|
|
1893
|
-
#
|
|
2055
|
+
# ========================================================================
|
|
1894
2056
|
.section id: "field"
|
|
1895
|
-
|
|
1896
|
-
span.badge @click: (=> @_viewSource('field')), "75 lines ❐"
|
|
1897
|
-
.section-nav
|
|
1898
|
-
a @click: (=> @_navSection('field', 'prev')), "‹"
|
|
1899
|
-
a @click: (=> @_navSection('field', 'home')), "⌂"
|
|
1900
|
-
a @click: (=> @_navSection('field', 'next')), "›"
|
|
2057
|
+
SectionHead tag: "field", name: "Field + Fieldset", lines: 48
|
|
1901
2058
|
.section-desc "Form field wrapper with label, description, and error."
|
|
1902
2059
|
.demo-row
|
|
1903
2060
|
Field label: "Email", description: "We'll never share your email.", required: true, error: fieldError
|
|
@@ -1934,16 +2091,11 @@ export WidgetGallery = component
|
|
|
1934
2091
|
code "$error"
|
|
1935
2092
|
code "$legend"
|
|
1936
2093
|
|
|
1937
|
-
#
|
|
2094
|
+
# ========================================================================
|
|
1938
2095
|
# FORM
|
|
1939
|
-
#
|
|
2096
|
+
# ========================================================================
|
|
1940
2097
|
.section id: "form"
|
|
1941
|
-
|
|
1942
|
-
span.badge @click: (=> @_viewSource('form')), "39 lines ❐"
|
|
1943
|
-
.section-nav
|
|
1944
|
-
a @click: (=> @_navSection('form', 'prev')), "‹"
|
|
1945
|
-
a @click: (=> @_navSection('form', 'home')), "⌂"
|
|
1946
|
-
a @click: (=> @_navSection('form', 'next')), "›"
|
|
2098
|
+
SectionHead tag: "form", name: "Form", lines: 21
|
|
1947
2099
|
.section-desc "Form wrapper with submit handling and validation state."
|
|
1948
2100
|
.demo-row
|
|
1949
2101
|
Form
|
|
@@ -1967,16 +2119,35 @@ export WidgetGallery = component
|
|
|
1967
2119
|
code "$submitting"
|
|
1968
2120
|
code "$submitted"
|
|
1969
2121
|
|
|
1970
|
-
#
|
|
2122
|
+
# ========================================================================
|
|
2123
|
+
# BUTTON GROUP
|
|
2124
|
+
# ========================================================================
|
|
2125
|
+
.section id: "button-group"
|
|
2126
|
+
SectionHead tag: "button-group", name: "ButtonGroup", lines: 11
|
|
2127
|
+
.section-desc "Groups related buttons with ARIA group semantics."
|
|
2128
|
+
.demo-row
|
|
2129
|
+
.demo-label "Horizontal"
|
|
2130
|
+
ButtonGroup label: "Actions"
|
|
2131
|
+
button "Cut"
|
|
2132
|
+
button "Copy"
|
|
2133
|
+
button "Paste"
|
|
2134
|
+
.api
|
|
2135
|
+
dl
|
|
2136
|
+
dt "Props"
|
|
2137
|
+
dd
|
|
2138
|
+
code "@orientation"
|
|
2139
|
+
code "@disabled"
|
|
2140
|
+
code "@label"
|
|
2141
|
+
dt "Data"
|
|
2142
|
+
dd
|
|
2143
|
+
code "$orientation"
|
|
2144
|
+
code "$disabled"
|
|
2145
|
+
|
|
2146
|
+
# ========================================================================
|
|
1971
2147
|
# GRID
|
|
1972
|
-
#
|
|
2148
|
+
# ========================================================================
|
|
1973
2149
|
.section id: "grid"
|
|
1974
|
-
|
|
1975
|
-
span.badge @click: (=> @_viewSource('grid')), "901 lines ❐"
|
|
1976
|
-
.section-nav
|
|
1977
|
-
a @click: (=> @_navSection('grid', 'prev')), "‹"
|
|
1978
|
-
a @click: (=> @_navSection('grid', 'home')), "⌂"
|
|
1979
|
-
a @click: (=> @_navSection('grid', 'next')), "›"
|
|
2150
|
+
SectionHead tag: "grid", name: "Grid", lines: 799
|
|
1980
2151
|
.section-desc "Virtual-scrolling data grid. Click to select, arrows to navigate, double-click to edit."
|
|
1981
2152
|
.demo-row
|
|
1982
2153
|
. style: "display:flex;justify-content:space-between;align-items:baseline;margin-bottom:8px"
|
|
@@ -2022,16 +2193,11 @@ export WidgetGallery = component
|
|
|
2022
2193
|
code "$selecting"
|
|
2023
2194
|
code "$sorted"
|
|
2024
2195
|
|
|
2025
|
-
#
|
|
2196
|
+
# ========================================================================
|
|
2026
2197
|
# ACCORDION
|
|
2027
|
-
#
|
|
2198
|
+
# ========================================================================
|
|
2028
2199
|
.section id: "accordion"
|
|
2029
|
-
|
|
2030
|
-
span.badge @click: (=> @_viewSource('accordion')), "113 lines ❐"
|
|
2031
|
-
.section-nav
|
|
2032
|
-
a @click: (=> @_navSection('accordion', 'prev')), "‹"
|
|
2033
|
-
a @click: (=> @_navSection('accordion', 'home')), "⌂"
|
|
2034
|
-
a @click: (=> @_navSection('accordion', 'next')), "›"
|
|
2200
|
+
SectionHead tag: "accordion", name: "Accordion", lines: 86
|
|
2035
2201
|
.section-desc "Expand/collapse sections, single or multiple mode."
|
|
2036
2202
|
.demo-row
|
|
2037
2203
|
.demo-label "Single mode"
|
|
@@ -2074,17 +2240,187 @@ export WidgetGallery = component
|
|
|
2074
2240
|
code "$open"
|
|
2075
2241
|
code "$disabled"
|
|
2076
2242
|
|
|
2077
|
-
#
|
|
2243
|
+
# ========================================================================
|
|
2244
|
+
# TABLE
|
|
2245
|
+
# ========================================================================
|
|
2246
|
+
.section id: "table"
|
|
2247
|
+
SectionHead tag: "table", name: "Table", lines: 9
|
|
2248
|
+
.section-desc "Semantic table wrapper. For data-heavy tables, use Grid."
|
|
2249
|
+
.demo-row.table-demo
|
|
2250
|
+
Table caption: "Team", striped: true
|
|
2251
|
+
thead
|
|
2252
|
+
tr
|
|
2253
|
+
th "Name"
|
|
2254
|
+
th "Role"
|
|
2255
|
+
th "City"
|
|
2256
|
+
tbody
|
|
2257
|
+
tr
|
|
2258
|
+
td "Alice"
|
|
2259
|
+
td "Engineer"
|
|
2260
|
+
td "Seattle"
|
|
2261
|
+
tr
|
|
2262
|
+
td "Bob"
|
|
2263
|
+
td "Designer"
|
|
2264
|
+
td "Portland"
|
|
2265
|
+
tr
|
|
2266
|
+
td "Carol"
|
|
2267
|
+
td "Manager"
|
|
2268
|
+
td "Denver"
|
|
2269
|
+
.api
|
|
2270
|
+
dl
|
|
2271
|
+
dt "Props"
|
|
2272
|
+
dd
|
|
2273
|
+
code "@caption"
|
|
2274
|
+
code "@striped"
|
|
2275
|
+
dt "Data"
|
|
2276
|
+
dd
|
|
2277
|
+
code "$striped"
|
|
2278
|
+
|
|
2279
|
+
# ========================================================================
|
|
2280
|
+
# COLLAPSIBLE
|
|
2281
|
+
# ========================================================================
|
|
2282
|
+
.section id: "collapsible"
|
|
2283
|
+
SectionHead tag: "collapsible", name: "Collapsible", lines: 33
|
|
2284
|
+
.section-desc "Single open/close section. Simpler than Accordion."
|
|
2285
|
+
.demo-row.collapsible-demo
|
|
2286
|
+
Collapsible open <=> collapsibleOpen
|
|
2287
|
+
button $trigger: true
|
|
2288
|
+
span style: "font-size:10px;margin-right:6px"
|
|
2289
|
+
if collapsibleOpen then "▼" else "▶"
|
|
2290
|
+
"Show details"
|
|
2291
|
+
div $content: true
|
|
2292
|
+
p "These are the collapsible details. Click the trigger or press Enter/Space to toggle."
|
|
2293
|
+
.status "open: #{collapsibleOpen}"
|
|
2294
|
+
.api
|
|
2295
|
+
dl
|
|
2296
|
+
dt "Props"
|
|
2297
|
+
dd
|
|
2298
|
+
code "@open"
|
|
2299
|
+
code "@disabled"
|
|
2300
|
+
dt "Events"
|
|
2301
|
+
dd
|
|
2302
|
+
code "change"
|
|
2303
|
+
dt "Keyboard"
|
|
2304
|
+
dd
|
|
2305
|
+
kbd "Enter"
|
|
2306
|
+
kbd "Space"
|
|
2307
|
+
dt "Data"
|
|
2308
|
+
dd
|
|
2309
|
+
code "$open"
|
|
2310
|
+
code "$disabled"
|
|
2311
|
+
|
|
2312
|
+
# ========================================================================
|
|
2313
|
+
# PAGINATION
|
|
2314
|
+
# ========================================================================
|
|
2315
|
+
.section id: "pagination"
|
|
2316
|
+
SectionHead tag: "pagination", name: "Pagination", lines: 96
|
|
2317
|
+
.section-desc "Page navigation with prev/next buttons and ellipsis gaps."
|
|
2318
|
+
.demo-row
|
|
2319
|
+
.demo-label "10 pages"
|
|
2320
|
+
Pagination page <=> currentPage, total: 100, perPage: 10
|
|
2321
|
+
.status "page: #{currentPage}"
|
|
2322
|
+
.api
|
|
2323
|
+
dl
|
|
2324
|
+
dt "Props"
|
|
2325
|
+
dd
|
|
2326
|
+
code "@page"
|
|
2327
|
+
code "@total"
|
|
2328
|
+
code "@perPage"
|
|
2329
|
+
code "@siblingCount"
|
|
2330
|
+
dt "Events"
|
|
2331
|
+
dd
|
|
2332
|
+
code "change"
|
|
2333
|
+
dt "Keyboard"
|
|
2334
|
+
dd
|
|
2335
|
+
kbd "← →"
|
|
2336
|
+
kbd "Home"
|
|
2337
|
+
kbd "End"
|
|
2338
|
+
dt "Data"
|
|
2339
|
+
dd
|
|
2340
|
+
code "$active"
|
|
2341
|
+
code "$disabled"
|
|
2342
|
+
code "$ellipsis"
|
|
2343
|
+
|
|
2344
|
+
# ========================================================================
|
|
2345
|
+
# CAROUSEL
|
|
2346
|
+
# ========================================================================
|
|
2347
|
+
.section id: "carousel"
|
|
2348
|
+
SectionHead tag: "carousel", name: "Carousel", lines: 78
|
|
2349
|
+
.section-desc "Slide carousel with loop and keyboard navigation."
|
|
2350
|
+
.demo-row
|
|
2351
|
+
Carousel loop: true
|
|
2352
|
+
div $slide: true
|
|
2353
|
+
"🍎 Slide 1 — Apples"
|
|
2354
|
+
div $slide: true
|
|
2355
|
+
"🍌 Slide 2 — Bananas"
|
|
2356
|
+
div $slide: true
|
|
2357
|
+
"🍒 Slide 3 — Cherries"
|
|
2358
|
+
.api
|
|
2359
|
+
dl
|
|
2360
|
+
dt "Props"
|
|
2361
|
+
dd
|
|
2362
|
+
code "@orientation"
|
|
2363
|
+
code "@loop"
|
|
2364
|
+
code "@autoplay"
|
|
2365
|
+
code "@interval"
|
|
2366
|
+
code "@label"
|
|
2367
|
+
dt "Events"
|
|
2368
|
+
dd
|
|
2369
|
+
code "change"
|
|
2370
|
+
dt "Keyboard"
|
|
2371
|
+
dd
|
|
2372
|
+
kbd "← →"
|
|
2373
|
+
kbd "↕"
|
|
2374
|
+
kbd "Home"
|
|
2375
|
+
kbd "End"
|
|
2376
|
+
dt "Data"
|
|
2377
|
+
dd
|
|
2378
|
+
code "$orientation"
|
|
2379
|
+
code "$active"
|
|
2380
|
+
code "$prev"
|
|
2381
|
+
code "$next"
|
|
2382
|
+
|
|
2383
|
+
# ========================================================================
|
|
2384
|
+
# RESIZABLE
|
|
2385
|
+
# ========================================================================
|
|
2386
|
+
.section id: "resizable"
|
|
2387
|
+
SectionHead tag: "resizable", name: "Resizable", lines: 89
|
|
2388
|
+
.section-desc "Draggable resize handles between panels."
|
|
2389
|
+
.demo-row.resizable-demo
|
|
2390
|
+
Resizable
|
|
2391
|
+
div $panel: true, "Left"
|
|
2392
|
+
div $handle: true
|
|
2393
|
+
div $panel: true, "Right"
|
|
2394
|
+
.api
|
|
2395
|
+
dl
|
|
2396
|
+
dt "Props"
|
|
2397
|
+
dd
|
|
2398
|
+
code "@orientation"
|
|
2399
|
+
code "@minSize"
|
|
2400
|
+
code "@maxSize"
|
|
2401
|
+
dt "Events"
|
|
2402
|
+
dd
|
|
2403
|
+
code "resize"
|
|
2404
|
+
dt "Keyboard"
|
|
2405
|
+
dd
|
|
2406
|
+
kbd "← →"
|
|
2407
|
+
kbd "↕"
|
|
2408
|
+
dt "Data"
|
|
2409
|
+
dd
|
|
2410
|
+
code "$orientation"
|
|
2411
|
+
code "$dragging"
|
|
2412
|
+
|
|
2413
|
+
# ========================================================================
|
|
2078
2414
|
# SOURCE CODE VIEWER
|
|
2079
|
-
#
|
|
2415
|
+
# ========================================================================
|
|
2080
2416
|
if sourceCode
|
|
2081
|
-
.source-overlay @click: @_closeSource
|
|
2417
|
+
.source-overlay @click: (=> @_closeSource())
|
|
2082
2418
|
.source-modal @click: (e => e.stopPropagation())
|
|
2083
2419
|
.source-header
|
|
2084
2420
|
.source-title
|
|
2085
2421
|
span.source-name sourceName
|
|
2086
2422
|
span.source-badge "#{sourceLines} lines"
|
|
2087
|
-
button.source-close @click: @_closeSource
|
|
2423
|
+
button.source-close @click: (=> @_closeSource())
|
|
2088
2424
|
"×"
|
|
2089
2425
|
.source-body
|
|
2090
2426
|
pre.source-pre
|