kiso 0.6.5.pre → 0.7.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/engine.css +1 -0
- data/app/assets/tailwind/kiso/progress.css +67 -0
- data/app/javascript/controllers/kiso/dropdown_menu_controller.js +5 -2
- data/app/javascript/controllers/kiso/tooltip_controller.js +12 -0
- data/app/views/kiso/components/_action_icon.html.erb +45 -0
- data/app/views/kiso/components/_button.html.erb +2 -1
- data/app/views/kiso/components/_progress.html.erb +74 -0
- data/app/views/kiso/components/dashboard_sidebar/_collapse.html.erb +5 -4
- data/config/locales/en.yml +4 -0
- data/lib/kiso/presets/rounded.rb +3 -0
- data/lib/kiso/presets/sharp.rb +7 -0
- data/lib/kiso/themes/action_icon.rb +38 -0
- data/lib/kiso/themes/dashboard.rb +1 -1
- data/lib/kiso/themes/pagination.rb +1 -1
- data/lib/kiso/themes/progress.rb +161 -0
- data/lib/kiso/themes/tooltip.rb +1 -1
- data/lib/kiso/version.rb +1 -1
- data/lib/kiso.rb +2 -0
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 53a2af001d842909751b3494e9fd0978a60c7cb62bf028a7a3461f195ebd6988
|
|
4
|
+
data.tar.gz: 5a6ce4a5958a2460be62ac17d2cc315b8e185f801c6d1801778f9b88e609cccc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 85ff1d9bbc10faa32d096149260d86ccb3feafa9a91673e8e8a8f9e479196166b4b244faa4d6f64db194a801ed33e25760c06b3673407038e845807b2dca1565
|
|
7
|
+
data.tar.gz: 86192d62578427cdf67dfc1e21028f8bf1f4accc208fdc2f65b3eb3179a780a244b40e39673fa214b9bf54b562bf466cb614ae5ca00a7f0a18846e40e84e23d4
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/* ── Progress ─────────────────────────────────────────────────────────
|
|
2
|
+
* Indeterminate animation keyframes for the progress indicator.
|
|
3
|
+
* 8 keyframes: 4 animation styles × 2 orientations (horizontal/vertical).
|
|
4
|
+
*
|
|
5
|
+
* Why CSS: @keyframes definitions and prefers-reduced-motion media
|
|
6
|
+
* queries cannot be expressed in ERB/Tailwind utilities.
|
|
7
|
+
* ──────────────────────────────────────────────────────────────────── */
|
|
8
|
+
|
|
9
|
+
/* === Carousel === */
|
|
10
|
+
|
|
11
|
+
@keyframes carousel {
|
|
12
|
+
0%, 100% { width: 50%; }
|
|
13
|
+
0% { transform: translateX(-100%); }
|
|
14
|
+
100% { transform: translateX(200%); }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@keyframes carousel-vertical {
|
|
18
|
+
0%, 100% { height: 50%; }
|
|
19
|
+
0% { transform: translateY(-100%); }
|
|
20
|
+
100% { transform: translateY(200%); }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* === Carousel Inverse === */
|
|
24
|
+
|
|
25
|
+
@keyframes carousel-inverse {
|
|
26
|
+
0%, 100% { width: 50%; }
|
|
27
|
+
0% { transform: translateX(200%); }
|
|
28
|
+
100% { transform: translateX(-100%); }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@keyframes carousel-inverse-vertical {
|
|
32
|
+
0%, 100% { height: 50%; }
|
|
33
|
+
0% { transform: translateY(200%); }
|
|
34
|
+
100% { transform: translateY(-100%); }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* === Swing === */
|
|
38
|
+
|
|
39
|
+
@keyframes swing {
|
|
40
|
+
0%, 100% { width: 50%; transform: translateX(-25%); }
|
|
41
|
+
50% { transform: translateX(125%); }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@keyframes swing-vertical {
|
|
45
|
+
0%, 100% { height: 50%; transform: translateY(-25%); }
|
|
46
|
+
50% { transform: translateY(125%); }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* === Elastic === */
|
|
50
|
+
|
|
51
|
+
@keyframes elastic {
|
|
52
|
+
0%, 100% { width: 50%; margin-left: 25%; }
|
|
53
|
+
50% { width: 90%; margin-left: 5%; }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@keyframes elastic-vertical {
|
|
57
|
+
0%, 100% { height: 50%; margin-top: 25%; }
|
|
58
|
+
50% { height: 90%; margin-top: 5%; }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* === Reduced motion === */
|
|
62
|
+
|
|
63
|
+
@media (prefers-reduced-motion: reduce) {
|
|
64
|
+
[data-slot="progress-indicator"][data-state="indeterminate"] {
|
|
65
|
+
animation-duration: 0s !important;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -461,13 +461,16 @@ export default class extends Controller {
|
|
|
461
461
|
}
|
|
462
462
|
|
|
463
463
|
/**
|
|
464
|
-
* Positions the dropdown content relative to the trigger
|
|
464
|
+
* Positions the dropdown content relative to the trigger using fixed
|
|
465
|
+
* positioning to escape ancestor overflow clipping (e.g., DashboardToolbar).
|
|
465
466
|
* Starts auto-updating on scroll/resize.
|
|
466
467
|
*
|
|
467
468
|
* @private
|
|
468
469
|
*/
|
|
469
470
|
_positionContent() {
|
|
470
|
-
this._cleanupPosition = startPositioning(this.triggerTarget, this.contentTarget
|
|
471
|
+
this._cleanupPosition = startPositioning(this.triggerTarget, this.contentTarget, {
|
|
472
|
+
strategy: "fixed",
|
|
473
|
+
})
|
|
471
474
|
}
|
|
472
475
|
|
|
473
476
|
/**
|
|
@@ -54,11 +54,23 @@ export default class extends Controller {
|
|
|
54
54
|
this._tooltipId = this.contentTarget.id || `tooltip-${crypto.randomUUID().slice(0, 8)}`
|
|
55
55
|
this.contentTarget.id = this._tooltipId
|
|
56
56
|
this._triggerEl.setAttribute("aria-describedby", this._tooltipId)
|
|
57
|
+
|
|
58
|
+
// Strip native title tooltip to prevent double tooltip
|
|
59
|
+
if (this._triggerEl.hasAttribute("title")) {
|
|
60
|
+
this._originalTitle = this._triggerEl.getAttribute("title")
|
|
61
|
+
this._triggerEl.removeAttribute("title")
|
|
62
|
+
}
|
|
57
63
|
}
|
|
58
64
|
|
|
59
65
|
disconnect() {
|
|
60
66
|
this._cleanupPosition?.()
|
|
61
67
|
this._clearTimers()
|
|
68
|
+
|
|
69
|
+
// Restore native title attribute
|
|
70
|
+
if (this._originalTitle != null) {
|
|
71
|
+
this._triggerEl.setAttribute("title", this._originalTitle)
|
|
72
|
+
this._originalTitle = null
|
|
73
|
+
}
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
/**
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<%# locals: (icon:, size: :sm, title: nil, href: nil, method: nil, disabled: false, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Inline icon-only action trigger. Polymorphic tag: <button> by default,
|
|
3
|
+
<a> with href:, or button_to with href: + method: (non-GET).
|
|
4
|
+
No fixed height — flows inline with surrounding text. %>
|
|
5
|
+
<%
|
|
6
|
+
css = Kiso::Themes::ActionIcon.render(size: size, class: css_classes)
|
|
7
|
+
label = title || t("kiso.action_icon.action")
|
|
8
|
+
data = kiso_prepare_options(component_options, slot: "action-icon")
|
|
9
|
+
use_button_to = href.present? && method.present? && method.to_s != "get"
|
|
10
|
+
%>
|
|
11
|
+
<% if use_button_to %>
|
|
12
|
+
<%= button_to href,
|
|
13
|
+
method: method,
|
|
14
|
+
class: css,
|
|
15
|
+
form_class: "contents",
|
|
16
|
+
data: data,
|
|
17
|
+
disabled: disabled || nil,
|
|
18
|
+
title: title,
|
|
19
|
+
aria: { label: label },
|
|
20
|
+
**component_options do %>
|
|
21
|
+
<%= kiso_icon(icon) %>
|
|
22
|
+
<% end %>
|
|
23
|
+
<% elsif href.present? %>
|
|
24
|
+
<% component_options[:href] = href
|
|
25
|
+
component_options[:"aria-disabled"] = true if disabled %>
|
|
26
|
+
<%= content_tag :a,
|
|
27
|
+
class: css,
|
|
28
|
+
data: data,
|
|
29
|
+
title: title,
|
|
30
|
+
aria: { label: label },
|
|
31
|
+
**component_options do %>
|
|
32
|
+
<%= kiso_icon(icon) %>
|
|
33
|
+
<% end %>
|
|
34
|
+
<% else %>
|
|
35
|
+
<%= content_tag :button,
|
|
36
|
+
class: css,
|
|
37
|
+
data: data,
|
|
38
|
+
type: "button",
|
|
39
|
+
disabled: disabled || nil,
|
|
40
|
+
title: title,
|
|
41
|
+
aria: { label: label },
|
|
42
|
+
**component_options do %>
|
|
43
|
+
<%= kiso_icon(icon) %>
|
|
44
|
+
<% end %>
|
|
45
|
+
<% end %>
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
<% end %>
|
|
38
38
|
<% else %>
|
|
39
39
|
<% component_options[:type] = type
|
|
40
|
-
component_options[:disabled] = true if is_disabled
|
|
40
|
+
component_options[:disabled] = true if is_disabled
|
|
41
|
+
component_options[:form] = form if form.is_a?(String) %>
|
|
41
42
|
<%= content_tag :button, class: css, data: data, **component_options do %>
|
|
42
43
|
<%= kiso_component_icon(:spinner, class: "animate-spin") if loading %>
|
|
43
44
|
<%= yield %>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<%# locals: (value: nil, max: 100, status: false, color: :primary, size: :md, animation: :carousel, orientation: :horizontal, inverted: false, ui: {}, css_classes: "", **component_options) %>
|
|
2
|
+
<%# Div-based progress bar with optional status text and step labels.
|
|
3
|
+
Indeterminate state when value: is nil (animated indicator via CSS).
|
|
4
|
+
Steps mode when max: is an array of labels. %>
|
|
5
|
+
<% is_indeterminate = value.nil? %>
|
|
6
|
+
<% has_steps = max.is_a?(Array) %>
|
|
7
|
+
<% real_max = has_steps ? [max.length - 1, 1].max : [max.to_i, 1].max %>
|
|
8
|
+
<% percent = is_indeterminate ? 0 : ((value.to_f / real_max) * 100).clamp(0, 100) %>
|
|
9
|
+
<%
|
|
10
|
+
vertical = orientation == :vertical
|
|
11
|
+
|
|
12
|
+
# Indicator transform
|
|
13
|
+
if is_indeterminate
|
|
14
|
+
indicator_style = nil
|
|
15
|
+
elsif vertical
|
|
16
|
+
indicator_style = inverted ? "transform: translateY(#{100 - percent}%)" : "transform: translateY(-#{100 - percent}%)"
|
|
17
|
+
else
|
|
18
|
+
indicator_style = inverted ? "transform: translateX(#{100 - percent}%)" : "transform: translateX(-#{100 - percent}%)"
|
|
19
|
+
end
|
|
20
|
+
%>
|
|
21
|
+
<%= content_tag :div,
|
|
22
|
+
class: Kiso::Themes::Progress.render(orientation: orientation, class: css_classes),
|
|
23
|
+
data: kiso_prepare_options(component_options, slot: "progress", orientation: orientation),
|
|
24
|
+
**component_options do %>
|
|
25
|
+
<% if !is_indeterminate && status %>
|
|
26
|
+
<%= tag.div(
|
|
27
|
+
class: Kiso::Themes::ProgressStatus.render(orientation: orientation, size: size, class: ui[:status]),
|
|
28
|
+
style: vertical ? "height: #{percent}%" : "width: #{percent}%",
|
|
29
|
+
data: {slot: "progress-status"}) do %>
|
|
30
|
+
<%= "#{percent.round}%" %>
|
|
31
|
+
<% end %>
|
|
32
|
+
<% end %>
|
|
33
|
+
<%= tag.div(
|
|
34
|
+
class: Kiso::Themes::ProgressTrack.render(orientation: orientation, size: size, class: ui[:track]),
|
|
35
|
+
role: "progressbar",
|
|
36
|
+
aria: {
|
|
37
|
+
valuenow: (is_indeterminate ? nil : value),
|
|
38
|
+
valuemin: 0,
|
|
39
|
+
valuemax: real_max,
|
|
40
|
+
label: component_options.dig(:aria, :label) || t("kiso.progress.label")
|
|
41
|
+
},
|
|
42
|
+
style: "transform: translateZ(0)",
|
|
43
|
+
data: {slot: "progress-track"}) do %>
|
|
44
|
+
<%= tag.div(
|
|
45
|
+
class: Kiso::Themes::ProgressIndicator.render(color: color, animation: animation, orientation: orientation, class: ui[:indicator]),
|
|
46
|
+
style: indicator_style,
|
|
47
|
+
data: {
|
|
48
|
+
slot: "progress-indicator",
|
|
49
|
+
state: is_indeterminate ? "indeterminate" : "loading"
|
|
50
|
+
}) %>
|
|
51
|
+
<% end %>
|
|
52
|
+
<% if has_steps %>
|
|
53
|
+
<%= tag.div(
|
|
54
|
+
class: Kiso::Themes::ProgressSteps.render(color: color, size: size, class: ui[:steps]),
|
|
55
|
+
data: {slot: "progress-steps"}) do %>
|
|
56
|
+
<% max.each_with_index do |step_label, index| %>
|
|
57
|
+
<%
|
|
58
|
+
step_variant = if index == value && index == 0
|
|
59
|
+
:first
|
|
60
|
+
elsif index == value && index == real_max
|
|
61
|
+
:last
|
|
62
|
+
elsif index == value
|
|
63
|
+
:active
|
|
64
|
+
else
|
|
65
|
+
:other
|
|
66
|
+
end
|
|
67
|
+
%>
|
|
68
|
+
<%= tag.div(step_label,
|
|
69
|
+
class: Kiso::Themes::ProgressStep.render(step: step_variant, class: ui[:step]),
|
|
70
|
+
data: {slot: "progress-step"}) %>
|
|
71
|
+
<% end %>
|
|
72
|
+
<% end %>
|
|
73
|
+
<% end %>
|
|
74
|
+
<% end %>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
<%# locals: (css_classes: "", **component_options) %>
|
|
1
|
+
<%# locals: (open_icon: nil, closed_icon: nil, css_classes: "", **component_options) %>
|
|
2
2
|
<%# Sidebar collapse toggle for desktop. Shows open/closed panel icons that swap
|
|
3
|
-
visibility based on sidebar state via CSS. Placed inside the sidebar itself.
|
|
3
|
+
visibility based on sidebar state via CSS. Placed inside the sidebar itself.
|
|
4
|
+
Pass open_icon: / closed_icon: to override the default panel icons per-instance. %>
|
|
4
5
|
<%= content_tag :button,
|
|
5
6
|
class: Kiso::Themes::DashboardSidebarCollapse.render(class: css_classes),
|
|
6
7
|
data: kiso_prepare_options(component_options, slot: "dashboard-sidebar-collapse",
|
|
@@ -9,6 +10,6 @@
|
|
|
9
10
|
aria: { label: t("kiso.dashboard_sidebar.collapse"), expanded: "false", controls: "dashboard-sidebar" },
|
|
10
11
|
type: "button",
|
|
11
12
|
**component_options do %>
|
|
12
|
-
<span data-slot="collapse-icon-open"><%= kiso_component_icon(:panel_left_close) %></span>
|
|
13
|
-
<span data-slot="collapse-icon-closed"><%= kiso_component_icon(:panel_left_open) %></span>
|
|
13
|
+
<span data-slot="collapse-icon-open"><%= open_icon || kiso_component_icon(:panel_left_close) %></span>
|
|
14
|
+
<span data-slot="collapse-icon-closed"><%= closed_icon || kiso_component_icon(:panel_left_open) %></span>
|
|
14
15
|
<% end %>
|
data/config/locales/en.yml
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
en:
|
|
2
2
|
kiso:
|
|
3
|
+
action_icon:
|
|
4
|
+
action: "Action"
|
|
3
5
|
alert:
|
|
4
6
|
dismiss: "Dismiss"
|
|
5
7
|
breadcrumb:
|
|
@@ -28,6 +30,8 @@ en:
|
|
|
28
30
|
loading: "Loading"
|
|
29
31
|
tooltip:
|
|
30
32
|
label: "Tooltip"
|
|
33
|
+
progress:
|
|
34
|
+
label: "Progress"
|
|
31
35
|
pagination:
|
|
32
36
|
label: "pagination"
|
|
33
37
|
more_pages: "More pages"
|
data/lib/kiso/presets/rounded.rb
CHANGED
|
@@ -10,6 +10,9 @@ module Kiso
|
|
|
10
10
|
# - Checkbox — uses rounded-[4px] for checkmark alignment
|
|
11
11
|
# - Shared::CHECKABLE_ITEM — uses rounded-sm for menu items (structural)
|
|
12
12
|
ROUNDED = {
|
|
13
|
+
# ActionIcon: rounded-md → rounded-full
|
|
14
|
+
action_icon: {base: "rounded-full"},
|
|
15
|
+
|
|
13
16
|
# Buttons: rounded-md → rounded-full (pill shape)
|
|
14
17
|
button: {
|
|
15
18
|
variants: {
|
data/lib/kiso/presets/sharp.rb
CHANGED
|
@@ -5,6 +5,9 @@ module Kiso
|
|
|
5
5
|
# No border-radius anywhere — geometric, brutalist aesthetic.
|
|
6
6
|
# Applies rounded-none to every component that has border-radius.
|
|
7
7
|
SHARP = {
|
|
8
|
+
# ActionIcon: rounded-md → rounded-none
|
|
9
|
+
action_icon: {base: "rounded-none"},
|
|
10
|
+
|
|
8
11
|
# Buttons: rounded-md → rounded-none
|
|
9
12
|
button: {
|
|
10
13
|
variants: {
|
|
@@ -136,6 +139,10 @@ module Kiso
|
|
|
136
139
|
slider_track: {base: "rounded-none"},
|
|
137
140
|
slider_thumb: {base: "rounded-none"},
|
|
138
141
|
|
|
142
|
+
# Progress: rounded-full → rounded-none
|
|
143
|
+
progress_track: {base: "rounded-none"},
|
|
144
|
+
progress_indicator: {base: "rounded-none"},
|
|
145
|
+
|
|
139
146
|
# RadioGroup indicator: rounded-full → rounded-none
|
|
140
147
|
radio_group_item: {base: "rounded-none"},
|
|
141
148
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Inline icon-only action trigger for table cells, card headers,
|
|
4
|
+
# and text rows.
|
|
5
|
+
#
|
|
6
|
+
# Quiet by default — muted foreground that brightens on hover with
|
|
7
|
+
# a subtle background. No fixed height; flows inline with
|
|
8
|
+
# surrounding text.
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# ActionIcon.render(size: :sm)
|
|
12
|
+
#
|
|
13
|
+
# Variants:
|
|
14
|
+
# - +size+ — :xs, :sm (default), :md
|
|
15
|
+
#
|
|
16
|
+
# shadcn base: n/a (no shadcn equivalent — inspired by Mantine ActionIcon
|
|
17
|
+
# and Outport's appui(:icon_action))
|
|
18
|
+
ActionIcon = ClassVariants.build(
|
|
19
|
+
base: "inline-flex items-center justify-center " \
|
|
20
|
+
"text-muted-foreground hover:text-foreground " \
|
|
21
|
+
"hover:bg-accent rounded-md " \
|
|
22
|
+
"cursor-pointer transition-colors duration-150 " \
|
|
23
|
+
"disabled:pointer-events-none disabled:opacity-50 " \
|
|
24
|
+
"aria-disabled:cursor-not-allowed aria-disabled:opacity-50 " \
|
|
25
|
+
"focus-visible:outline-2 focus-visible:outline-offset-2 " \
|
|
26
|
+
"focus-visible:outline-inverted " \
|
|
27
|
+
"#{Shared::SVG_BASE}",
|
|
28
|
+
variants: {
|
|
29
|
+
size: {
|
|
30
|
+
xs: "p-0.5 [&_svg:not([class*='size-'])]:size-3",
|
|
31
|
+
sm: "p-1 [&_svg:not([class*='size-'])]:size-3.5",
|
|
32
|
+
md: "p-1.5 [&_svg:not([class*='size-'])]:size-4"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
defaults: {size: :sm}
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -37,7 +37,7 @@ module Kiso
|
|
|
37
37
|
|
|
38
38
|
# Flex row container for pagination items.
|
|
39
39
|
PaginationContent = ClassVariants.build(
|
|
40
|
-
base: "flex flex-row items-center gap-1"
|
|
40
|
+
base: "flex flex-row flex-wrap items-center justify-center gap-1"
|
|
41
41
|
)
|
|
42
42
|
|
|
43
43
|
# Wrapper for a single pagination element (link, ellipsis, etc.).
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Visual progress bar with color, size, and orientation axes.
|
|
4
|
+
#
|
|
5
|
+
# Div-based structure (not native <progress>) for full Tailwind control.
|
|
6
|
+
# Optional status percentage text and step labels (when +max:+ is an array).
|
|
7
|
+
# Indeterminate animation when +value:+ is nil.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# Progress.render(orientation: :horizontal)
|
|
11
|
+
#
|
|
12
|
+
# Variants:
|
|
13
|
+
# - +orientation+ — :horizontal (default), :vertical
|
|
14
|
+
#
|
|
15
|
+
# Sub-parts: {ProgressTrack}, {ProgressIndicator}, {ProgressStatus},
|
|
16
|
+
# {ProgressSteps}, {ProgressStep}
|
|
17
|
+
#
|
|
18
|
+
# shadcn base: (no direct equivalent — shadcn wraps in Radix ProgressRoot)
|
|
19
|
+
Progress = ClassVariants.build(
|
|
20
|
+
base: "text-foreground gap-2",
|
|
21
|
+
variants: {
|
|
22
|
+
orientation: {
|
|
23
|
+
horizontal: "w-full flex flex-col",
|
|
24
|
+
vertical: "h-full flex flex-row-reverse"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
defaults: {orientation: :horizontal}
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Track (bar background) with orientation × size compound variants.
|
|
31
|
+
#
|
|
32
|
+
# shadcn base: bg-primary/20 relative h-2 w-full overflow-hidden rounded-full
|
|
33
|
+
ProgressTrack = ClassVariants.build(
|
|
34
|
+
base: "relative overflow-hidden rounded-full bg-accented",
|
|
35
|
+
variants: {
|
|
36
|
+
orientation: {
|
|
37
|
+
horizontal: "w-full",
|
|
38
|
+
vertical: "h-full"
|
|
39
|
+
},
|
|
40
|
+
size: {
|
|
41
|
+
xs: "", sm: "", md: "", lg: "", xl: ""
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
compound_variants: [
|
|
45
|
+
# == horizontal sizes (height) ==
|
|
46
|
+
{orientation: :horizontal, size: :xs, class: "h-0.5"},
|
|
47
|
+
{orientation: :horizontal, size: :sm, class: "h-1"},
|
|
48
|
+
{orientation: :horizontal, size: :md, class: "h-2"},
|
|
49
|
+
{orientation: :horizontal, size: :lg, class: "h-3"},
|
|
50
|
+
{orientation: :horizontal, size: :xl, class: "h-4"},
|
|
51
|
+
# == vertical sizes (width) ==
|
|
52
|
+
{orientation: :vertical, size: :xs, class: "w-0.5"},
|
|
53
|
+
{orientation: :vertical, size: :sm, class: "w-1"},
|
|
54
|
+
{orientation: :vertical, size: :md, class: "w-2"},
|
|
55
|
+
{orientation: :vertical, size: :lg, class: "w-3"},
|
|
56
|
+
{orientation: :vertical, size: :xl, class: "w-4"}
|
|
57
|
+
],
|
|
58
|
+
defaults: {orientation: :horizontal, size: :md}
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Indicator (fill bar) — color axis maps directly to bg-{color}.
|
|
62
|
+
# No variant axis (solid/outline/soft/subtle) — just direct color.
|
|
63
|
+
# Indeterminate animations gated by data-[state=indeterminate]: selector
|
|
64
|
+
# so the class is always present but only activates when indeterminate.
|
|
65
|
+
#
|
|
66
|
+
# shadcn base: bg-primary h-full w-full flex-1 transition-all
|
|
67
|
+
ProgressIndicator = ClassVariants.build(
|
|
68
|
+
base: "rounded-full size-full transition-transform duration-200 ease-out",
|
|
69
|
+
variants: {
|
|
70
|
+
color: {
|
|
71
|
+
primary: "bg-primary",
|
|
72
|
+
secondary: "bg-secondary",
|
|
73
|
+
success: "bg-success",
|
|
74
|
+
info: "bg-info",
|
|
75
|
+
warning: "bg-warning",
|
|
76
|
+
error: "bg-error",
|
|
77
|
+
neutral: "bg-inverted"
|
|
78
|
+
},
|
|
79
|
+
animation: {
|
|
80
|
+
carousel: "", carousel_inverse: "", swing: "", elastic: ""
|
|
81
|
+
},
|
|
82
|
+
orientation: {
|
|
83
|
+
horizontal: "", vertical: ""
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
compound_variants: [
|
|
87
|
+
# == indeterminate animation: horizontal ==
|
|
88
|
+
{animation: :carousel, orientation: :horizontal,
|
|
89
|
+
class: "data-[state=indeterminate]:animate-[carousel_2s_ease-in-out_infinite]"},
|
|
90
|
+
{animation: :carousel_inverse, orientation: :horizontal,
|
|
91
|
+
class: "data-[state=indeterminate]:animate-[carousel-inverse_2s_ease-in-out_infinite]"},
|
|
92
|
+
{animation: :swing, orientation: :horizontal,
|
|
93
|
+
class: "data-[state=indeterminate]:animate-[swing_2s_ease-in-out_infinite]"},
|
|
94
|
+
{animation: :elastic, orientation: :horizontal,
|
|
95
|
+
class: "data-[state=indeterminate]:animate-[elastic_2s_ease-in-out_infinite]"},
|
|
96
|
+
# == indeterminate animation: vertical ==
|
|
97
|
+
{animation: :carousel, orientation: :vertical,
|
|
98
|
+
class: "data-[state=indeterminate]:animate-[carousel-vertical_2s_ease-in-out_infinite]"},
|
|
99
|
+
{animation: :carousel_inverse, orientation: :vertical,
|
|
100
|
+
class: "data-[state=indeterminate]:animate-[carousel-inverse-vertical_2s_ease-in-out_infinite]"},
|
|
101
|
+
{animation: :swing, orientation: :vertical,
|
|
102
|
+
class: "data-[state=indeterminate]:animate-[swing-vertical_2s_ease-in-out_infinite]"},
|
|
103
|
+
{animation: :elastic, orientation: :vertical,
|
|
104
|
+
class: "data-[state=indeterminate]:animate-[elastic-vertical_2s_ease-in-out_infinite]"}
|
|
105
|
+
],
|
|
106
|
+
defaults: {color: :primary, animation: :carousel, orientation: :horizontal}
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# Status text showing percentage above/beside the bar.
|
|
110
|
+
ProgressStatus = ClassVariants.build(
|
|
111
|
+
base: "flex text-muted-foreground transition-[width] duration-200",
|
|
112
|
+
variants: {
|
|
113
|
+
orientation: {
|
|
114
|
+
horizontal: "flex-row items-center justify-end min-w-fit",
|
|
115
|
+
vertical: "flex-col justify-end min-h-fit"
|
|
116
|
+
},
|
|
117
|
+
size: {
|
|
118
|
+
xs: "text-xs", sm: "text-xs", md: "text-sm", lg: "text-sm", xl: "text-base"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
defaults: {orientation: :horizontal, size: :md}
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# Container for step labels — grid overlay technique.
|
|
125
|
+
ProgressSteps = ClassVariants.build(
|
|
126
|
+
base: "grid items-end",
|
|
127
|
+
variants: {
|
|
128
|
+
color: {
|
|
129
|
+
primary: "text-primary",
|
|
130
|
+
secondary: "text-secondary",
|
|
131
|
+
success: "text-success",
|
|
132
|
+
info: "text-info",
|
|
133
|
+
warning: "text-warning",
|
|
134
|
+
error: "text-error",
|
|
135
|
+
# text-inverted (not text-inverted-foreground) — step labels sit on
|
|
136
|
+
# the page background, so we want dark-on-light / light-on-dark text.
|
|
137
|
+
neutral: "text-inverted"
|
|
138
|
+
},
|
|
139
|
+
size: {
|
|
140
|
+
xs: "text-xs", sm: "text-xs", md: "text-sm", lg: "text-sm", xl: "text-base"
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
defaults: {color: :primary, size: :md}
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# Individual step label — stacked in same grid cell via row/col-start-1.
|
|
147
|
+
# Only the active step is visible (opacity-100), others hidden (opacity-0).
|
|
148
|
+
ProgressStep = ClassVariants.build(
|
|
149
|
+
base: "truncate text-end row-start-1 col-start-1 transition-opacity",
|
|
150
|
+
variants: {
|
|
151
|
+
step: {
|
|
152
|
+
active: "opacity-100",
|
|
153
|
+
first: "opacity-50",
|
|
154
|
+
other: "opacity-0",
|
|
155
|
+
last: ""
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
defaults: {step: :other}
|
|
159
|
+
)
|
|
160
|
+
end
|
|
161
|
+
end
|
data/lib/kiso/themes/tooltip.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Kiso
|
|
|
12
12
|
# Kiso: bg-inverted text-inverted-foreground (semantic equivalents)
|
|
13
13
|
TooltipContent = ClassVariants.build(
|
|
14
14
|
base: "bg-inverted text-inverted-foreground px-3 py-1.5 text-xs rounded-md " \
|
|
15
|
-
"flex items-center gap-1.5 select-none w-max max-w-xs"
|
|
15
|
+
"flex items-center gap-1.5 select-none w-max max-w-xs overflow-hidden"
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
# Arrow element pointing from tooltip content to the trigger.
|
data/lib/kiso/version.rb
CHANGED
data/lib/kiso.rb
CHANGED
|
@@ -11,6 +11,7 @@ require "kiso/propshaft_tailwind_stub_filter"
|
|
|
11
11
|
require "kiso/engine"
|
|
12
12
|
require "kiso/themes/shared"
|
|
13
13
|
require "kiso/themes/badge"
|
|
14
|
+
require "kiso/themes/action_icon"
|
|
14
15
|
require "kiso/themes/alert"
|
|
15
16
|
require "kiso/themes/aspect_ratio"
|
|
16
17
|
require "kiso/themes/button"
|
|
@@ -53,6 +54,7 @@ require "kiso/themes/skeleton"
|
|
|
53
54
|
require "kiso/themes/spinner"
|
|
54
55
|
require "kiso/themes/tooltip"
|
|
55
56
|
require "kiso/themes/slider"
|
|
57
|
+
require "kiso/themes/progress"
|
|
56
58
|
require "kiso/themes/layout"
|
|
57
59
|
require "kiso/icons"
|
|
58
60
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kiso
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0.pre
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Steve Clarke
|
|
@@ -91,6 +91,7 @@ files:
|
|
|
91
91
|
- app/assets/tailwind/kiso/palettes/orange.css
|
|
92
92
|
- app/assets/tailwind/kiso/palettes/violet.css
|
|
93
93
|
- app/assets/tailwind/kiso/palettes/zinc.css
|
|
94
|
+
- app/assets/tailwind/kiso/progress.css
|
|
94
95
|
- app/assets/tailwind/kiso/radio-group.css
|
|
95
96
|
- app/assets/tailwind/kiso/slider.css
|
|
96
97
|
- app/assets/tailwind/kiso/tooltip.css
|
|
@@ -123,6 +124,7 @@ files:
|
|
|
123
124
|
- app/javascript/kiso/utils/positioning.js
|
|
124
125
|
- app/javascript/kiso/vendor/floating-ui-core.js
|
|
125
126
|
- app/javascript/kiso/vendor/floating-ui-dom.js
|
|
127
|
+
- app/views/kiso/components/_action_icon.html.erb
|
|
126
128
|
- app/views/kiso/components/_alert.html.erb
|
|
127
129
|
- app/views/kiso/components/_alert_dialog.html.erb
|
|
128
130
|
- app/views/kiso/components/_app.html.erb
|
|
@@ -166,6 +168,7 @@ files:
|
|
|
166
168
|
- app/views/kiso/components/_page_section.html.erb
|
|
167
169
|
- app/views/kiso/components/_pagination.html.erb
|
|
168
170
|
- app/views/kiso/components/_popover.html.erb
|
|
171
|
+
- app/views/kiso/components/_progress.html.erb
|
|
169
172
|
- app/views/kiso/components/_radio_group.html.erb
|
|
170
173
|
- app/views/kiso/components/_select.html.erb
|
|
171
174
|
- app/views/kiso/components/_select_native.html.erb
|
|
@@ -356,6 +359,7 @@ files:
|
|
|
356
359
|
- lib/kiso/presets/sharp.rb
|
|
357
360
|
- lib/kiso/propshaft_tailwind_stub_filter.rb
|
|
358
361
|
- lib/kiso/theme_overrides.rb
|
|
362
|
+
- lib/kiso/themes/action_icon.rb
|
|
359
363
|
- lib/kiso/themes/alert.rb
|
|
360
364
|
- lib/kiso/themes/alert_dialog.rb
|
|
361
365
|
- lib/kiso/themes/aspect_ratio.rb
|
|
@@ -386,6 +390,7 @@ files:
|
|
|
386
390
|
- lib/kiso/themes/page.rb
|
|
387
391
|
- lib/kiso/themes/pagination.rb
|
|
388
392
|
- lib/kiso/themes/popover.rb
|
|
393
|
+
- lib/kiso/themes/progress.rb
|
|
389
394
|
- lib/kiso/themes/radio_group.rb
|
|
390
395
|
- lib/kiso/themes/select.rb
|
|
391
396
|
- lib/kiso/themes/select_native.rb
|