kiso 0.1.0.pre → 0.2.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/CHANGELOG.md +36 -2
- data/README.md +67 -27
- data/Rakefile +8 -0
- data/app/assets/tailwind/kiso/checkbox.css +18 -0
- data/app/assets/tailwind/kiso/color-mode.css +9 -0
- data/app/assets/tailwind/kiso/dashboard.css +194 -0
- data/app/assets/tailwind/kiso/engine.css +117 -0
- data/app/assets/tailwind/kiso/input-otp.css +10 -0
- data/app/assets/tailwind/kiso/radio-group.css +17 -0
- data/app/helpers/kiso/component_helper.rb +46 -27
- data/app/helpers/kiso/icon_helper.rb +53 -9
- data/app/helpers/kiso/theme_helper.rb +38 -0
- data/app/javascript/controllers/kiso/combobox_controller.js +616 -0
- data/app/javascript/controllers/kiso/command_controller.js +184 -0
- data/app/javascript/controllers/kiso/command_dialog_controller.js +104 -0
- data/app/javascript/controllers/kiso/dropdown_menu_controller.js +684 -0
- data/app/javascript/controllers/kiso/index.d.ts +12 -0
- data/app/javascript/controllers/kiso/index.js +42 -0
- data/app/javascript/controllers/kiso/input_otp_controller.js +195 -0
- data/app/javascript/controllers/kiso/popover_controller.js +254 -0
- data/app/javascript/controllers/kiso/select_controller.js +307 -0
- data/app/javascript/controllers/kiso/sidebar_controller.js +84 -0
- data/app/javascript/controllers/kiso/theme_controller.js +89 -0
- data/app/javascript/controllers/kiso/toggle_controller.js +24 -0
- data/app/javascript/controllers/kiso/toggle_group_controller.js +128 -0
- data/app/javascript/kiso/utils/focusable.js +8 -0
- data/app/javascript/kiso/utils/highlight.js +43 -0
- data/app/javascript/kiso/utils/positioning.js +86 -0
- data/app/javascript/kiso/vendor/floating-ui-core.js +1 -0
- data/app/javascript/kiso/vendor/floating-ui-dom.js +1 -0
- data/app/views/kiso/components/_alert.html.erb +1 -1
- data/app/views/kiso/components/_avatar.html.erb +23 -0
- data/app/views/kiso/components/_badge.html.erb +1 -1
- data/app/views/kiso/components/_breadcrumb.html.erb +8 -0
- data/app/views/kiso/components/_button.html.erb +1 -1
- data/app/views/kiso/components/_card.html.erb +1 -1
- data/app/views/kiso/components/_checkbox.html.erb +7 -0
- data/app/views/kiso/components/_color_mode_button.html.erb +14 -0
- data/app/views/kiso/components/_color_mode_select.html.erb +24 -0
- data/app/views/kiso/components/_combobox.html.erb +12 -0
- data/app/views/kiso/components/_command.html.erb +7 -0
- data/app/views/kiso/components/_dashboard_group.html.erb +14 -0
- data/app/views/kiso/components/_dashboard_navbar.html.erb +7 -0
- data/app/views/kiso/components/_dashboard_panel.html.erb +7 -0
- data/app/views/kiso/components/_dashboard_sidebar.html.erb +11 -0
- data/app/views/kiso/components/_dashboard_toolbar.html.erb +7 -0
- data/app/views/kiso/components/_dropdown_menu.html.erb +7 -0
- data/app/views/kiso/components/{_empty_state.html.erb → _empty.html.erb} +2 -2
- data/app/views/kiso/components/_field.html.erb +12 -0
- data/app/views/kiso/components/_field_group.html.erb +7 -0
- data/app/views/kiso/components/_field_set.html.erb +7 -0
- data/app/views/kiso/components/_input.html.erb +8 -0
- data/app/views/kiso/components/_input_group.html.erb +8 -0
- data/app/views/kiso/components/_input_otp.html.erb +22 -0
- data/app/views/kiso/components/_kbd.html.erb +7 -0
- data/app/views/kiso/components/_label.html.erb +5 -0
- data/app/views/kiso/components/_nav.html.erb +7 -0
- data/app/views/kiso/components/_pagination.html.erb +9 -0
- data/app/views/kiso/components/_popover.html.erb +8 -0
- data/app/views/kiso/components/_radio_group.html.erb +8 -0
- data/app/views/kiso/components/_select.html.erb +8 -0
- data/app/views/kiso/components/_select_native.html.erb +16 -0
- data/app/views/kiso/components/_separator.html.erb +1 -1
- data/app/views/kiso/components/_stats_card.html.erb +1 -1
- data/app/views/kiso/components/_stats_grid.html.erb +1 -1
- data/app/views/kiso/components/_switch.html.erb +10 -0
- data/app/views/kiso/components/_table.html.erb +2 -1
- data/app/views/kiso/components/_textarea.html.erb +9 -0
- data/app/views/kiso/components/_toggle.html.erb +12 -0
- data/app/views/kiso/components/_toggle_group.html.erb +12 -0
- data/app/views/kiso/components/alert/_description.html.erb +1 -1
- data/app/views/kiso/components/alert/_title.html.erb +1 -1
- data/app/views/kiso/components/avatar/_badge.html.erb +7 -0
- data/app/views/kiso/components/avatar/_fallback.html.erb +7 -0
- data/app/views/kiso/components/avatar/_group.html.erb +7 -0
- data/app/views/kiso/components/avatar/_group_count.html.erb +7 -0
- data/app/views/kiso/components/avatar/_image.html.erb +6 -0
- data/app/views/kiso/components/breadcrumb/_ellipsis.html.erb +10 -0
- data/app/views/kiso/components/breadcrumb/_item.html.erb +7 -0
- data/app/views/kiso/components/breadcrumb/_link.html.erb +7 -0
- data/app/views/kiso/components/breadcrumb/_list.html.erb +7 -0
- data/app/views/kiso/components/breadcrumb/_page.html.erb +9 -0
- data/app/views/kiso/components/breadcrumb/_separator.html.erb +9 -0
- data/app/views/kiso/components/card/_action.html.erb +7 -0
- data/app/views/kiso/components/card/_content.html.erb +1 -1
- data/app/views/kiso/components/card/_description.html.erb +1 -1
- data/app/views/kiso/components/card/_footer.html.erb +1 -1
- data/app/views/kiso/components/card/_header.html.erb +1 -1
- data/app/views/kiso/components/card/_title.html.erb +1 -1
- data/app/views/kiso/components/combobox/_chip.html.erb +19 -0
- data/app/views/kiso/components/combobox/_chips.html.erb +20 -0
- data/app/views/kiso/components/combobox/_chips_input.html.erb +10 -0
- data/app/views/kiso/components/combobox/_content.html.erb +9 -0
- data/app/views/kiso/components/combobox/_empty.html.erb +9 -0
- data/app/views/kiso/components/combobox/_group.html.erb +8 -0
- data/app/views/kiso/components/combobox/_input.html.erb +23 -0
- data/app/views/kiso/components/combobox/_item.html.erb +19 -0
- data/app/views/kiso/components/combobox/_label.html.erb +7 -0
- data/app/views/kiso/components/combobox/_list.html.erb +10 -0
- data/app/views/kiso/components/combobox/_separator.html.erb +6 -0
- data/app/views/kiso/components/command/_dialog.html.erb +11 -0
- data/app/views/kiso/components/command/_empty.html.erb +9 -0
- data/app/views/kiso/components/command/_group.html.erb +14 -0
- data/app/views/kiso/components/command/_input.html.erb +16 -0
- data/app/views/kiso/components/command/_item.html.erb +13 -0
- data/app/views/kiso/components/command/_list.html.erb +10 -0
- data/app/views/kiso/components/command/_separator.html.erb +7 -0
- data/app/views/kiso/components/command/_shortcut.html.erb +7 -0
- data/app/views/kiso/components/dashboard_navbar/_toggle.html.erb +11 -0
- data/app/views/kiso/components/dashboard_sidebar/_collapse.html.erb +12 -0
- data/app/views/kiso/components/dashboard_sidebar/_footer.html.erb +7 -0
- data/app/views/kiso/components/dashboard_sidebar/_header.html.erb +7 -0
- data/app/views/kiso/components/dashboard_sidebar/_toggle.html.erb +11 -0
- data/app/views/kiso/components/dashboard_toolbar/_left.html.erb +7 -0
- data/app/views/kiso/components/dashboard_toolbar/_right.html.erb +7 -0
- data/app/views/kiso/components/dropdown_menu/_checkbox_item.html.erb +18 -0
- data/app/views/kiso/components/dropdown_menu/_content.html.erb +10 -0
- data/app/views/kiso/components/dropdown_menu/_group.html.erb +8 -0
- data/app/views/kiso/components/dropdown_menu/_item.html.erb +15 -0
- data/app/views/kiso/components/dropdown_menu/_label.html.erb +8 -0
- data/app/views/kiso/components/dropdown_menu/_radio_group.html.erb +10 -0
- data/app/views/kiso/components/dropdown_menu/_radio_item.html.erb +19 -0
- data/app/views/kiso/components/dropdown_menu/_separator.html.erb +6 -0
- data/app/views/kiso/components/dropdown_menu/_shortcut.html.erb +7 -0
- data/app/views/kiso/components/dropdown_menu/_sub.html.erb +8 -0
- data/app/views/kiso/components/dropdown_menu/_sub_content.html.erb +10 -0
- data/app/views/kiso/components/dropdown_menu/_sub_trigger.html.erb +12 -0
- data/app/views/kiso/components/dropdown_menu/_trigger.html.erb +9 -0
- data/app/views/kiso/components/empty/_content.html.erb +7 -0
- data/app/views/kiso/components/empty/_description.html.erb +7 -0
- data/app/views/kiso/components/empty/_header.html.erb +7 -0
- data/app/views/kiso/components/empty/_media.html.erb +7 -0
- data/app/views/kiso/components/empty/_title.html.erb +7 -0
- data/app/views/kiso/components/field/_content.html.erb +7 -0
- data/app/views/kiso/components/field/_description.html.erb +7 -0
- data/app/views/kiso/components/field/_error.html.erb +22 -0
- data/app/views/kiso/components/field/_label.html.erb +5 -0
- data/app/views/kiso/components/field/_separator.html.erb +15 -0
- data/app/views/kiso/components/field/_title.html.erb +7 -0
- data/app/views/kiso/components/field_set/_legend.html.erb +9 -0
- data/app/views/kiso/components/input_group/_addon.html.erb +7 -0
- data/app/views/kiso/components/input_otp/_group.html.erb +7 -0
- data/app/views/kiso/components/input_otp/_separator.html.erb +8 -0
- data/app/views/kiso/components/input_otp/_slot.html.erb +11 -0
- data/app/views/kiso/components/kbd/_group.html.erb +7 -0
- data/app/views/kiso/components/nav/_item.html.erb +15 -0
- data/app/views/kiso/components/nav/_section.html.erb +37 -0
- data/app/views/kiso/components/nav/_section_title.html.erb +7 -0
- data/app/views/kiso/components/pagination/_content.html.erb +7 -0
- data/app/views/kiso/components/pagination/_ellipsis.html.erb +9 -0
- data/app/views/kiso/components/pagination/_item.html.erb +7 -0
- data/app/views/kiso/components/pagination/_link.html.erb +9 -0
- data/app/views/kiso/components/pagination/_next.html.erb +12 -0
- data/app/views/kiso/components/pagination/_previous.html.erb +12 -0
- data/app/views/kiso/components/popover/_anchor.html.erb +8 -0
- data/app/views/kiso/components/popover/_content.html.erb +11 -0
- data/app/views/kiso/components/popover/_description.html.erb +7 -0
- data/app/views/kiso/components/popover/_header.html.erb +7 -0
- data/app/views/kiso/components/popover/_title.html.erb +7 -0
- data/app/views/kiso/components/popover/_trigger.html.erb +9 -0
- data/app/views/kiso/components/radio_group/_item.html.erb +6 -0
- data/app/views/kiso/components/select/_content.html.erb +10 -0
- data/app/views/kiso/components/select/_group.html.erb +8 -0
- data/app/views/kiso/components/select/_item.html.erb +19 -0
- data/app/views/kiso/components/select/_label.html.erb +7 -0
- data/app/views/kiso/components/select/_separator.html.erb +6 -0
- data/app/views/kiso/components/select/_trigger.html.erb +13 -0
- data/app/views/kiso/components/select/_value.html.erb +11 -0
- data/app/views/kiso/components/stats_card/_description.html.erb +1 -1
- data/app/views/kiso/components/stats_card/_header.html.erb +1 -1
- data/app/views/kiso/components/stats_card/_label.html.erb +1 -1
- data/app/views/kiso/components/stats_card/_value.html.erb +1 -1
- data/app/views/kiso/components/table/_body.html.erb +1 -1
- data/app/views/kiso/components/table/_caption.html.erb +1 -1
- data/app/views/kiso/components/table/_cell.html.erb +1 -1
- data/app/views/kiso/components/table/_footer.html.erb +1 -1
- data/app/views/kiso/components/table/_head.html.erb +1 -1
- data/app/views/kiso/components/table/_header.html.erb +1 -1
- data/app/views/kiso/components/table/_row.html.erb +1 -1
- data/app/views/kiso/components/toggle_group/_item.html.erb +13 -0
- data/config/deploy.docs.yml +31 -0
- data/config/deploy.yml +34 -0
- data/config/importmap.rb +10 -0
- data/lib/kiso/cli/base.rb +15 -0
- data/lib/kiso/cli/icons.rb +2 -1
- data/lib/kiso/cli/main.rb +6 -0
- data/lib/kiso/cli/make.rb +22 -12
- data/lib/kiso/configuration.rb +54 -0
- data/lib/kiso/engine.rb +36 -1
- data/lib/kiso/theme_overrides.rb +130 -0
- data/lib/kiso/themes/alert.rb +16 -1
- data/lib/kiso/themes/avatar.rb +53 -0
- data/lib/kiso/themes/badge.rb +15 -5
- data/lib/kiso/themes/breadcrumb.rb +44 -0
- data/lib/kiso/themes/button.rb +15 -2
- data/lib/kiso/themes/card.rb +18 -2
- data/lib/kiso/themes/checkbox.rb +33 -0
- data/lib/kiso/themes/color_mode_button.rb +15 -0
- data/lib/kiso/themes/color_mode_select.rb +7 -0
- data/lib/kiso/themes/combobox.rb +97 -0
- data/lib/kiso/themes/command.rb +79 -0
- data/lib/kiso/themes/dashboard.rb +51 -0
- data/lib/kiso/themes/dropdown_menu.rb +108 -0
- data/lib/kiso/themes/empty.rb +54 -0
- data/lib/kiso/themes/field.rb +76 -0
- data/lib/kiso/themes/field_group.rb +15 -0
- data/lib/kiso/themes/field_set.rb +32 -0
- data/lib/kiso/themes/input.rb +33 -0
- data/lib/kiso/themes/input_group.rb +39 -0
- data/lib/kiso/themes/input_otp.rb +46 -0
- data/lib/kiso/themes/kbd.rb +31 -0
- data/lib/kiso/themes/label.rb +16 -0
- data/lib/kiso/themes/nav.rb +27 -0
- data/lib/kiso/themes/pagination.rb +73 -0
- data/lib/kiso/themes/popover.rb +32 -0
- data/lib/kiso/themes/radio_group.rb +43 -0
- data/lib/kiso/themes/select.rb +78 -0
- data/lib/kiso/themes/select_native.rb +49 -0
- data/lib/kiso/themes/separator.rb +8 -2
- data/lib/kiso/themes/shared.rb +51 -0
- data/lib/kiso/themes/stats_card.rb +26 -14
- data/lib/kiso/themes/switch.rb +56 -0
- data/lib/kiso/themes/table.rb +18 -15
- data/lib/kiso/themes/textarea.rb +33 -0
- data/lib/kiso/themes/toggle.rb +71 -0
- data/lib/kiso/themes/toggle_group.rb +13 -0
- data/lib/kiso/version.rb +4 -1
- data/lib/kiso.rb +70 -2
- metadata +183 -22
- data/app/views/kiso/components/empty_state/_content.html.erb +0 -7
- data/app/views/kiso/components/empty_state/_description.html.erb +0 -7
- data/app/views/kiso/components/empty_state/_header.html.erb +0 -7
- data/app/views/kiso/components/empty_state/_media.html.erb +0 -7
- data/app/views/kiso/components/empty_state/_title.html.erb +0 -7
- data/lib/kiso/themes/empty_state.rb +0 -42
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Navigation breadcrumb trail rendered as a +<nav>+ element.
|
|
4
|
+
#
|
|
5
|
+
# @example
|
|
6
|
+
# Breadcrumb.render
|
|
7
|
+
#
|
|
8
|
+
# Sub-parts: {BreadcrumbList}, {BreadcrumbItem}, {BreadcrumbLink},
|
|
9
|
+
# {BreadcrumbPage}, {BreadcrumbSeparator}, {BreadcrumbEllipsis}
|
|
10
|
+
Breadcrumb = ClassVariants.build(
|
|
11
|
+
base: ""
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
# Ordered list (+<ol>+) containing breadcrumb items.
|
|
15
|
+
BreadcrumbList = ClassVariants.build(
|
|
16
|
+
base: "text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# List item (+<li>+) wrapping a link or page indicator.
|
|
20
|
+
BreadcrumbItem = ClassVariants.build(
|
|
21
|
+
base: "inline-flex items-center gap-1.5"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Clickable link to an ancestor page.
|
|
25
|
+
BreadcrumbLink = ClassVariants.build(
|
|
26
|
+
base: "hover:text-foreground transition-colors"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# Current page indicator (non-interactive, +aria-current="page"+).
|
|
30
|
+
BreadcrumbPage = ClassVariants.build(
|
|
31
|
+
base: "text-foreground font-normal"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Chevron or custom separator between breadcrumb items.
|
|
35
|
+
BreadcrumbSeparator = ClassVariants.build(
|
|
36
|
+
base: "[&>svg]:size-3.5"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Ellipsis indicator for collapsed breadcrumb levels.
|
|
40
|
+
BreadcrumbEllipsis = ClassVariants.build(
|
|
41
|
+
base: "flex size-9 items-center justify-center"
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/kiso/themes/button.rb
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
module Kiso
|
|
2
2
|
module Themes
|
|
3
|
+
# Clickable button with color, variant, and size axes.
|
|
4
|
+
#
|
|
5
|
+
# Renders as a +<button>+ by default; the partial switches to +<a>+ when
|
|
6
|
+
# +href:+ is provided (smart tag).
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# Button.render(color: :primary, variant: :solid, size: :md)
|
|
10
|
+
#
|
|
11
|
+
# Variants:
|
|
12
|
+
# - +color+ — :primary (default), :secondary, :success, :info, :warning, :error, :neutral
|
|
13
|
+
# - +variant+ — :solid (default), :outline, :soft, :subtle, :ghost, :link
|
|
14
|
+
# - +size+ — :xs, :sm, :md (default), :lg, :xl
|
|
15
|
+
# - +block+ — +true+ for full-width, +false+ (default)
|
|
3
16
|
Button = ClassVariants.build(
|
|
4
17
|
base: "inline-flex items-center justify-center gap-2 font-medium whitespace-nowrap shrink-0 " \
|
|
5
18
|
"transition-all " \
|
|
6
19
|
"focus-visible:outline-2 focus-visible:outline-offset-2 " \
|
|
7
20
|
"disabled:pointer-events-none disabled:opacity-50 " \
|
|
8
21
|
"aria-disabled:cursor-not-allowed aria-disabled:opacity-50 " \
|
|
9
|
-
"
|
|
22
|
+
"#{Shared::SVG_BASE}",
|
|
10
23
|
variants: {
|
|
11
24
|
variant: {
|
|
12
25
|
solid: "",
|
|
@@ -21,7 +34,7 @@ module Kiso
|
|
|
21
34
|
sm: "h-8 px-3 py-1.5 text-xs rounded-md gap-1.5 has-[>svg]:px-2.5",
|
|
22
35
|
md: "h-9 px-4 py-2 text-sm rounded-md gap-2 has-[>svg]:px-3",
|
|
23
36
|
lg: "h-10 px-5 py-2.5 text-sm rounded-md gap-2 has-[>svg]:px-4",
|
|
24
|
-
xl: "h-11 px-6 py-3 text-base rounded-
|
|
37
|
+
xl: "h-11 px-6 py-3 text-base rounded-md gap-2.5 has-[>svg]:px-5 [&_svg:not([class*='size-'])]:size-5"
|
|
25
38
|
},
|
|
26
39
|
color: COLORS.index_with { "" },
|
|
27
40
|
block: {
|
data/lib/kiso/themes/card.rb
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
module Kiso
|
|
2
2
|
module Themes
|
|
3
|
+
# Container card with header, content, and footer sections.
|
|
4
|
+
#
|
|
5
|
+
# @example
|
|
6
|
+
# Card.render(variant: :outline)
|
|
7
|
+
#
|
|
8
|
+
# Variants:
|
|
9
|
+
# - +variant+ — :outline (default), :soft, :subtle
|
|
10
|
+
#
|
|
11
|
+
# Sub-parts: {CardHeader}, {CardTitle}, {CardDescription}, {CardAction},
|
|
12
|
+
# {CardContent}, {CardFooter}
|
|
13
|
+
#
|
|
3
14
|
# shadcn base: bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm
|
|
4
15
|
# We use variant: instead of hardcoded border + shadow, and our semantic tokens.
|
|
5
16
|
Card = ClassVariants.build(
|
|
@@ -16,9 +27,9 @@ module Kiso
|
|
|
16
27
|
|
|
17
28
|
# shadcn: @container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6
|
|
18
29
|
# has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6
|
|
19
|
-
# Simplified: we don't have CardAction yet, so flex-col instead of grid.
|
|
20
30
|
CardHeader = ClassVariants.build(
|
|
21
|
-
base: "
|
|
31
|
+
base: "grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 " \
|
|
32
|
+
"has-[>[data-card-part=action]]:grid-cols-[1fr_auto]"
|
|
22
33
|
)
|
|
23
34
|
|
|
24
35
|
# shadcn: leading-none font-semibold
|
|
@@ -31,6 +42,11 @@ module Kiso
|
|
|
31
42
|
base: "text-sm text-muted-foreground"
|
|
32
43
|
)
|
|
33
44
|
|
|
45
|
+
# shadcn: col-start-2 row-span-2 row-start-1 self-start justify-self-end
|
|
46
|
+
CardAction = ClassVariants.build(
|
|
47
|
+
base: "col-start-2 row-span-2 row-start-1 self-start justify-self-end"
|
|
48
|
+
)
|
|
49
|
+
|
|
34
50
|
# shadcn: px-6
|
|
35
51
|
CardContent = ClassVariants.build(
|
|
36
52
|
base: "px-6"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Native +<input type="checkbox">+ styled with +appearance-none+ and
|
|
4
|
+
# semantic color tokens.
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# Checkbox.render(color: :primary)
|
|
8
|
+
#
|
|
9
|
+
# Variants:
|
|
10
|
+
# - +color+ — :primary (default), :secondary, :success, :info, :warning, :error, :neutral
|
|
11
|
+
Checkbox = ClassVariants.build(
|
|
12
|
+
base: "appearance-none size-4 shrink-0 rounded-[4px] " \
|
|
13
|
+
"ring ring-inset ring-accented shadow-xs " \
|
|
14
|
+
"transition-shadow outline-none " \
|
|
15
|
+
"disabled:cursor-not-allowed disabled:opacity-50 " \
|
|
16
|
+
"focus-visible:ring-[3px] " \
|
|
17
|
+
"aria-invalid:ring-error/30 aria-invalid:ring-2",
|
|
18
|
+
variants: {
|
|
19
|
+
color: COLORS.index_with { "" }
|
|
20
|
+
},
|
|
21
|
+
compound_variants: [
|
|
22
|
+
{color: :primary, class: "checked:bg-primary checked:ring-primary checked:text-primary-foreground focus-visible:ring-primary/50"},
|
|
23
|
+
{color: :secondary, class: "checked:bg-secondary checked:ring-secondary checked:text-secondary-foreground focus-visible:ring-secondary/50"},
|
|
24
|
+
{color: :success, class: "checked:bg-success checked:ring-success checked:text-success-foreground focus-visible:ring-success/50"},
|
|
25
|
+
{color: :info, class: "checked:bg-info checked:ring-info checked:text-info-foreground focus-visible:ring-info/50"},
|
|
26
|
+
{color: :warning, class: "checked:bg-warning checked:ring-warning checked:text-warning-foreground focus-visible:ring-warning/50"},
|
|
27
|
+
{color: :error, class: "checked:bg-error checked:ring-error checked:text-error-foreground focus-visible:ring-error/50"},
|
|
28
|
+
{color: :neutral, class: "checked:bg-inverted checked:ring-inverted checked:text-inverted-foreground focus-visible:ring-inverted/50"}
|
|
29
|
+
],
|
|
30
|
+
defaults: {color: :primary}
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
ColorModeButton = ClassVariants.build(
|
|
4
|
+
base: "inline-flex items-center justify-center rounded-md text-foreground/50 hover:text-foreground hover:bg-accent transition-colors duration-150 shrink-0 cursor-pointer",
|
|
5
|
+
variants: {
|
|
6
|
+
size: {
|
|
7
|
+
sm: "w-7 h-7 [&>svg]:size-3.5",
|
|
8
|
+
md: "w-8 h-8 [&>svg]:size-4",
|
|
9
|
+
lg: "w-9 h-9 [&>svg]:size-5"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
defaults: {size: :md}
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Searchable dropdown (autocomplete) with keyboard navigation.
|
|
4
|
+
#
|
|
5
|
+
# @example
|
|
6
|
+
# Combobox.render
|
|
7
|
+
#
|
|
8
|
+
# Sub-parts: {ComboboxInput}, {ComboboxContent}, {ComboboxList},
|
|
9
|
+
# {ComboboxItem}, {ComboboxItemIndicator}, {ComboboxGroup}, {ComboboxLabel},
|
|
10
|
+
# {ComboboxEmpty}, {ComboboxSeparator}, {ComboboxChips}, {ComboboxChip},
|
|
11
|
+
# {ComboboxChipsInput}
|
|
12
|
+
Combobox = ClassVariants.build(
|
|
13
|
+
base: "relative text-foreground"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# Input wrapper (replicates {InputGroup} pattern with embedded text input).
|
|
17
|
+
ComboboxInput = ClassVariants.build(
|
|
18
|
+
base: "text-foreground flex w-full items-center rounded-md " \
|
|
19
|
+
"bg-background ring ring-inset ring-accented shadow-xs " \
|
|
20
|
+
"h-9 min-w-0 " \
|
|
21
|
+
"has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-inset has-[:focus-visible]:ring-primary " \
|
|
22
|
+
"has-[[aria-invalid]]:ring-error " \
|
|
23
|
+
"[&_input]:flex-1 [&_input]:rounded-none [&_input]:border-0 [&_input]:shadow-none " \
|
|
24
|
+
"[&_input]:ring-0 [&_input]:bg-transparent [&_input]:focus-visible:ring-0 " \
|
|
25
|
+
"[&_input]:h-full [&_input]:px-3 [&_input]:py-1 [&_input]:text-base [&_input]:md:text-sm " \
|
|
26
|
+
"[&_input]:outline-none [&_input]:placeholder:text-muted-foreground " \
|
|
27
|
+
"[&_input]:disabled:cursor-not-allowed [&_input]:disabled:opacity-50"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Dropdown panel containing the filtered list of items.
|
|
31
|
+
ComboboxContent = ClassVariants.build(
|
|
32
|
+
base: "bg-background text-foreground z-50 max-h-96 min-w-32 " \
|
|
33
|
+
"overflow-hidden rounded-md shadow-md ring ring-inset ring-border"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Scrollable list container inside {ComboboxContent}.
|
|
37
|
+
ComboboxList = ClassVariants.build(
|
|
38
|
+
base: "scroll-py-1 overflow-y-auto p-1"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Selectable option within the combobox dropdown.
|
|
42
|
+
ComboboxItem = ClassVariants.build(
|
|
43
|
+
base: "relative flex w-full cursor-default items-center gap-2 rounded-sm " \
|
|
44
|
+
"py-1.5 pr-8 pl-2 text-sm outline-none select-none " \
|
|
45
|
+
"data-[highlighted]:bg-elevated data-[highlighted]:text-foreground " \
|
|
46
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50 " \
|
|
47
|
+
"#{Shared::SVG_BASE}"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Check mark indicator on the selected item.
|
|
51
|
+
ComboboxItemIndicator = ClassVariants.build(
|
|
52
|
+
base: "pointer-events-none absolute right-2 flex size-4 items-center justify-center"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Semantic grouping wrapper for related combobox items.
|
|
56
|
+
ComboboxGroup = ClassVariants.build(
|
|
57
|
+
base: ""
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Non-interactive heading for a {ComboboxGroup}.
|
|
61
|
+
ComboboxLabel = ClassVariants.build(
|
|
62
|
+
base: Shared::MENU_LABEL
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# "No results" message shown when the filter matches nothing.
|
|
66
|
+
ComboboxEmpty = ClassVariants.build(
|
|
67
|
+
base: "text-muted-foreground flex w-full justify-center py-2 text-center text-sm"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Horizontal divider between combobox items or groups.
|
|
71
|
+
ComboboxSeparator = ClassVariants.build(
|
|
72
|
+
base: Shared::ITEM_SEPARATOR
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Multi-select input container displaying selected values as chips.
|
|
76
|
+
ComboboxChips = ClassVariants.build(
|
|
77
|
+
base: "text-foreground flex min-h-9 flex-wrap items-center gap-1.5 rounded-md " \
|
|
78
|
+
"bg-background ring ring-inset ring-accented shadow-xs " \
|
|
79
|
+
"px-2.5 py-1.5 text-sm transition-[color,box-shadow] " \
|
|
80
|
+
"focus-within:ring-2 focus-within:ring-inset focus-within:ring-primary " \
|
|
81
|
+
"has-[[aria-invalid]]:ring-error"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Individual chip representing a selected value in {ComboboxChips}.
|
|
85
|
+
ComboboxChip = ClassVariants.build(
|
|
86
|
+
base: "bg-muted text-foreground flex h-5.5 w-fit items-center " \
|
|
87
|
+
"justify-center gap-1 rounded-sm px-1.5 text-xs font-medium whitespace-nowrap"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Inline text input within the {ComboboxChips} container.
|
|
91
|
+
ComboboxChipsInput = ClassVariants.build(
|
|
92
|
+
base: "min-w-16 flex-1 bg-transparent outline-none text-base md:text-sm " \
|
|
93
|
+
"placeholder:text-muted-foreground " \
|
|
94
|
+
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
95
|
+
)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Command palette (cmdk-style) with search input, grouped items, and
|
|
4
|
+
# keyboard navigation.
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# Command.render
|
|
8
|
+
#
|
|
9
|
+
# Sub-parts: {CommandInputWrapper}, {CommandInput}, {CommandList},
|
|
10
|
+
# {CommandEmpty}, {CommandGroup}, {CommandGroupHeading}, {CommandItem},
|
|
11
|
+
# {CommandSeparator}, {CommandShortcut}, {CommandDialog}, {CommandDialogContent}
|
|
12
|
+
Command = ClassVariants.build(
|
|
13
|
+
base: "bg-background text-foreground flex h-full w-full flex-col overflow-hidden rounded-md"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# Container for the search icon and input, separated from the list by a border.
|
|
17
|
+
CommandInputWrapper = ClassVariants.build(
|
|
18
|
+
base: "flex h-9 items-center gap-2 border-b border-border px-3"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# The search text input element.
|
|
22
|
+
CommandInput = ClassVariants.build(
|
|
23
|
+
base: "placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent " \
|
|
24
|
+
"py-3 text-sm outline-none " \
|
|
25
|
+
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# Scrollable results container.
|
|
29
|
+
CommandList = ClassVariants.build(
|
|
30
|
+
base: "max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# "No results" message shown when the search matches nothing.
|
|
34
|
+
CommandEmpty = ClassVariants.build(
|
|
35
|
+
base: "py-6 text-center text-sm"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Logical group of related command items.
|
|
39
|
+
CommandGroup = ClassVariants.build(
|
|
40
|
+
base: "text-foreground overflow-hidden p-1"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Label text displayed above a {CommandGroup}.
|
|
44
|
+
CommandGroupHeading = ClassVariants.build(
|
|
45
|
+
base: "text-muted-foreground px-2 py-1.5 text-xs font-medium"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# Selectable action item within the command palette.
|
|
49
|
+
CommandItem = ClassVariants.build(
|
|
50
|
+
base: "data-[selected]:bg-elevated data-[selected]:text-foreground " \
|
|
51
|
+
"[&_svg:not([class*='text-'])]:text-muted-foreground " \
|
|
52
|
+
"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm " \
|
|
53
|
+
"outline-none select-none " \
|
|
54
|
+
"data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 " \
|
|
55
|
+
"#{Shared::SVG_BASE}"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Horizontal divider between command groups.
|
|
59
|
+
CommandSeparator = ClassVariants.build(
|
|
60
|
+
base: "bg-border -mx-1 h-px"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# Keyboard shortcut hint displayed on the right side of a {CommandItem}.
|
|
64
|
+
CommandShortcut = ClassVariants.build(
|
|
65
|
+
base: Shared::MENU_SHORTCUT
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# The native +<dialog>+ element for modal command palette usage.
|
|
69
|
+
CommandDialog = ClassVariants.build(
|
|
70
|
+
base: "fixed inset-0 z-50 m-0 h-full w-full max-w-none max-h-none bg-black/50 p-0 " \
|
|
71
|
+
"flex items-center justify-center backdrop:bg-transparent open:flex"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Inner content wrapper inside the {CommandDialog}.
|
|
75
|
+
CommandDialogContent = ClassVariants.build(
|
|
76
|
+
base: "bg-background text-foreground overflow-hidden rounded-lg ring ring-inset ring-border shadow-lg w-full max-w-lg"
|
|
77
|
+
)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
DashboardGroup = ClassVariants.build(
|
|
4
|
+
base: "grid h-dvh overflow-hidden bg-background text-foreground antialiased"
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
DashboardNavbar = ClassVariants.build(
|
|
8
|
+
base: "flex items-center gap-3 px-4 border-b border-border bg-background shrink-0 z-[--z-topbar]"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
DashboardNavbarToggle = ClassVariants.build(
|
|
12
|
+
base: "flex items-center justify-center w-8 h-8 rounded-md text-foreground/50 hover:text-foreground hover:bg-accent transition-colors duration-150 shrink-0"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
DashboardSidebar = ClassVariants.build(
|
|
16
|
+
base: "overflow-hidden"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
DashboardPanel = ClassVariants.build(
|
|
20
|
+
base: "min-w-0 overflow-y-auto bg-background"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
DashboardSidebarHeader = ClassVariants.build(
|
|
24
|
+
base: "shrink-0 flex items-center gap-1.5 px-4"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
DashboardSidebarFooter = ClassVariants.build(
|
|
28
|
+
base: "shrink-0 flex items-center gap-1.5 px-4 py-2"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
DashboardSidebarToggle = ClassVariants.build(
|
|
32
|
+
base: "lg:hidden flex items-center justify-center w-8 h-8 rounded-md text-foreground/50 hover:text-foreground hover:bg-accent transition-colors duration-150 shrink-0 cursor-pointer"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
DashboardSidebarCollapse = ClassVariants.build(
|
|
36
|
+
base: "hidden lg:flex items-center justify-center w-8 h-8 rounded-md text-foreground/50 hover:text-foreground hover:bg-accent transition-colors duration-150 shrink-0 cursor-pointer"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
DashboardToolbar = ClassVariants.build(
|
|
40
|
+
base: "shrink-0 flex items-center justify-between border-b border-border px-4 sm:px-6 gap-1.5 overflow-x-auto h-(--topbar-height)"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
DashboardToolbarLeft = ClassVariants.build(
|
|
44
|
+
base: "flex items-center gap-1.5"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
DashboardToolbarRight = ClassVariants.build(
|
|
48
|
+
base: "flex items-center gap-1.5"
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Context menu or action menu triggered by a button click.
|
|
4
|
+
#
|
|
5
|
+
# @example
|
|
6
|
+
# DropdownMenu.render
|
|
7
|
+
#
|
|
8
|
+
# Sub-parts: {DropdownMenuTrigger}, {DropdownMenuContent}, {DropdownMenuItem},
|
|
9
|
+
# {DropdownMenuCheckboxItem}, {DropdownMenuRadioGroup}, {DropdownMenuRadioItem},
|
|
10
|
+
# {DropdownMenuLabel}, {DropdownMenuSeparator}, {DropdownMenuShortcut},
|
|
11
|
+
# {DropdownMenuGroup}, {DropdownMenuSub}, {DropdownMenuSubTrigger},
|
|
12
|
+
# {DropdownMenuSubContent}
|
|
13
|
+
DropdownMenu = ClassVariants.build(
|
|
14
|
+
base: "relative inline-block text-foreground"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# Wrapper for the button that opens the menu.
|
|
18
|
+
DropdownMenuTrigger = ClassVariants.build(
|
|
19
|
+
base: "inline-flex"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# The dropdown panel containing menu items.
|
|
23
|
+
DropdownMenuContent = ClassVariants.build(
|
|
24
|
+
base: "bg-background text-foreground z-50 min-w-32 " \
|
|
25
|
+
"overflow-x-hidden overflow-y-auto rounded-md ring ring-inset ring-border p-1 shadow-md"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# Clickable menu action. Supports a +destructive+ variant for
|
|
29
|
+
# dangerous actions (delete, remove, etc.).
|
|
30
|
+
#
|
|
31
|
+
# Variants:
|
|
32
|
+
# - +variant+ — :default, :destructive
|
|
33
|
+
DropdownMenuItem = ClassVariants.build(
|
|
34
|
+
base: "relative flex cursor-default items-center gap-2 rounded-sm " \
|
|
35
|
+
"px-2 py-1.5 text-sm outline-none select-none " \
|
|
36
|
+
"data-[highlighted]:bg-elevated data-[highlighted]:text-foreground " \
|
|
37
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50 " \
|
|
38
|
+
"data-[inset]:pl-8 " \
|
|
39
|
+
"#{Shared::SVG_BASE} " \
|
|
40
|
+
"[&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
41
|
+
variants: {
|
|
42
|
+
variant: {
|
|
43
|
+
default: "",
|
|
44
|
+
destructive: "text-error data-[highlighted]:bg-error/10 data-[highlighted]:text-error " \
|
|
45
|
+
"[&_svg:not([class*='text-'])]:text-error"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
defaults: {variant: :default}
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Menu item with a checkbox indicator. Uses {Shared::CHECKABLE_ITEM} base.
|
|
52
|
+
DropdownMenuCheckboxItem = ClassVariants.build(
|
|
53
|
+
base: Shared::CHECKABLE_ITEM
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# Wrapper for a set of mutually exclusive {DropdownMenuRadioItem} elements.
|
|
57
|
+
DropdownMenuRadioGroup = ClassVariants.build(
|
|
58
|
+
base: ""
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Menu item with a radio indicator. Uses {Shared::CHECKABLE_ITEM} base.
|
|
62
|
+
DropdownMenuRadioItem = ClassVariants.build(
|
|
63
|
+
base: Shared::CHECKABLE_ITEM
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Non-interactive heading within the menu.
|
|
67
|
+
DropdownMenuLabel = ClassVariants.build(
|
|
68
|
+
base: "px-2 py-1.5 text-sm font-medium data-[inset]:pl-8"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Horizontal divider between menu sections.
|
|
72
|
+
DropdownMenuSeparator = ClassVariants.build(
|
|
73
|
+
base: Shared::ITEM_SEPARATOR
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Keyboard shortcut hint on the right side of a {DropdownMenuItem}.
|
|
77
|
+
DropdownMenuShortcut = ClassVariants.build(
|
|
78
|
+
base: Shared::MENU_SHORTCUT
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Semantic grouping wrapper for related menu items.
|
|
82
|
+
DropdownMenuGroup = ClassVariants.build(
|
|
83
|
+
base: ""
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Wrapper for a nested sub-menu (trigger + content pair).
|
|
87
|
+
DropdownMenuSub = ClassVariants.build(
|
|
88
|
+
base: "relative"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Menu item that opens a nested {DropdownMenuSubContent} on hover.
|
|
92
|
+
DropdownMenuSubTrigger = ClassVariants.build(
|
|
93
|
+
base: "flex cursor-default items-center gap-2 rounded-sm " \
|
|
94
|
+
"px-2 py-1.5 text-sm outline-none select-none " \
|
|
95
|
+
"data-[highlighted]:bg-elevated data-[highlighted]:text-foreground " \
|
|
96
|
+
"data-[state=open]:bg-elevated data-[state=open]:text-foreground " \
|
|
97
|
+
"data-[inset]:pl-8 " \
|
|
98
|
+
"#{Shared::SVG_BASE} " \
|
|
99
|
+
"[&_svg:not([class*='text-'])]:text-muted-foreground"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Panel for nested sub-menu items (same as {DropdownMenuContent} but +shadow-lg+).
|
|
103
|
+
DropdownMenuSubContent = ClassVariants.build(
|
|
104
|
+
base: "bg-background text-foreground z-50 min-w-32 " \
|
|
105
|
+
"overflow-hidden rounded-md ring ring-inset ring-border p-1 shadow-lg"
|
|
106
|
+
)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Empty state placeholder for when there's no content to display.
|
|
4
|
+
#
|
|
5
|
+
# Centered layout with dashed border (border becomes visible when the user
|
|
6
|
+
# adds +border+ via +css_classes:+).
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# Empty.render
|
|
10
|
+
#
|
|
11
|
+
# Sub-parts: {EmptyHeader}, {EmptyMedia}, {EmptyTitle}, {EmptyDescription},
|
|
12
|
+
# {EmptyContent}
|
|
13
|
+
#
|
|
14
|
+
# shadcn base: flex min-w-0 flex-1 flex-col ... border-dashed p-6 ... md:p-12
|
|
15
|
+
Empty = ClassVariants.build(
|
|
16
|
+
base: "flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance text-foreground md:p-12"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# Container for the empty state's title and description.
|
|
20
|
+
EmptyHeader = ClassVariants.build(
|
|
21
|
+
base: "flex max-w-sm flex-col items-center gap-2 text-center"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Media container for an illustration or icon above the title.
|
|
25
|
+
#
|
|
26
|
+
# Variants:
|
|
27
|
+
# - +variant+ — :default (transparent), :icon (muted background + rounded container)
|
|
28
|
+
EmptyMedia = ClassVariants.build(
|
|
29
|
+
base: "flex shrink-0 items-center justify-center mb-2 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
30
|
+
variants: {
|
|
31
|
+
variant: {
|
|
32
|
+
default: "bg-transparent",
|
|
33
|
+
icon: "bg-muted text-foreground size-10 rounded-lg [&_svg:not([class*='size-'])]:size-6"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
defaults: {variant: :default}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Empty state heading text.
|
|
40
|
+
EmptyTitle = ClassVariants.build(
|
|
41
|
+
base: "text-lg font-medium tracking-tight"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Empty state body text with automatic link styling.
|
|
45
|
+
EmptyDescription = ClassVariants.build(
|
|
46
|
+
base: "text-muted-foreground text-sm/relaxed [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Container for action buttons or other interactive content.
|
|
50
|
+
EmptyContent = ClassVariants.build(
|
|
51
|
+
base: "flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance"
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Form field wrapper that groups a label, input, description, and error message.
|
|
4
|
+
#
|
|
5
|
+
# @example
|
|
6
|
+
# Field.render(orientation: :vertical)
|
|
7
|
+
#
|
|
8
|
+
# Variants:
|
|
9
|
+
# - +orientation+ — :vertical (default), :horizontal, :responsive
|
|
10
|
+
#
|
|
11
|
+
# Sub-parts: {FieldContent}, {FieldLabel}, {FieldTitle}, {FieldDescription},
|
|
12
|
+
# {FieldError}, {FieldSeparator}, {FieldSeparatorText}
|
|
13
|
+
Field = ClassVariants.build(
|
|
14
|
+
base: "group/field flex w-full gap-3 text-foreground data-[invalid=true]:text-error",
|
|
15
|
+
variants: {
|
|
16
|
+
orientation: {
|
|
17
|
+
vertical: "flex-col [&>*]:w-full [&>.sr-only]:w-auto",
|
|
18
|
+
horizontal: "flex-row items-center " \
|
|
19
|
+
"[&>[data-slot=field-label]]:flex-auto " \
|
|
20
|
+
"has-[>[data-slot=field-content]]:items-start " \
|
|
21
|
+
"has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
|
|
22
|
+
responsive: "flex-col [&>*]:w-full [&>.sr-only]:w-auto " \
|
|
23
|
+
"@md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto " \
|
|
24
|
+
"@md/field-group:[&>[data-slot=field-label]]:flex-auto " \
|
|
25
|
+
"@md/field-group:has-[>[data-slot=field-content]]:items-start " \
|
|
26
|
+
"@md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
defaults: {orientation: :vertical}
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Wrapper for the input element plus description/error text within a {Field}.
|
|
33
|
+
FieldContent = ClassVariants.build(
|
|
34
|
+
base: "group/field-content flex flex-1 flex-col gap-1.5 leading-snug"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Label container within a {Field}. Supports nested field layouts for
|
|
38
|
+
# checkbox/radio card patterns.
|
|
39
|
+
FieldLabel = ClassVariants.build(
|
|
40
|
+
base: "group/field-label peer/field-label flex w-fit gap-2 leading-snug " \
|
|
41
|
+
"group-data-[disabled=true]/field:opacity-50 " \
|
|
42
|
+
"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col " \
|
|
43
|
+
"has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border " \
|
|
44
|
+
"[&>*[data-slot=field]]:p-4"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Title text within a {FieldLabel}.
|
|
48
|
+
FieldTitle = ClassVariants.build(
|
|
49
|
+
base: "flex w-fit items-center gap-2 text-sm leading-snug font-medium " \
|
|
50
|
+
"group-data-[disabled=true]/field:opacity-50"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Help text below the input. Includes automatic link styling.
|
|
54
|
+
FieldDescription = ClassVariants.build(
|
|
55
|
+
base: "text-muted-foreground text-sm leading-normal font-normal " \
|
|
56
|
+
"group-has-[[data-orientation=horizontal]]/field:text-balance " \
|
|
57
|
+
"last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5 " \
|
|
58
|
+
"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Validation error message displayed below the input.
|
|
62
|
+
FieldError = ClassVariants.build(
|
|
63
|
+
base: "text-error text-sm font-normal"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Horizontal rule between fields (e.g. "or" divider).
|
|
67
|
+
FieldSeparator = ClassVariants.build(
|
|
68
|
+
base: "relative -my-2 h-5 text-sm"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Text label centered on the {FieldSeparator} line.
|
|
72
|
+
FieldSeparatorText = ClassVariants.build(
|
|
73
|
+
base: "bg-background text-muted-foreground relative mx-auto block w-fit px-2"
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Groups multiple {Field} elements with consistent vertical spacing.
|
|
4
|
+
#
|
|
5
|
+
# Supports nesting — inner field groups use tighter +gap-4+ spacing.
|
|
6
|
+
# Uses +@container/field-group+ for responsive field orientation queries.
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# FieldGroup.render
|
|
10
|
+
FieldGroup = ClassVariants.build(
|
|
11
|
+
base: "group/field-group @container/field-group flex w-full flex-col gap-7 " \
|
|
12
|
+
"[&>[data-slot=field-group]]:gap-4"
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
end
|