kiso 0.5.2.pre → 0.6.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/tailwind/kiso/button.css +12 -3
- data/app/assets/tailwind/kiso/checkbox.css +13 -2
- data/app/assets/tailwind/kiso/color-mode.css +15 -3
- data/app/assets/tailwind/kiso/dashboard.css +97 -44
- data/app/assets/tailwind/kiso/dialog.css +39 -5
- data/app/assets/tailwind/kiso/engine.css +117 -34
- data/app/assets/tailwind/kiso/input-otp.css +24 -4
- data/app/assets/tailwind/kiso/palettes/blue.css +14 -5
- data/app/assets/tailwind/kiso/palettes/green.css +9 -5
- data/app/assets/tailwind/kiso/palettes/orange.css +9 -5
- data/app/assets/tailwind/kiso/palettes/violet.css +9 -5
- data/app/assets/tailwind/kiso/palettes/zinc.css +11 -7
- data/app/assets/tailwind/kiso/radio-group.css +11 -4
- data/app/assets/tailwind/kiso/slider.css +25 -6
- data/app/assets/tailwind/kiso/tooltip.css +37 -11
- data/app/helpers/kiso/app_component_helper.rb +83 -34
- data/app/helpers/kiso/component_helper.rb +227 -70
- data/app/helpers/kiso/icon_helper.rb +101 -39
- data/app/helpers/kiso/theme_helper.rb +50 -9
- data/app/helpers/kiso/ui_context_helper.rb +87 -35
- data/app/javascript/controllers/kiso/combobox_controller.js +10 -2
- data/app/javascript/controllers/kiso/command_controller.js +2 -0
- data/app/javascript/controllers/kiso/command_dialog_controller.js +4 -0
- data/app/javascript/controllers/kiso/dialog_controller.js +6 -1
- data/app/javascript/controllers/kiso/dialog_trigger_controller.js +1 -1
- data/app/javascript/controllers/kiso/dropdown_menu_controller.js +23 -5
- data/app/javascript/controllers/kiso/index.js +25 -0
- data/app/javascript/controllers/kiso/input_otp_controller.js +5 -3
- data/app/javascript/controllers/kiso/popover_controller.js +18 -4
- data/app/javascript/controllers/kiso/select_controller.js +10 -2
- data/app/javascript/controllers/kiso/sidebar_controller.js +26 -4
- data/app/javascript/controllers/kiso/slider_controller.js +3 -3
- data/app/javascript/controllers/kiso/theme_controller.js +2 -1
- data/app/javascript/controllers/kiso/toggle_controller.js +2 -0
- data/app/javascript/controllers/kiso/toggle_group_controller.js +3 -0
- data/app/javascript/controllers/kiso/tooltip_controller.js +3 -0
- data/app/javascript/kiso/utils/focusable.js +14 -0
- data/app/javascript/kiso/utils/highlight.js +15 -1
- data/app/views/kiso/components/_alert.html.erb +2 -0
- data/app/views/kiso/components/_alert_dialog.html.erb +5 -2
- data/app/views/kiso/components/_app.html.erb +2 -0
- data/app/views/kiso/components/_aspect_ratio.html.erb +1 -0
- data/app/views/kiso/components/_avatar.html.erb +6 -2
- data/app/views/kiso/components/_button.html.erb +3 -0
- data/app/views/kiso/components/_checkbox.html.erb +1 -0
- data/app/views/kiso/components/_color_mode_button.html.erb +2 -0
- data/app/views/kiso/components/_color_mode_select.html.erb +2 -0
- data/app/views/kiso/components/_combobox.html.erb +3 -0
- data/app/views/kiso/components/_command.html.erb +2 -0
- data/app/views/kiso/components/_dashboard_group.html.erb +4 -0
- data/app/views/kiso/components/_dashboard_navbar.html.erb +2 -0
- data/app/views/kiso/components/_dashboard_panel.html.erb +1 -0
- data/app/views/kiso/components/_dashboard_sidebar.html.erb +2 -0
- data/app/views/kiso/components/_dashboard_toolbar.html.erb +2 -0
- data/app/views/kiso/components/_dialog.html.erb +3 -0
- data/app/views/kiso/components/_dropdown_menu.html.erb +2 -0
- data/app/views/kiso/components/_empty.html.erb +2 -0
- data/app/views/kiso/components/_field.html.erb +2 -0
- data/app/views/kiso/components/_field_group.html.erb +1 -0
- data/app/views/kiso/components/_field_set.html.erb +1 -0
- data/app/views/kiso/components/_input_group.html.erb +1 -0
- data/app/views/kiso/components/_input_otp.html.erb +3 -0
- data/app/views/kiso/components/_nav.html.erb +2 -0
- data/app/views/kiso/components/_page_card.html.erb +3 -0
- data/app/views/kiso/components/_page_header.html.erb +3 -0
- data/app/views/kiso/components/_page_section.html.erb +2 -0
- data/app/views/kiso/components/_pagination.html.erb +2 -0
- data/app/views/kiso/components/_popover.html.erb +3 -0
- data/app/views/kiso/components/_select.html.erb +3 -0
- data/app/views/kiso/components/_select_native.html.erb +2 -0
- data/app/views/kiso/components/_separator.html.erb +2 -0
- data/app/views/kiso/components/_skeleton.html.erb +1 -0
- data/app/views/kiso/components/_slider.html.erb +4 -0
- data/app/views/kiso/components/_spinner.html.erb +2 -0
- data/app/views/kiso/components/_stats_card.html.erb +2 -0
- data/app/views/kiso/components/_stats_grid.html.erb +1 -0
- data/app/views/kiso/components/_switch.html.erb +2 -0
- data/app/views/kiso/components/_table.html.erb +2 -0
- data/app/views/kiso/components/_textarea.html.erb +3 -0
- data/app/views/kiso/components/_toggle.html.erb +2 -0
- data/app/views/kiso/components/_toggle_group.html.erb +2 -0
- data/app/views/kiso/components/_tooltip.html.erb +3 -0
- data/app/views/kiso/components/alert_dialog/_action.html.erb +1 -0
- data/app/views/kiso/components/alert_dialog/_cancel.html.erb +1 -0
- data/app/views/kiso/components/alert_dialog/_description.html.erb +1 -0
- data/app/views/kiso/components/alert_dialog/_title.html.erb +1 -0
- data/app/views/kiso/components/avatar/_image.html.erb +1 -0
- data/app/views/kiso/components/breadcrumb/_separator.html.erb +3 -0
- data/app/views/kiso/components/combobox/_chips.html.erb +3 -0
- data/app/views/kiso/components/command/_dialog.html.erb +2 -0
- data/app/views/kiso/components/dashboard_sidebar/_collapse.html.erb +2 -0
- data/app/views/kiso/components/dialog/_close.html.erb +1 -0
- data/app/views/kiso/components/field/_error.html.erb +4 -0
- data/app/views/kiso/components/field/_label.html.erb +2 -0
- data/app/views/kiso/components/field/_separator.html.erb +3 -0
- data/app/views/kiso/components/input_otp/_separator.html.erb +2 -0
- data/app/views/kiso/components/input_otp/_slot.html.erb +2 -0
- data/app/views/kiso/components/nav/_section.html.erb +4 -0
- data/app/views/kiso/components/tooltip/_content.html.erb +2 -0
- data/lib/generators/kiso/install/USAGE +23 -0
- data/lib/generators/kiso/install/install_generator.rb +91 -0
- data/lib/generators/kiso/install/templates/design_system.md.tt +190 -0
- data/lib/generators/kiso/install/templates/initializer.rb.tt +40 -0
- data/lib/kiso/cli/make.rb +6 -3
- data/lib/kiso/cli.rb +10 -0
- data/lib/kiso/color_utils.rb +31 -8
- data/lib/kiso/configuration.rb +11 -0
- data/lib/kiso/engine.rb +9 -2
- data/lib/kiso/propshaft_tailwind_stub_filter.rb +9 -2
- data/lib/kiso/themes/avatar.rb +40 -6
- data/lib/kiso/themes/badge.rb +5 -1
- data/lib/kiso/themes/color_mode_button.rb +11 -0
- data/lib/kiso/themes/color_mode_select.rb +7 -0
- data/lib/kiso/themes/dashboard.rb +28 -0
- data/lib/kiso/themes/dropdown_menu.rb +2 -2
- data/lib/kiso/themes/input_otp.rb +6 -3
- data/lib/kiso/themes/nav.rb +17 -0
- data/lib/kiso/themes/pagination.rb +9 -4
- data/lib/kiso/themes/shared.rb +27 -7
- data/lib/kiso/version.rb +5 -2
- metadata +5 -1
|
@@ -20,7 +20,8 @@ import { startPositioning } from "kiso-ui/utils/positioning"
|
|
|
20
20
|
*
|
|
21
21
|
* @property {HTMLElement} triggerTarget - Button that opens/closes the popover
|
|
22
22
|
* @property {HTMLElement} contentTarget - The floating panel
|
|
23
|
-
* @property {HTMLElement} [anchorTarget] - Optional alternate positioning reference
|
|
23
|
+
* @property {HTMLElement} [anchorTarget] - Optional alternate positioning reference element.
|
|
24
|
+
* When present, the popover is positioned relative to this element instead of the trigger.
|
|
24
25
|
*/
|
|
25
26
|
export default class extends Controller {
|
|
26
27
|
static targets = ["trigger", "content", "anchor"]
|
|
@@ -164,7 +165,12 @@ export default class extends Controller {
|
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
|
|
167
|
-
/**
|
|
168
|
+
/**
|
|
169
|
+
* Maps `data-align` attribute values to Floating UI placement strings.
|
|
170
|
+
*
|
|
171
|
+
* @type {Record<string, string>}
|
|
172
|
+
* @private
|
|
173
|
+
*/
|
|
168
174
|
static _alignToPlacement = {
|
|
169
175
|
start: "bottom-start",
|
|
170
176
|
center: "bottom",
|
|
@@ -240,13 +246,21 @@ export default class extends Controller {
|
|
|
240
246
|
}
|
|
241
247
|
}
|
|
242
248
|
|
|
243
|
-
/**
|
|
249
|
+
/**
|
|
250
|
+
* Attaches global listeners for outside-click and keyboard navigation.
|
|
251
|
+
*
|
|
252
|
+
* @private
|
|
253
|
+
*/
|
|
244
254
|
_addGlobalListeners() {
|
|
245
255
|
document.addEventListener("click", this._handleOutsideClick, true)
|
|
246
256
|
document.addEventListener("keydown", this._handleKeydown)
|
|
247
257
|
}
|
|
248
258
|
|
|
249
|
-
/**
|
|
259
|
+
/**
|
|
260
|
+
* Removes global listeners for outside-click and keyboard navigation.
|
|
261
|
+
*
|
|
262
|
+
* @private
|
|
263
|
+
*/
|
|
250
264
|
_removeGlobalListeners() {
|
|
251
265
|
document.removeEventListener("click", this._handleOutsideClick, true)
|
|
252
266
|
document.removeEventListener("keydown", this._handleKeydown)
|
|
@@ -293,13 +293,21 @@ export default class extends Controller {
|
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
-
/**
|
|
296
|
+
/**
|
|
297
|
+
* Attaches global listeners for outside-click and keyboard navigation.
|
|
298
|
+
*
|
|
299
|
+
* @private
|
|
300
|
+
*/
|
|
297
301
|
_addGlobalListeners() {
|
|
298
302
|
document.addEventListener("click", this._handleOutsideClick, true)
|
|
299
303
|
document.addEventListener("keydown", this._handleKeydown)
|
|
300
304
|
}
|
|
301
305
|
|
|
302
|
-
/**
|
|
306
|
+
/**
|
|
307
|
+
* Removes global listeners for outside-click and keyboard navigation.
|
|
308
|
+
*
|
|
309
|
+
* @private
|
|
310
|
+
*/
|
|
303
311
|
_removeGlobalListeners() {
|
|
304
312
|
document.removeEventListener("click", this._handleOutsideClick, true)
|
|
305
313
|
document.removeEventListener("keydown", this._handleKeydown)
|
|
@@ -9,6 +9,9 @@ import { Controller } from "@hotwired/stimulus"
|
|
|
9
9
|
* boolean attribute and persists the preference to a cookie for
|
|
10
10
|
* FOUC-free server-side restoration on the next page load.
|
|
11
11
|
*
|
|
12
|
+
* On mobile, the sidebar auto-closes when a nav item link is clicked
|
|
13
|
+
* so users don't have to manually dismiss it after every navigation.
|
|
14
|
+
*
|
|
12
15
|
* Register as `kiso--sidebar` (the engine index does this automatically).
|
|
13
16
|
*
|
|
14
17
|
* @example
|
|
@@ -35,12 +38,31 @@ import { Controller } from "@hotwired/stimulus"
|
|
|
35
38
|
* aria-hidden="true"></div>
|
|
36
39
|
* </div>
|
|
37
40
|
*
|
|
38
|
-
* @property {
|
|
39
|
-
* @property {
|
|
41
|
+
* @property {HTMLElement[]} triggerTargets - Toggle/collapse buttons that control the sidebar
|
|
42
|
+
* @property {HTMLElement} scrimTarget - The mobile overlay scrim element
|
|
40
43
|
*/
|
|
41
44
|
export default class extends Controller {
|
|
42
45
|
static targets = ["trigger", "scrim"]
|
|
43
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Sets up event delegation for auto-closing the sidebar on mobile
|
|
49
|
+
* when a nav item link is clicked.
|
|
50
|
+
*/
|
|
51
|
+
connect() {
|
|
52
|
+
this._handleNavClick = (event) => {
|
|
53
|
+
// Matches both: nav-item that IS a link (current Kiso markup: <a data-slot="nav-item">)
|
|
54
|
+
// and a link nested inside a nav-item (defensive for host app customization)
|
|
55
|
+
if (event.target.closest('[data-slot="nav-item"][href], [data-slot="nav-item"] a')) {
|
|
56
|
+
this.closeOnMobile()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
this.element.addEventListener("click", this._handleNavClick)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
disconnect() {
|
|
63
|
+
this.element.removeEventListener("click", this._handleNavClick)
|
|
64
|
+
}
|
|
65
|
+
|
|
44
66
|
/**
|
|
45
67
|
* Toggles the sidebar open/closed state.
|
|
46
68
|
*
|
|
@@ -56,8 +78,8 @@ export default class extends Controller {
|
|
|
56
78
|
/**
|
|
57
79
|
* Closes the sidebar on mobile viewports only.
|
|
58
80
|
*
|
|
59
|
-
* Connected to the scrim click event
|
|
60
|
-
* the
|
|
81
|
+
* Connected to the scrim click event and nav item click delegation.
|
|
82
|
+
* Dismisses the sidebar without affecting desktop layout.
|
|
61
83
|
*/
|
|
62
84
|
closeOnMobile() {
|
|
63
85
|
if (matchMedia("(max-width: 767px)").matches) {
|
|
@@ -30,9 +30,9 @@ import { Controller } from "@hotwired/stimulus"
|
|
|
30
30
|
* @property {HTMLElement} trackTarget - The background track element
|
|
31
31
|
* @property {HTMLElement} rangeTarget - The filled range portion
|
|
32
32
|
* @property {HTMLElement} thumbTarget - The draggable thumb handle
|
|
33
|
-
* @property {
|
|
34
|
-
* @property {
|
|
35
|
-
* @property {
|
|
33
|
+
* @property {number} minValue - Minimum slider value (default: 0)
|
|
34
|
+
* @property {number} maxValue - Maximum slider value (default: 100)
|
|
35
|
+
* @property {number} stepValue - Step increment (default: 1)
|
|
36
36
|
*
|
|
37
37
|
* @fires kiso--slider:change - When the slider value changes.
|
|
38
38
|
* Detail: `{ value: number }`
|
|
@@ -25,7 +25,8 @@ import { Controller } from "@hotwired/stimulus"
|
|
|
25
25
|
* <!-- kui(:select) with light/dark/system items -->
|
|
26
26
|
* </div>
|
|
27
27
|
*
|
|
28
|
-
* @fires kiso:theme-change on document.documentElement when theme changes
|
|
28
|
+
* @fires kiso:theme-change - Dispatched on `document.documentElement` when the theme changes.
|
|
29
|
+
* Detail: `{ theme: "light" | "dark" | "system" }`.
|
|
29
30
|
*/
|
|
30
31
|
export default class extends Controller {
|
|
31
32
|
/**
|
|
@@ -4,6 +4,8 @@ import { Controller } from "@hotwired/stimulus"
|
|
|
4
4
|
* Manages pressed state for a standalone toggle button.
|
|
5
5
|
* Toggles `data-state` between "on" and "off" and updates `aria-pressed`.
|
|
6
6
|
*
|
|
7
|
+
* For grouped toggles, use the `kiso--toggle-group` controller instead.
|
|
8
|
+
*
|
|
7
9
|
* @example
|
|
8
10
|
* <button data-controller="kiso--toggle"
|
|
9
11
|
* data-action="click->kiso--toggle#toggle"
|
|
@@ -77,6 +77,7 @@ export default class extends Controller {
|
|
|
77
77
|
* Wraps around at boundaries.
|
|
78
78
|
*
|
|
79
79
|
* @param {KeyboardEvent} event
|
|
80
|
+
* @private
|
|
80
81
|
*/
|
|
81
82
|
#handleKeydown = (event) => {
|
|
82
83
|
const items = this.itemTargets.filter((item) => !item.disabled)
|
|
@@ -113,6 +114,8 @@ export default class extends Controller {
|
|
|
113
114
|
* Dispatches a "change" event with the currently selected value(s).
|
|
114
115
|
* Single mode emits `{ value: string | null }`,
|
|
115
116
|
* multiple mode emits `{ value: string[] }`.
|
|
117
|
+
*
|
|
118
|
+
* @private
|
|
116
119
|
*/
|
|
117
120
|
#dispatchChange() {
|
|
118
121
|
const selectedValues = this.itemTargets
|
|
@@ -30,6 +30,9 @@ import { startPositioning } from "kiso-ui/utils/positioning"
|
|
|
30
30
|
* @property {HTMLElement} triggerTarget - Element that activates the tooltip on hover/focus
|
|
31
31
|
* @property {HTMLElement} contentTarget - The floating tooltip panel (popover)
|
|
32
32
|
* @property {HTMLElement} arrowTarget - Arrow element positioned by Floating UI
|
|
33
|
+
* @property {string} sideValue - Which side to place the tooltip: "top", "bottom", "left", or "right" (default: "top")
|
|
34
|
+
* @property {string} alignValue - Alignment along the side: "start", "center", or "end" (default: "center")
|
|
35
|
+
* @property {number} delayValue - Delay in milliseconds before showing the tooltip (default: 0)
|
|
33
36
|
*
|
|
34
37
|
* @fires kiso--tooltip:show - When the tooltip becomes visible
|
|
35
38
|
* @fires kiso--tooltip:hide - When the tooltip is hidden
|
|
@@ -1,8 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared focusable element utilities.
|
|
3
|
+
* Provides a CSS selector for querying focusable elements in the DOM.
|
|
4
|
+
*
|
|
5
|
+
* Used by popover, dropdown_menu, and other controllers that need
|
|
6
|
+
* focus trapping or focus management.
|
|
7
|
+
*
|
|
8
|
+
* @module utils/focusable
|
|
9
|
+
*/
|
|
10
|
+
|
|
1
11
|
/**
|
|
2
12
|
* CSS selector for all natively focusable elements that are not disabled
|
|
3
13
|
* or explicitly removed from the tab order.
|
|
4
14
|
*
|
|
5
15
|
* @type {string}
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const focusable = container.querySelectorAll(FOCUSABLE_SELECTOR)
|
|
19
|
+
* focusable[0]?.focus()
|
|
6
20
|
*/
|
|
7
21
|
export const FOCUSABLE_SELECTOR =
|
|
8
22
|
'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
@@ -10,11 +10,19 @@
|
|
|
10
10
|
* clearItems, then sets it on the item at `index` within `items` and
|
|
11
11
|
* scrolls it into view.
|
|
12
12
|
*
|
|
13
|
-
* @param {HTMLElement[]} clearItems - Items to remove the attribute from
|
|
13
|
+
* @param {HTMLElement[]} clearItems - Items to remove the attribute from (may differ from `items` to clear a broader set)
|
|
14
14
|
* @param {HTMLElement[]} items - Items to index into for highlighting
|
|
15
15
|
* @param {number} index - Index to highlight, or -1 to clear only
|
|
16
16
|
* @param {Object} [options]
|
|
17
17
|
* @param {string} [options.attr="data-highlighted"] - The attribute to toggle
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Highlight the third item, clearing all item targets first
|
|
21
|
+
* highlightItem(this.itemTargets, this._visibleEnabledItems, 2)
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Use a custom attribute for command palette selection
|
|
25
|
+
* highlightItem(this.itemTargets, enabledItems, 0, { attr: "data-selected" })
|
|
18
26
|
*/
|
|
19
27
|
export function highlightItem(clearItems, items, index, { attr = "data-highlighted" } = {}) {
|
|
20
28
|
clearItems.forEach((item) => item.removeAttribute(attr))
|
|
@@ -32,6 +40,12 @@ export function highlightItem(clearItems, items, index, { attr = "data-highlight
|
|
|
32
40
|
* @param {number} direction - +1 for next, -1 for previous
|
|
33
41
|
* @param {number} length - Total number of items
|
|
34
42
|
* @returns {number} The wrapped index, or -1 if length is 0
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* wrapIndex(2, 1, 5) // => 3
|
|
46
|
+
* wrapIndex(4, 1, 5) // => 0 (wraps to start)
|
|
47
|
+
* wrapIndex(0, -1, 5) // => 4 (wraps to end)
|
|
48
|
+
* wrapIndex(0, 1, 0) // => -1 (empty list)
|
|
35
49
|
*/
|
|
36
50
|
export function wrapIndex(current, direction, length) {
|
|
37
51
|
if (length === 0) return -1
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (icon: nil, color: :primary, variant: :soft, close: false, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Dismissible alert banner with optional icon. Composes with alert/title, alert/description,
|
|
3
|
+
and alert/actions sub-parts. The close: prop adds a Stimulus-powered dismiss button. %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
role: :alert,
|
|
4
6
|
class: Kiso::Themes::Alert.render(color: color, variant: variant, class: css_classes),
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
<%# locals: (open: false, size: :default, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Non-dismissible confirmation dialog using native <dialog> with showModal().
|
|
3
|
+
Requires role="alertdialog" for screen readers. Pass id: to enable automatic
|
|
4
|
+
aria-labelledby/aria-describedby linking with title and description sub-parts. %>
|
|
2
5
|
<%
|
|
3
6
|
# Store the dialog id on the view context so child sub-part partials
|
|
4
7
|
# (_title, _description) can auto-generate matching aria-labelledby /
|
|
5
|
-
# aria-describedby
|
|
6
|
-
#
|
|
8
|
+
# aria-describedby ids without requiring the caller to thread the id
|
|
9
|
+
# through each nested kui() call.
|
|
7
10
|
@_kiso_alert_dialog_id = component_options[:id]
|
|
8
11
|
aria = {}
|
|
9
12
|
if @_kiso_alert_dialog_id
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (center: false, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Top-level app layout wrapper. Composes with Header, Main, Footer sub-components.
|
|
3
|
+
Set center: true to constrain content width. %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
class: Kiso::Themes::App.render(center: center, class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "app"),
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
<%# locals: (src: nil, alt: "", text: nil, size: :md, color: nil, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
-
|
|
1
|
+
<%# locals: (src: nil, alt: "", text: nil, size: :md, color: nil, contrast_threshold: nil, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
+
<%# User avatar with image, text fallback, and optional status badge. Supports
|
|
3
|
+
arbitrary background colors via color: with automatic contrast text selection.
|
|
4
|
+
Yield a block to fully override internal structure, or use props for defaults. %>
|
|
5
|
+
<% text_color = Kiso::ColorUtils.contrast_text_color(color, threshold: contrast_threshold) if color %>
|
|
3
6
|
<%= content_tag :span,
|
|
4
7
|
class: Kiso::Themes::Avatar.render(size: size, class: css_classes),
|
|
5
8
|
style: (color ? "background-color: #{color}; color: #{text_color};" : nil),
|
|
6
9
|
data: kiso_prepare_options(component_options, slot: "avatar", size: size),
|
|
7
10
|
**component_options do %>
|
|
11
|
+
<%# Block override: if caller yields content, render it instead of the default image+fallback. %>
|
|
8
12
|
<% content = capture { yield }.presence %>
|
|
9
13
|
<% if content %>
|
|
10
14
|
<%= content %>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
<%# locals: (color: :primary, variant: :solid, size: :md, block: false,
|
|
2
2
|
type: :button, href: nil, method: nil, disabled: false,
|
|
3
3
|
form: {}, css_classes: "", **component_options) %>
|
|
4
|
+
<%# Polymorphic button that renders as <button>, <a>, or button_to depending on props.
|
|
5
|
+
With href: renders an anchor tag. With href: + method: (non-GET) renders a Rails
|
|
6
|
+
button_to form for safe non-GET navigation. Without href: renders a plain <button>. %>
|
|
4
7
|
<%
|
|
5
8
|
css = Kiso::Themes::Button.render(
|
|
6
9
|
color: color, variant: variant, size: size, block: block, class: css_classes)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (size: :md, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Light/dark mode toggle button. Swaps sun/moon icons via CSS visibility
|
|
3
|
+
controlled by the .dark class on <html>. Uses the kiso--theme Stimulus controller. %>
|
|
2
4
|
<%= content_tag :button,
|
|
3
5
|
class: Kiso::Themes::ColorModeButton.render(size: size, class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "color-mode-button",
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (size: :md, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Color mode dropdown with Light/Dark/System options. Composes a Select component
|
|
3
|
+
and dispatches kiso--select:change events to the kiso--theme controller. %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
class: Kiso::Themes::ColorModeSelect.render(class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "color-mode-select",
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<%# locals: (name: nil, multiple: false, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Autocomplete combobox with keyboard navigation and optional multi-select.
|
|
3
|
+
Composes with combobox/input, combobox/content, combobox/item sub-parts.
|
|
4
|
+
Pass name: to include a hidden input for form submission. %>
|
|
2
5
|
<%= content_tag :div,
|
|
3
6
|
class: Kiso::Themes::Combobox.render(class: css_classes),
|
|
4
7
|
data: kiso_prepare_options(component_options, slot: "combobox",
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Command palette with search filtering and keyboard navigation.
|
|
3
|
+
Composes with command/input, command/list, command/group, command/item sub-parts. %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
class: Kiso::Themes::Command.render(class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "command", controller: "kiso--command"),
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
<%# locals: (sidebar_open: nil, layout: :sidebar, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Root wrapper for the dashboard layout system. Reads sidebar state from cookies
|
|
3
|
+
by default, or accepts an explicit sidebar_open: override. Renders a scrim
|
|
4
|
+
overlay for mobile sidebar dismissal. %>
|
|
5
|
+
<%# Default to cookie-based sidebar state; explicit prop overrides. %>
|
|
2
6
|
<% sidebar_open = cookies[:sidebar_open] != "false" if sidebar_open.nil? %>
|
|
3
7
|
<%= content_tag :div,
|
|
4
8
|
class: Kiso::Themes::DashboardGroup.render(class: css_classes),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Top navigation bar for the dashboard layout. Typically contains sidebar toggle
|
|
3
|
+
buttons, breadcrumbs, and user actions. %>
|
|
2
4
|
<%= content_tag :header,
|
|
3
5
|
class: Kiso::Themes::DashboardNavbar.render(class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "dashboard-navbar"),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Main content area of the dashboard layout, adjacent to the sidebar. %>
|
|
2
3
|
<%= content_tag :main,
|
|
3
4
|
class: Kiso::Themes::DashboardPanel.render(class: css_classes),
|
|
4
5
|
data: kiso_prepare_options(component_options, slot: "dashboard-panel"),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Dashboard sidebar <aside> with a fixed id for aria-controls references.
|
|
3
|
+
The inner wrapper div provides the scrollable content area. %>
|
|
2
4
|
<%= content_tag :aside,
|
|
3
5
|
id: "dashboard-sidebar",
|
|
4
6
|
class: Kiso::Themes::DashboardSidebar.render(class: css_classes),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Secondary toolbar below the navbar. Composes with dashboard_toolbar/left
|
|
3
|
+
and dashboard_toolbar/right for split layouts. %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
class: Kiso::Themes::DashboardToolbar.render(class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "dashboard-toolbar"),
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<%# locals: (open: false, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Modal dialog using native <dialog> with showModal(). Dismissable via Escape
|
|
3
|
+
key or backdrop click (unlike AlertDialog). Composes with dialog/header,
|
|
4
|
+
dialog/title, dialog/description, dialog/body, dialog/footer, dialog/close. %>
|
|
2
5
|
<%= content_tag :dialog,
|
|
3
6
|
class: Kiso::Themes::Dialog.render(class: css_classes),
|
|
4
7
|
data: kiso_prepare_options(component_options, slot: "dialog",
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Dropdown menu with keyboard navigation, checkbox/radio items, and nested submenus.
|
|
3
|
+
Composes with dropdown_menu/trigger, dropdown_menu/content, dropdown_menu/item, etc. %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
class: Kiso::Themes::DropdownMenu.render(class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "dropdown-menu", controller: "kiso--dropdown-menu"),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Empty state placeholder. Composes with empty/media, empty/header, empty/title,
|
|
3
|
+
empty/description, empty/content, and empty/actions sub-parts. %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
class: Kiso::Themes::Empty.render(class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "empty"),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (orientation: :vertical, invalid: false, disabled: false, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Form field wrapper that groups a label, input, description, and error message.
|
|
3
|
+
Sets data-invalid and data-disabled attributes for CSS-driven state styling. %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
role: :group,
|
|
4
6
|
class: Kiso::Themes::Field.render(orientation: orientation, class: css_classes),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Vertical stack of Field components with consistent spacing. %>
|
|
2
3
|
<%= content_tag :div,
|
|
3
4
|
class: Kiso::Themes::FieldGroup.render(class: css_classes),
|
|
4
5
|
data: kiso_prepare_options(component_options, slot: "field-group"),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Native <fieldset> for grouping related form fields. Use with field_set/legend. %>
|
|
2
3
|
<%= content_tag :fieldset,
|
|
3
4
|
class: Kiso::Themes::FieldSet.render(class: css_classes),
|
|
4
5
|
data: kiso_prepare_options(component_options, slot: "field-set"),
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<%# locals: (length: 6, name: nil, id: nil, value: nil, pattern: "\\d", disabled: false, autocomplete: "one-time-code", aria_label: nil, css_classes: "", **component_options) %>
|
|
2
|
+
<%# One-time password input with individual character slots. A hidden real input
|
|
3
|
+
captures keystrokes while visible slot divs display each character. Compose
|
|
4
|
+
with input_otp/group and input_otp/slot sub-parts for the visual layout. %>
|
|
2
5
|
<%= content_tag :div,
|
|
3
6
|
class: Kiso::Themes::InputOtp.render(class: css_classes),
|
|
4
7
|
data: kiso_prepare_options(component_options, slot: "input-otp",
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Sidebar navigation container. Composes with nav/section, nav/section_title,
|
|
3
|
+
and nav/item sub-parts. Typically placed inside a dashboard_sidebar. %>
|
|
2
4
|
<%= content_tag :nav,
|
|
3
5
|
class: Kiso::Themes::Nav.render(class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "nav"),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (variant: :outline, icon: nil, title: nil, description: nil, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Page-level card with optional icon, title, and description props.
|
|
3
|
+
Yield a block to fully override the internal structure. %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
class: Kiso::Themes::PageCard.render(variant: variant, class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "page-card"),
|
|
@@ -9,6 +11,7 @@
|
|
|
9
11
|
<%= content_tag :div,
|
|
10
12
|
class: Kiso::Themes::PageCardWrapper.render(class: ui[:wrapper]),
|
|
11
13
|
data: { slot: "page-card-wrapper" } do %>
|
|
14
|
+
<%# Block override: yield replaces default icon/title/description layout. %>
|
|
12
15
|
<% content = capture { yield }.presence %>
|
|
13
16
|
<% if content %>
|
|
14
17
|
<%= content %>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (headline: nil, title: nil, description: nil, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Page header with optional headline, title, and description props.
|
|
3
|
+
Yield a block to fully override the internal structure (e.g., to add action buttons). %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
class: Kiso::Themes::PageHeader.render(class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "page-header"),
|
|
@@ -6,6 +8,7 @@
|
|
|
6
8
|
<%= content_tag :div,
|
|
7
9
|
class: Kiso::Themes::PageHeaderWrapper.render(class: ui[:wrapper]),
|
|
8
10
|
data: { slot: "page-header-wrapper" } do %>
|
|
11
|
+
<%# Block override: yield replaces default headline/title/description layout. %>
|
|
9
12
|
<% content = capture { yield }.presence %>
|
|
10
13
|
<% if content %>
|
|
11
14
|
<%= content %>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (orientation: :horizontal, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Page content section with horizontal or vertical orientation. Composes with
|
|
3
|
+
page_section/header, page_section/body, page_section/title, page_section/description. %>
|
|
2
4
|
<%= content_tag :section,
|
|
3
5
|
class: Kiso::Themes::PageSection.render(orientation: orientation, class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "page-section"),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Pagination navigation. Composes with pagination/content, pagination/item,
|
|
3
|
+
pagination/link, pagination/previous, pagination/next, pagination/ellipsis. %>
|
|
2
4
|
<%= content_tag :nav,
|
|
3
5
|
role: "navigation",
|
|
4
6
|
aria: {label: t("kiso.pagination.label")},
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Floating popover positioned via Floating UI. Uses position: relative as the
|
|
3
|
+
anchor reference for absolute positioning of the content panel.
|
|
4
|
+
Composes with popover/trigger, popover/anchor, and popover/content sub-parts. %>
|
|
2
5
|
<%= content_tag :div,
|
|
3
6
|
class: css_classes.presence,
|
|
4
7
|
data: kiso_prepare_options(component_options, slot: "popover", controller: "kiso--popover"),
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<%# locals: (name: nil, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Custom select with keyboard navigation and Stimulus-driven open/close.
|
|
3
|
+
Pass name: to include a hidden input for form submission. For a native
|
|
4
|
+
<select>, use select_native instead. %>
|
|
2
5
|
<%= content_tag :div,
|
|
3
6
|
class: Kiso::Themes::Select.render(class: css_classes),
|
|
4
7
|
data: kiso_prepare_options(component_options, slot: "select", controller: "kiso--select"),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (variant: :outline, size: :md, disabled: false, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Native <select> element with a styled chevron icon overlay. Yield <option>
|
|
3
|
+
elements as the block content. For a custom dropdown, use select instead. %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
class: Kiso::Themes::SelectNativeWrapper.render(class: ui[:wrapper]),
|
|
4
6
|
data: {slot: "select-native-wrapper"} do %>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (orientation: :horizontal, decorative: true, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Visual divider line. Set decorative: false to expose a semantic separator
|
|
3
|
+
role to assistive technology. %>
|
|
2
4
|
<%= tag.div(
|
|
3
5
|
role: (decorative ? "none" : "separator"),
|
|
4
6
|
aria: (decorative ? {} : { orientation: orientation }),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Animated placeholder for content that is loading. Style dimensions via css_classes:. %>
|
|
2
3
|
<%= tag.div(
|
|
3
4
|
class: Kiso::Themes::Skeleton.render(class: css_classes),
|
|
4
5
|
data: kiso_prepare_options(component_options, slot: "skeleton"),
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
<%# locals: (min: 0, max: 100, step: 1, value: nil, name: nil, id: nil, disabled: false, size: :md, aria_label: nil, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Range slider with a hidden native <input type="range"> for form submission and an
|
|
3
|
+
accessible ARIA slider thumb for keyboard/pointer interaction. The Stimulus controller
|
|
4
|
+
syncs the visual position with the hidden input value. %>
|
|
2
5
|
<% slider_value = value || min %>
|
|
6
|
+
<%# Calculate initial thumb/range position as a percentage for inline styles. %>
|
|
3
7
|
<% percent = ((slider_value.to_f - min) / (max - min) * 100).clamp(0, 100) %>
|
|
4
8
|
<%= content_tag :div,
|
|
5
9
|
class: Kiso::Themes::Slider.render(class: css_classes),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (label: nil, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Animated loading spinner rendered via kiso_component_icon. Uses role="status"
|
|
3
|
+
for screen reader announcements. %>
|
|
2
4
|
<%= kiso_component_icon(:spinner,
|
|
3
5
|
role: "status",
|
|
4
6
|
aria: { label: label || t("kiso.spinner.loading") },
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (variant: :outline, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Metric display card. Composes with stats_card/header, stats_card/label,
|
|
3
|
+
stats_card/value, and stats_card/description sub-parts. %>
|
|
2
4
|
<%= content_tag :div,
|
|
3
5
|
class: Kiso::Themes::StatsCard.render(variant: variant, class: css_classes),
|
|
4
6
|
data: kiso_prepare_options(component_options, slot: "stats-card"),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<%# locals: (columns: 4, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Responsive grid layout for stats_card components. %>
|
|
2
3
|
<%= content_tag :div,
|
|
3
4
|
class: Kiso::Themes::StatsGrid.render(columns: columns, class: css_classes),
|
|
4
5
|
data: kiso_prepare_options(component_options, slot: "stats-grid"),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (color: :primary, size: :md, checked: false, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Toggle switch built on a hidden checkbox with role="switch". The <label> wraps
|
|
3
|
+
the hidden input and a visible thumb span, using peer-checked: for state styling. %>
|
|
2
4
|
<% component_options[:type] = :checkbox
|
|
3
5
|
component_options[:role] = :switch
|
|
4
6
|
component_options[:checked] = true if checked %>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<%# locals: (css_classes: "", **component_options) %>
|
|
2
|
+
<%# Data table wrapped in a horizontally-scrollable container. Composes with table/header,
|
|
3
|
+
table/body, table/row, table/head, table/cell, table/footer, and table/caption. %>
|
|
2
4
|
<div class="relative w-full overflow-x-auto">
|
|
3
5
|
<%= content_tag :table,
|
|
4
6
|
class: Kiso::Themes::Table.render(class: css_classes),
|