kiso 0.3.0.pre → 0.4.1.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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -1
  3. data/README.md +16 -3
  4. data/app/assets/tailwind/kiso/engine.css +40 -28
  5. data/app/assets/tailwind/kiso/palettes/blue.css +65 -0
  6. data/app/assets/tailwind/kiso/palettes/green.css +65 -0
  7. data/app/assets/tailwind/kiso/palettes/orange.css +65 -0
  8. data/app/assets/tailwind/kiso/palettes/violet.css +65 -0
  9. data/app/assets/tailwind/kiso/palettes/zinc.css +65 -0
  10. data/app/helpers/kiso/app_component_helper.rb +63 -0
  11. data/app/helpers/kiso/component_helper.rb +140 -24
  12. data/app/helpers/kiso/ui_context_helper.rb +59 -0
  13. data/app/javascript/controllers/kiso/alert_controller.js +33 -0
  14. data/app/javascript/controllers/kiso/index.js +3 -0
  15. data/app/views/kiso/components/_alert.html.erb +19 -3
  16. data/app/views/kiso/components/_alert_dialog.html.erb +2 -2
  17. data/app/views/kiso/components/_app.html.erb +7 -0
  18. data/app/views/kiso/components/_avatar.html.erb +3 -3
  19. data/app/views/kiso/components/_breadcrumb.html.erb +1 -1
  20. data/app/views/kiso/components/_color_mode_button.html.erb +1 -1
  21. data/app/views/kiso/components/_color_mode_select.html.erb +4 -4
  22. data/app/views/kiso/components/_container.html.erb +7 -0
  23. data/app/views/kiso/components/_dashboard_sidebar.html.erb +1 -1
  24. data/app/views/kiso/components/_dialog.html.erb +2 -2
  25. data/app/views/kiso/components/_footer.html.erb +7 -0
  26. data/app/views/kiso/components/_header.html.erb +7 -0
  27. data/app/views/kiso/components/_main.html.erb +7 -0
  28. data/app/views/kiso/components/_page.html.erb +7 -0
  29. data/app/views/kiso/components/_page_body.html.erb +7 -0
  30. data/app/views/kiso/components/_page_card.html.erb +40 -0
  31. data/app/views/kiso/components/_page_grid.html.erb +7 -0
  32. data/app/views/kiso/components/_page_header.html.erb +38 -0
  33. data/app/views/kiso/components/_page_section.html.erb +11 -0
  34. data/app/views/kiso/components/_pagination.html.erb +1 -1
  35. data/app/views/kiso/components/_select_native.html.erb +3 -3
  36. data/app/views/kiso/components/_skeleton.html.erb +5 -0
  37. data/app/views/kiso/components/_slider.html.erb +4 -4
  38. data/app/views/kiso/components/_switch.html.erb +2 -2
  39. data/app/views/kiso/components/alert/_actions.html.erb +7 -0
  40. data/app/views/kiso/components/breadcrumb/_ellipsis.html.erb +1 -1
  41. data/app/views/kiso/components/combobox/_input.html.erb +1 -1
  42. data/app/views/kiso/components/combobox/_item.html.erb +2 -2
  43. data/app/views/kiso/components/combobox/_list.html.erb +2 -1
  44. data/app/views/kiso/components/command/_group.html.erb +2 -2
  45. data/app/views/kiso/components/command/_input.html.erb +3 -2
  46. data/app/views/kiso/components/command/_list.html.erb +2 -1
  47. data/app/views/kiso/components/dashboard_navbar/_toggle.html.erb +1 -1
  48. data/app/views/kiso/components/dashboard_sidebar/_collapse.html.erb +1 -1
  49. data/app/views/kiso/components/dashboard_sidebar/_toggle.html.erb +1 -1
  50. data/app/views/kiso/components/dialog/_close.html.erb +1 -1
  51. data/app/views/kiso/components/nav/_item.html.erb +2 -2
  52. data/app/views/kiso/components/nav/_section.html.erb +5 -5
  53. data/app/views/kiso/components/page/_center.html.erb +7 -0
  54. data/app/views/kiso/components/page/_left.html.erb +7 -0
  55. data/app/views/kiso/components/page/_right.html.erb +7 -0
  56. data/app/views/kiso/components/page_card/_body.html.erb +7 -0
  57. data/app/views/kiso/components/page_card/_description.html.erb +7 -0
  58. data/app/views/kiso/components/page_card/_footer.html.erb +7 -0
  59. data/app/views/kiso/components/page_card/_header.html.erb +7 -0
  60. data/app/views/kiso/components/page_card/_icon.html.erb +7 -0
  61. data/app/views/kiso/components/page_card/_title.html.erb +7 -0
  62. data/app/views/kiso/components/page_header/_description.html.erb +7 -0
  63. data/app/views/kiso/components/page_header/_headline.html.erb +7 -0
  64. data/app/views/kiso/components/page_header/_links.html.erb +7 -0
  65. data/app/views/kiso/components/page_header/_title.html.erb +7 -0
  66. data/app/views/kiso/components/page_section/_body.html.erb +7 -0
  67. data/app/views/kiso/components/page_section/_description.html.erb +7 -0
  68. data/app/views/kiso/components/page_section/_header.html.erb +7 -0
  69. data/app/views/kiso/components/page_section/_headline.html.erb +7 -0
  70. data/app/views/kiso/components/page_section/_links.html.erb +7 -0
  71. data/app/views/kiso/components/page_section/_title.html.erb +7 -0
  72. data/app/views/kiso/components/page_section/_wrapper.html.erb +7 -0
  73. data/app/views/kiso/components/pagination/_ellipsis.html.erb +1 -1
  74. data/app/views/kiso/components/pagination/_next.html.erb +2 -2
  75. data/app/views/kiso/components/pagination/_previous.html.erb +2 -2
  76. data/app/views/kiso/components/select/_item.html.erb +2 -2
  77. data/config/locales/en.yml +33 -0
  78. data/lib/generators/kiso/component/USAGE +35 -0
  79. data/lib/generators/kiso/component/component_generator.rb +104 -0
  80. data/lib/generators/kiso/component/templates/partial.html.erb.tt +5 -0
  81. data/lib/generators/kiso/component/templates/sub_part_partial.html.erb.tt +5 -0
  82. data/lib/generators/kiso/component/templates/sub_part_theme.rb.tt +21 -0
  83. data/lib/generators/kiso/component/templates/theme.rb.tt +21 -0
  84. data/lib/kiso/configuration.rb +40 -0
  85. data/lib/kiso/engine.rb +109 -1
  86. data/lib/kiso/presets/rounded.rb +136 -0
  87. data/lib/kiso/presets/sharp.rb +178 -0
  88. data/lib/kiso/presets.rb +49 -0
  89. data/lib/kiso/theme_overrides.rb +5 -1
  90. data/lib/kiso/themes/alert.rb +24 -11
  91. data/lib/kiso/themes/dashboard.rb +1 -1
  92. data/lib/kiso/themes/layout.rb +78 -0
  93. data/lib/kiso/themes/page.rb +295 -0
  94. data/lib/kiso/themes/skeleton.rb +16 -0
  95. data/lib/kiso/version.rb +1 -1
  96. data/lib/kiso.rb +7 -0
  97. data/lib/tasks/kiso.rake +36 -0
  98. metadata +64 -1
@@ -11,6 +11,11 @@ module Kiso
11
11
  # @param component [Symbol] the component name (e.g. +:badge+, +:card+)
12
12
  # @param part [Symbol, nil] optional sub-part name (e.g. +:header+, +:footer+)
13
13
  # @param collection [Array, nil] renders the partial once per item when present
14
+ # @param ui [Hash{Symbol => String}, nil] per-slot class overrides keyed by sub-part name.
15
+ # For parent components, the hash is pushed onto a context stack so sub-parts
16
+ # inherit overrides automatically. For self-rendering components, the hash is
17
+ # also passed as a local so the partial can apply overrides to internally
18
+ # rendered elements.
14
19
  # @param kwargs [Hash] locals passed to the partial (e.g. +color:+, +variant:+, +css_classes:+)
15
20
  # @yield optional block for component content
16
21
  # @return [ActiveSupport::SafeBuffer] rendered HTML
@@ -18,33 +23,25 @@ module Kiso
18
23
  # @example Render a badge
19
24
  # kui(:badge, color: :success, variant: :soft) { "Active" }
20
25
  #
21
- # @example Render a card sub-part
22
- # kui(:card, :header) { "Title" }
26
+ # @example Render a card with per-slot overrides
27
+ # kui(:card, ui: { header: "p-8", title: "text-xl" }) do
28
+ # kui(:card, :header) do
29
+ # kui(:card, :title) { "Dashboard" }
30
+ # end
31
+ # end
32
+ #
33
+ # @example Render an alert with inner element overrides
34
+ # kui(:alert, icon: "info", ui: { close: "opacity-50" })
23
35
  #
24
36
  # @example Render a collection
25
37
  # kui(:badge, collection: @tags)
26
- def kui(component, part = nil, collection: nil, **kwargs, &block)
27
- path = if part
28
- "kiso/components/#{component}/#{part}"
29
- else
30
- "kiso/components/#{component}"
31
- end
32
-
33
- # Prevent yield from bubbling up the ERB rendering chain when no block
34
- # is passed. Without this, partials that use `capture { yield }.presence`
35
- # to support optional block overrides (e.g., toggle/collapse/separator)
36
- # would have their `yield` bubble through nested content_tag blocks all
37
- # the way to the layout's `<%= yield %>`, capturing the entire page
38
- # template content. An explicit empty proc gives `yield` something to
39
- # call, returning empty string → `.presence` returns nil → default
40
- # content renders correctly.
41
- block ||= proc {}
42
-
43
- if collection
44
- render partial: path, collection: collection, locals: kwargs, &block
45
- else
46
- render path, **kwargs, &block
47
- end
38
+ def kui(component, part = nil, collection: nil, ui: nil, **kwargs, &block)
39
+ kiso_render_component(
40
+ component, part,
41
+ path_prefix: "kiso/components",
42
+ collection: collection, ui: ui, merge_global_ui: true,
43
+ **kwargs, &block
44
+ )
48
45
  end
49
46
 
50
47
  # Prepares +component_options+ for use with +content_tag+.
@@ -72,5 +69,124 @@ module Kiso
72
69
 
73
70
  (component_options.delete(:data) || {}).merge(slot: slot, **data_attrs)
74
71
  end
72
+
73
+ # Renders a themed HTML element with Kiso conventions.
74
+ #
75
+ # Collapses the common +content_tag+ + +kiso_prepare_options+ + theme
76
+ # rendering boilerplate into a single call. Use in component partials
77
+ # instead of manually wiring +content_tag+.
78
+ #
79
+ # @param tag [Symbol] HTML element name (e.g. +:div+, +:span+, +:button+)
80
+ # @param theme [ClassVariants::Instance] the theme module to render classes from
81
+ # @param slot [String] the +data-slot+ value (kebab-case)
82
+ # @param css_classes [String] caller's class overrides, merged via +tailwind_merge+
83
+ # @param variants [Hash] variant values forwarded to +theme.render+
84
+ # (e.g. +{ size: :md, color: :primary }+)
85
+ # @param component_options [Hash] HTML attributes forwarded to +content_tag+
86
+ # (e.g. +id:+, +aria:+). A +data:+ key is extracted and merged with slot.
87
+ # @yield optional block for element content
88
+ # @return [ActiveSupport::SafeBuffer] rendered HTML
89
+ #
90
+ # @example In a component partial
91
+ # kui_tag :div, theme: Kiso::Themes::Badge, slot: "badge",
92
+ # css_classes: css_classes, variants: { color: color, variant: variant },
93
+ # **component_options do
94
+ # yield
95
+ # end
96
+ def kui_tag(tag, theme:, slot:, css_classes: "", variants: {}, **component_options, &block)
97
+ content_tag(tag,
98
+ class: theme.render(**variants, class: css_classes),
99
+ data: kiso_prepare_options(component_options, slot: slot),
100
+ **component_options, &block)
101
+ end
102
+
103
+ private
104
+
105
+ # Shared rendering pipeline for both kui() and appui().
106
+ #
107
+ # @param component [Symbol] the component name
108
+ # @param part [Symbol, nil] optional sub-part name
109
+ # @param path_prefix [String] partial path prefix (e.g. "kiso/components" or "components")
110
+ # @param collection [Array, nil] renders the partial once per item when present
111
+ # @param ui [Hash, nil] per-slot class overrides
112
+ # @param merge_global_ui [Boolean] whether to merge global config ui layer
113
+ # @param kwargs [Hash] locals passed to the partial
114
+ # @param block [Proc] optional block for component content
115
+ # @return [ActiveSupport::SafeBuffer] rendered HTML
116
+ def kiso_render_component(component, part, path_prefix:, collection:, ui:, merge_global_ui: true, **kwargs, &block)
117
+ path = if part
118
+ "#{path_prefix}/#{component}/#{part}"
119
+ else
120
+ "#{path_prefix}/#{component}"
121
+ end
122
+
123
+ # Prevent yield from bubbling up the ERB rendering chain when no block
124
+ # is passed. Without this, partials that use `capture { yield }.presence`
125
+ # to support optional block overrides (e.g., toggle/collapse/separator)
126
+ # would have their `yield` bubble through nested content_tag blocks all
127
+ # the way to the layout's `<%= yield %>`, capturing the entire page
128
+ # template content. An explicit empty proc gives `yield` something to
129
+ # call, returning empty string → `.presence` returns nil → default
130
+ # content renders correctly.
131
+ block ||= proc {}
132
+
133
+ if part
134
+ # Sub-part: merge slot override from parent's ui context
135
+ parent_ui = kiso_current_ui(component)
136
+ if (slot_classes = parent_ui[part].presence)
137
+ existing = kwargs[:css_classes] || ""
138
+ kwargs[:css_classes] = existing.blank? ? slot_classes : "#{existing} #{slot_classes}"
139
+ end
140
+
141
+ # Forward ui: to sub-part partial when explicitly provided
142
+ kwargs[:ui] = ui if ui
143
+
144
+ if collection
145
+ render partial: path, collection: collection, locals: kwargs, &block
146
+ else
147
+ render path, **kwargs, &block
148
+ end
149
+ else
150
+ # Parent component: merge global ui config with instance ui (or use instance ui directly)
151
+ merged_ui = if merge_global_ui
152
+ kiso_merge_ui_layers(component, ui)
153
+ else
154
+ ui || {}
155
+ end
156
+ has_ui = merged_ui.present?
157
+
158
+ # Push context for composed sub-parts to read (skip when empty)
159
+ kiso_push_ui_context(component, merged_ui) if has_ui
160
+ begin
161
+ locals = has_ui ? kwargs.merge(ui: merged_ui) : kwargs
162
+
163
+ if collection
164
+ render partial: path, collection: collection, locals: locals, &block
165
+ else
166
+ render path, **locals, &block
167
+ end
168
+ ensure
169
+ kiso_pop_ui_context(component) if has_ui
170
+ end
171
+ end
172
+ end
173
+
174
+ # Merge global config ui overrides with instance ui overrides.
175
+ # Global config is Layer 2, instance +ui:+ is Layer 3.
176
+ #
177
+ # @param component [Symbol] the component name
178
+ # @param instance_ui [Hash, nil] per-instance ui overrides
179
+ # @return [Hash{Symbol => String}] merged ui hash
180
+ def kiso_merge_ui_layers(component, instance_ui)
181
+ global_ui = Kiso.config.theme.dig(component, :ui)
182
+ return instance_ui || {} if global_ui.nil? || global_ui.empty?
183
+ return global_ui if instance_ui.nil? || instance_ui.empty?
184
+
185
+ # Instance wins. For slots in both, concatenate — tailwind_merge
186
+ # resolves conflicts when .render(class:) is called.
187
+ global_ui.merge(instance_ui) do |_slot, global_classes, instance_classes|
188
+ "#{global_classes} #{instance_classes}"
189
+ end
190
+ end
75
191
  end
76
192
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kiso
4
+ # Manages a request-scoped context stack for per-slot +ui:+ overrides.
5
+ #
6
+ # This is ERB's equivalent of Vue's provide/inject pattern. When a parent
7
+ # component is rendered with +ui:+, the hash is pushed onto a stack.
8
+ # Sub-parts rendered inside the parent's block read their slot override
9
+ # from the stack automatically.
10
+ #
11
+ # Thread-safe because Rails creates a fresh view context (and therefore
12
+ # fresh instance variables) per request.
13
+ #
14
+ # @example How the stack flows
15
+ # # Parent pushes:
16
+ # kiso_push_ui_context(:card, { header: "p-8", title: "text-xl" })
17
+ #
18
+ # # Sub-part reads:
19
+ # kiso_current_ui(:card) #=> { header: "p-8", title: "text-xl" }
20
+ #
21
+ # # After parent renders:
22
+ # kiso_pop_ui_context(:card)
23
+ #
24
+ # @see ComponentHelper#kui
25
+ module UiContextHelper
26
+ # Push a ui hash onto the context stack for a component.
27
+ #
28
+ # @param component [Symbol] the component name (e.g. +:card+)
29
+ # @param ui [Hash{Symbol => String}] slot-name to class-string mapping
30
+ # @return [void]
31
+ def kiso_push_ui_context(component, ui)
32
+ kiso_ui_stack[component] ||= []
33
+ kiso_ui_stack[component].push(ui || {})
34
+ end
35
+
36
+ # Pop the most recent ui hash for a component.
37
+ #
38
+ # @param component [Symbol] the component name
39
+ # @return [Hash, nil] the popped ui hash
40
+ def kiso_pop_ui_context(component)
41
+ kiso_ui_stack[component]&.pop
42
+ end
43
+
44
+ # Read the current ui hash for a component (top of stack).
45
+ #
46
+ # @param component [Symbol] the component name
47
+ # @return [Hash{Symbol => String}] the current ui overrides, or empty hash
48
+ def kiso_current_ui(component)
49
+ kiso_ui_stack.dig(component, -1) || {}
50
+ end
51
+
52
+ private
53
+
54
+ # @return [Hash{Symbol => Array<Hash>}] per-component stacks
55
+ def kiso_ui_stack
56
+ @kiso_ui_stack ||= {}
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,33 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ /**
4
+ * Alert controller. Handles dismissing an alert by removing it from the DOM.
5
+ *
6
+ * Attach to the alert root element with `data-controller="kiso--alert"`.
7
+ * The close button dispatches the `close` action on click.
8
+ *
9
+ * @example
10
+ * <div data-controller="kiso--alert" data-slot="alert" role="alert">
11
+ * <div data-slot="alert-wrapper">
12
+ * <div data-slot="alert-title">Heads up!</div>
13
+ * <div data-slot="alert-description">You can dismiss this alert.</div>
14
+ * </div>
15
+ * <button data-action="click->kiso--alert#close" data-slot="alert-close">
16
+ * <svg>...</svg>
17
+ * </button>
18
+ * </div>
19
+ *
20
+ * @fires kiso--alert:close - Dispatched before the alert is removed from the DOM
21
+ */
22
+ export default class extends Controller {
23
+ /**
24
+ * Dismisses the alert. Dispatches a `close` event and removes the element.
25
+ * The event can be cancelled with `event.preventDefault()` to prevent removal.
26
+ */
27
+ close() {
28
+ const event = this.dispatch("close", { cancelable: true })
29
+ if (!event.defaultPrevented) {
30
+ this.element.remove()
31
+ }
32
+ }
33
+ }
@@ -1,3 +1,4 @@
1
+ import KisoAlertController from "./alert_controller.js"
1
2
  import KisoComboboxController from "./combobox_controller.js"
2
3
  import KisoCommandController from "./command_controller.js"
3
4
  import KisoCommandDialogController from "./command_dialog_controller.js"
@@ -13,6 +14,7 @@ import KisoToggleGroupController from "./toggle_group_controller.js"
13
14
 
14
15
  const KisoUi = {
15
16
  start(application) {
17
+ application.register("kiso--alert", KisoAlertController)
16
18
  application.register("kiso--combobox", KisoComboboxController)
17
19
  application.register("kiso--command", KisoCommandController)
18
20
  application.register("kiso--command-dialog", KisoCommandDialogController)
@@ -30,6 +32,7 @@ const KisoUi = {
30
32
 
31
33
  export default KisoUi
32
34
  export {
35
+ KisoAlertController,
33
36
  KisoComboboxController,
34
37
  KisoCommandController,
35
38
  KisoCommandDialogController,
@@ -1,8 +1,24 @@
1
- <%# locals: (color: :primary, variant: :soft, css_classes: "", **component_options) %>
1
+ <%# locals: (icon: nil, color: :primary, variant: :soft, close: false, ui: {}, css_classes: "", **component_options) %>
2
2
  <%= content_tag :div,
3
3
  role: :alert,
4
4
  class: Kiso::Themes::Alert.render(color: color, variant: variant, class: css_classes),
5
- data: kiso_prepare_options(component_options, slot: "alert"),
5
+ data: kiso_prepare_options(component_options, slot: "alert",
6
+ **({ controller: "kiso--alert" } if close)),
6
7
  **component_options do %>
7
- <%= yield %>
8
+ <% if icon %>
9
+ <%= kiso_icon(icon, class: "size-4 translate-y-0.5 text-current #{ui[:icon]}") %>
10
+ <% end %>
11
+ <%= content_tag :div,
12
+ class: Kiso::Themes::AlertWrapper.render(class: ui[:wrapper]),
13
+ data: { slot: "alert-wrapper" } do %>
14
+ <%= yield %>
15
+ <% end %>
16
+ <% if close %>
17
+ <%= tag.button type: "button",
18
+ class: Kiso::Themes::AlertClose.render(class: ui[:close]),
19
+ data: { slot: "alert-close", action: "click->kiso--alert#close" },
20
+ aria: { label: t("kiso.alert.dismiss") } do %>
21
+ <%= kiso_component_icon(:x, class: "size-4") %>
22
+ <% end %>
23
+ <% end %>
8
24
  <% end %>
@@ -1,4 +1,4 @@
1
- <%# locals: (open: false, size: :default, css_classes: "", **component_options) %>
1
+ <%# locals: (open: false, size: :default, ui: {}, css_classes: "", **component_options) %>
2
2
  <%
3
3
  # Store the dialog id on the view context so child sub-part partials
4
4
  # (_title, _description) can auto-generate matching aria-labelledby /
@@ -20,7 +20,7 @@
20
20
  kiso__dialog_open_value: (open ? true : nil),
21
21
  kiso__dialog_dismissable_value: false),
22
22
  **component_options do %>
23
- <div class="<%= Kiso::Themes::AlertDialogContent.render(size: size) %>"
23
+ <div class="<%= Kiso::Themes::AlertDialogContent.render(size: size, class: ui[:content]) %>"
24
24
  data-slot="alert-dialog-content"
25
25
  data-size="<%= size %>">
26
26
  <%= yield %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (center: false, css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::App.render(center: center, class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "app"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -1,4 +1,4 @@
1
- <%# locals: (src: nil, alt: "", text: nil, size: :md, css_classes: "", **component_options) %>
1
+ <%# locals: (src: nil, alt: "", text: nil, size: :md, ui: {}, css_classes: "", **component_options) %>
2
2
  <%= content_tag :span,
3
3
  class: Kiso::Themes::Avatar.render(size: size, class: css_classes),
4
4
  data: kiso_prepare_options(component_options, slot: "avatar", size: size),
@@ -8,14 +8,14 @@
8
8
  <%= content %>
9
9
  <% else %>
10
10
  <% if text.present? %>
11
- <%= tag.span class: Kiso::Themes::AvatarFallback.render(size: size),
11
+ <%= tag.span class: Kiso::Themes::AvatarFallback.render(size: size, class: ui[:fallback]),
12
12
  data: { slot: "avatar-fallback" } do %>
13
13
  <%= text %>
14
14
  <% end %>
15
15
  <% end %>
16
16
  <% if src.present? %>
17
17
  <%= tag.img src: src, alt: alt,
18
- class: Kiso::Themes::AvatarImage.render,
18
+ class: Kiso::Themes::AvatarImage.render(class: ui[:image]),
19
19
  data: { slot: "avatar-image" },
20
20
  onerror: "this.style.display='none'" %>
21
21
  <% end %>
@@ -1,7 +1,7 @@
1
1
  <%# locals: (css_classes: "", **component_options) %>
2
2
  <%= content_tag :nav,
3
3
  class: Kiso::Themes::Breadcrumb.render(class: css_classes),
4
- aria: { label: "breadcrumb" },
4
+ aria: { label: t("kiso.breadcrumb.label") },
5
5
  data: kiso_prepare_options(component_options, slot: "breadcrumb"),
6
6
  **component_options do %>
7
7
  <%= yield %>
@@ -4,7 +4,7 @@
4
4
  data: kiso_prepare_options(component_options, slot: "color-mode-button",
5
5
  controller: "kiso--theme",
6
6
  action: "click->kiso--theme#toggle"),
7
- aria: { label: "Toggle color mode" },
7
+ aria: { label: t("kiso.color_mode_button.toggle") },
8
8
  type: "button",
9
9
  **component_options do %>
10
10
  <%# Light icon — visible in light mode, hidden in dark %>
@@ -7,17 +7,17 @@
7
7
  **component_options do %>
8
8
  <%= kui(:select) do %>
9
9
  <%= kui(:select, :trigger, size: size) do %>
10
- <%= kui(:select, :value, placeholder: "Theme") %>
10
+ <%= kui(:select, :value, placeholder: t("kiso.color_mode_select.theme")) %>
11
11
  <% end %>
12
12
  <%= kui(:select, :content) do %>
13
13
  <%= kui(:select, :item, value: "system") do %>
14
- <span class="inline-flex items-center gap-2"><%= kiso_component_icon(:monitor, class: "size-4 opacity-60") %> System</span>
14
+ <span class="inline-flex items-center gap-2"><%= kiso_component_icon(:monitor, class: "size-4 opacity-60") %> <%= t("kiso.color_mode_select.system") %></span>
15
15
  <% end %>
16
16
  <%= kui(:select, :item, value: "light") do %>
17
- <span class="inline-flex items-center gap-2"><%= kiso_component_icon(:sun, class: "size-4 opacity-60") %> Light</span>
17
+ <span class="inline-flex items-center gap-2"><%= kiso_component_icon(:sun, class: "size-4 opacity-60") %> <%= t("kiso.color_mode_select.light") %></span>
18
18
  <% end %>
19
19
  <%= kui(:select, :item, value: "dark") do %>
20
- <span class="inline-flex items-center gap-2"><%= kiso_component_icon(:moon, class: "size-4 opacity-60") %> Dark</span>
20
+ <span class="inline-flex items-center gap-2"><%= kiso_component_icon(:moon, class: "size-4 opacity-60") %> <%= t("kiso.color_mode_select.dark") %></span>
21
21
  <% end %>
22
22
  <% end %>
23
23
  <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (size: :default, css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::Container.render(size: size, class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "container"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -3,7 +3,7 @@
3
3
  id: "dashboard-sidebar",
4
4
  class: Kiso::Themes::DashboardSidebar.render(class: css_classes),
5
5
  data: kiso_prepare_options(component_options, slot: "dashboard-sidebar"),
6
- aria: { label: "Sidebar navigation" },
6
+ aria: { label: t("kiso.dashboard_sidebar.label") },
7
7
  **component_options do %>
8
8
  <div data-slot="dashboard-sidebar-inner">
9
9
  <%= yield %>
@@ -1,11 +1,11 @@
1
- <%# locals: (open: false, css_classes: "", **component_options) %>
1
+ <%# locals: (open: false, ui: {}, css_classes: "", **component_options) %>
2
2
  <%= content_tag :dialog,
3
3
  class: Kiso::Themes::Dialog.render(class: css_classes),
4
4
  data: kiso_prepare_options(component_options, slot: "dialog",
5
5
  controller: "kiso--dialog",
6
6
  kiso__dialog_open_value: (open ? true : nil)),
7
7
  **component_options do %>
8
- <div class="<%= Kiso::Themes::DialogContent.render %>" data-slot="dialog-content">
8
+ <div class="<%= Kiso::Themes::DialogContent.render(class: ui[:content]) %>" data-slot="dialog-content">
9
9
  <%= yield %>
10
10
  </div>
11
11
  <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :footer,
3
+ class: Kiso::Themes::Footer.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "footer"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :header,
3
+ class: Kiso::Themes::Header.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "header"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :main,
3
+ class: Kiso::Themes::Main.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "main"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::Page.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageBody.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-body"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,40 @@
1
+ <%# locals: (variant: :outline, icon: nil, title: nil, description: nil, ui: {}, css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageCard.render(variant: variant, class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-card"),
5
+ **component_options do %>
6
+ <%= content_tag :div,
7
+ class: Kiso::Themes::PageCardContainer.render(class: ui[:container]),
8
+ data: { slot: "page-card-container" } do %>
9
+ <%= content_tag :div,
10
+ class: Kiso::Themes::PageCardWrapper.render(class: ui[:wrapper]),
11
+ data: { slot: "page-card-wrapper" } do %>
12
+ <% content = capture { yield }.presence %>
13
+ <% if content %>
14
+ <%= content %>
15
+ <% else %>
16
+ <% if icon %>
17
+ <%= content_tag :div,
18
+ class: Kiso::Themes::PageCardIcon.render(class: ui[:icon]),
19
+ data: { slot: "page-card-icon" } do %>
20
+ <%= kiso_icon(icon) %>
21
+ <% end %>
22
+ <% end %>
23
+ <% if title %>
24
+ <%= content_tag :p,
25
+ class: Kiso::Themes::PageCardTitle.render(class: ui[:title]),
26
+ data: { slot: "page-card-title" } do %>
27
+ <%= title %>
28
+ <% end %>
29
+ <% end %>
30
+ <% if description %>
31
+ <%= content_tag :p,
32
+ class: Kiso::Themes::PageCardDescription.render(class: ui[:description]),
33
+ data: { slot: "page-card-description" } do %>
34
+ <%= description %>
35
+ <% end %>
36
+ <% end %>
37
+ <% end %>
38
+ <% end %>
39
+ <% end %>
40
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageGrid.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-grid"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,38 @@
1
+ <%# locals: (headline: nil, title: nil, description: nil, ui: {}, css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageHeader.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-header"),
5
+ **component_options do %>
6
+ <%= content_tag :div,
7
+ class: Kiso::Themes::PageHeaderWrapper.render(class: ui[:wrapper]),
8
+ data: { slot: "page-header-wrapper" } do %>
9
+ <% content = capture { yield }.presence %>
10
+ <% if content %>
11
+ <%= content %>
12
+ <% else %>
13
+ <div>
14
+ <% if headline %>
15
+ <%= content_tag :div,
16
+ class: Kiso::Themes::PageHeaderHeadline.render(class: ui[:headline]),
17
+ data: { slot: "page-header-headline" } do %>
18
+ <%= headline %>
19
+ <% end %>
20
+ <% end %>
21
+ <% if title %>
22
+ <%= content_tag :h1,
23
+ class: Kiso::Themes::PageHeaderTitle.render(class: ui[:title]),
24
+ data: { slot: "page-header-title" } do %>
25
+ <%= title %>
26
+ <% end %>
27
+ <% end %>
28
+ <% if description %>
29
+ <%= content_tag :p,
30
+ class: Kiso::Themes::PageHeaderDescription.render(class: ui[:description]),
31
+ data: { slot: "page-header-description" } do %>
32
+ <%= description %>
33
+ <% end %>
34
+ <% end %>
35
+ </div>
36
+ <% end %>
37
+ <% end %>
38
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <%# locals: (orientation: :horizontal, ui: {}, css_classes: "", **component_options) %>
2
+ <%= content_tag :section,
3
+ class: Kiso::Themes::PageSection.render(orientation: orientation, class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-section"),
5
+ **component_options do %>
6
+ <%= content_tag :div,
7
+ class: Kiso::Themes::PageSectionContainer.render(orientation: orientation, class: ui[:container]),
8
+ data: { slot: "page-section-container" } do %>
9
+ <%= yield %>
10
+ <% end %>
11
+ <% end %>
@@ -1,7 +1,7 @@
1
1
  <%# locals: (css_classes: "", **component_options) %>
2
2
  <%= content_tag :nav,
3
3
  role: "navigation",
4
- aria: {label: "pagination"},
4
+ aria: {label: t("kiso.pagination.label")},
5
5
  class: Kiso::Themes::Pagination.render(class: css_classes),
6
6
  data: kiso_prepare_options(component_options, slot: "pagination"),
7
7
  **component_options do %>
@@ -1,6 +1,6 @@
1
- <%# locals: (variant: :outline, size: :md, disabled: false, css_classes: "", **component_options) %>
1
+ <%# locals: (variant: :outline, size: :md, disabled: false, ui: {}, css_classes: "", **component_options) %>
2
2
  <%= content_tag :div,
3
- class: Kiso::Themes::SelectNativeWrapper.render,
3
+ class: Kiso::Themes::SelectNativeWrapper.render(class: ui[:wrapper]),
4
4
  data: {slot: "select-native-wrapper"} do %>
5
5
  <% component_options[:disabled] = true if disabled %>
6
6
  <%= tag.select(
@@ -8,7 +8,7 @@
8
8
  data: kiso_prepare_options(component_options, slot: "select-native"),
9
9
  **component_options) { yield } %>
10
10
  <%= content_tag :span,
11
- class: Kiso::Themes::SelectNativeIcon.render,
11
+ class: Kiso::Themes::SelectNativeIcon.render(class: ui[:icon]),
12
12
  aria: {hidden: true},
13
13
  data: {slot: "select-native-icon"} do %>
14
14
  <%= kiso_component_icon(:chevron_down) %>
@@ -0,0 +1,5 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= tag.div(
3
+ class: Kiso::Themes::Skeleton.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "skeleton"),
5
+ **component_options) %>