kiso 0.2.2.pre → 0.4.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 +35 -1
- data/README.md +16 -3
- data/app/assets/tailwind/kiso/dialog.css +46 -0
- data/app/assets/tailwind/kiso/engine.css +6 -3
- data/app/assets/tailwind/kiso/input-otp.css +17 -0
- data/app/assets/tailwind/kiso/palettes/blue.css +65 -0
- data/app/assets/tailwind/kiso/palettes/green.css +65 -0
- data/app/assets/tailwind/kiso/palettes/orange.css +65 -0
- data/app/assets/tailwind/kiso/palettes/violet.css +65 -0
- data/app/assets/tailwind/kiso/palettes/zinc.css +65 -0
- data/app/assets/tailwind/kiso/slider.css +27 -0
- data/app/helpers/kiso/app_component_helper.rb +53 -0
- data/app/helpers/kiso/component_helper.rb +110 -24
- data/app/helpers/kiso/ui_context_helper.rb +59 -0
- data/app/javascript/controllers/kiso/alert_controller.js +33 -0
- data/app/javascript/controllers/kiso/dialog_controller.js +140 -0
- data/app/javascript/controllers/kiso/index.js +6 -0
- data/app/javascript/controllers/kiso/slider_controller.js +276 -0
- data/app/views/kiso/components/_alert.html.erb +19 -3
- data/app/views/kiso/components/_alert_dialog.html.erb +28 -0
- data/app/views/kiso/components/_app.html.erb +7 -0
- data/app/views/kiso/components/_aspect_ratio.html.erb +8 -0
- data/app/views/kiso/components/_avatar.html.erb +3 -3
- data/app/views/kiso/components/_breadcrumb.html.erb +1 -1
- data/app/views/kiso/components/_button.html.erb +31 -17
- data/app/views/kiso/components/_color_mode_button.html.erb +1 -1
- data/app/views/kiso/components/_color_mode_select.html.erb +4 -4
- data/app/views/kiso/components/_container.html.erb +7 -0
- data/app/views/kiso/components/_dashboard_sidebar.html.erb +1 -1
- data/app/views/kiso/components/_dialog.html.erb +11 -0
- data/app/views/kiso/components/_footer.html.erb +7 -0
- data/app/views/kiso/components/_header.html.erb +7 -0
- data/app/views/kiso/components/_main.html.erb +7 -0
- data/app/views/kiso/components/_page.html.erb +7 -0
- data/app/views/kiso/components/_page_body.html.erb +7 -0
- data/app/views/kiso/components/_page_card.html.erb +40 -0
- data/app/views/kiso/components/_page_grid.html.erb +7 -0
- data/app/views/kiso/components/_page_header.html.erb +38 -0
- data/app/views/kiso/components/_page_section.html.erb +11 -0
- data/app/views/kiso/components/_pagination.html.erb +1 -1
- data/app/views/kiso/components/_select_native.html.erb +3 -3
- data/app/views/kiso/components/_skeleton.html.erb +5 -0
- data/app/views/kiso/components/_slider.html.erb +42 -0
- data/app/views/kiso/components/_switch.html.erb +2 -2
- data/app/views/kiso/components/alert/_actions.html.erb +7 -0
- data/app/views/kiso/components/alert_dialog/_action.html.erb +8 -0
- data/app/views/kiso/components/alert_dialog/_cancel.html.erb +8 -0
- data/app/views/kiso/components/alert_dialog/_description.html.erb +8 -0
- data/app/views/kiso/components/alert_dialog/_footer.html.erb +7 -0
- data/app/views/kiso/components/alert_dialog/_header.html.erb +7 -0
- data/app/views/kiso/components/alert_dialog/_media.html.erb +7 -0
- data/app/views/kiso/components/alert_dialog/_title.html.erb +8 -0
- data/app/views/kiso/components/breadcrumb/_ellipsis.html.erb +1 -1
- data/app/views/kiso/components/combobox/_input.html.erb +1 -1
- data/app/views/kiso/components/combobox/_item.html.erb +2 -2
- data/app/views/kiso/components/combobox/_list.html.erb +2 -1
- data/app/views/kiso/components/command/_group.html.erb +2 -2
- data/app/views/kiso/components/command/_input.html.erb +3 -2
- data/app/views/kiso/components/command/_list.html.erb +2 -1
- data/app/views/kiso/components/dashboard_navbar/_toggle.html.erb +1 -1
- data/app/views/kiso/components/dashboard_sidebar/_collapse.html.erb +1 -1
- data/app/views/kiso/components/dashboard_sidebar/_toggle.html.erb +1 -1
- data/app/views/kiso/components/dialog/_body.html.erb +7 -0
- data/app/views/kiso/components/dialog/_close.html.erb +10 -0
- data/app/views/kiso/components/dialog/_description.html.erb +7 -0
- data/app/views/kiso/components/dialog/_footer.html.erb +7 -0
- data/app/views/kiso/components/dialog/_header.html.erb +7 -0
- data/app/views/kiso/components/dialog/_title.html.erb +7 -0
- data/app/views/kiso/components/empty/_actions.html.erb +7 -0
- data/app/views/kiso/components/nav/_item.html.erb +2 -2
- data/app/views/kiso/components/nav/_section.html.erb +5 -5
- data/app/views/kiso/components/page/_center.html.erb +7 -0
- data/app/views/kiso/components/page/_left.html.erb +7 -0
- data/app/views/kiso/components/page/_right.html.erb +7 -0
- data/app/views/kiso/components/page_card/_body.html.erb +7 -0
- data/app/views/kiso/components/page_card/_description.html.erb +7 -0
- data/app/views/kiso/components/page_card/_footer.html.erb +7 -0
- data/app/views/kiso/components/page_card/_header.html.erb +7 -0
- data/app/views/kiso/components/page_card/_icon.html.erb +7 -0
- data/app/views/kiso/components/page_card/_title.html.erb +7 -0
- data/app/views/kiso/components/page_header/_description.html.erb +7 -0
- data/app/views/kiso/components/page_header/_headline.html.erb +7 -0
- data/app/views/kiso/components/page_header/_links.html.erb +7 -0
- data/app/views/kiso/components/page_header/_title.html.erb +7 -0
- data/app/views/kiso/components/page_section/_body.html.erb +7 -0
- data/app/views/kiso/components/page_section/_description.html.erb +7 -0
- data/app/views/kiso/components/page_section/_header.html.erb +7 -0
- data/app/views/kiso/components/page_section/_headline.html.erb +7 -0
- data/app/views/kiso/components/page_section/_links.html.erb +7 -0
- data/app/views/kiso/components/page_section/_title.html.erb +7 -0
- data/app/views/kiso/components/page_section/_wrapper.html.erb +7 -0
- data/app/views/kiso/components/pagination/_ellipsis.html.erb +1 -1
- data/app/views/kiso/components/pagination/_next.html.erb +2 -2
- data/app/views/kiso/components/pagination/_previous.html.erb +2 -2
- data/app/views/kiso/components/select/_item.html.erb +2 -2
- data/config/locales/en.yml +33 -0
- data/lib/generators/kiso/component/USAGE +35 -0
- data/lib/generators/kiso/component/component_generator.rb +104 -0
- data/lib/generators/kiso/component/templates/partial.html.erb.tt +7 -0
- data/lib/generators/kiso/component/templates/sub_part_partial.html.erb.tt +7 -0
- data/lib/generators/kiso/component/templates/sub_part_theme.rb.tt +21 -0
- data/lib/generators/kiso/component/templates/theme.rb.tt +21 -0
- data/lib/kiso/configuration.rb +40 -0
- data/lib/kiso/engine.rb +105 -1
- data/lib/kiso/presets/rounded.rb +136 -0
- data/lib/kiso/presets/sharp.rb +178 -0
- data/lib/kiso/presets.rb +49 -0
- data/lib/kiso/theme_overrides.rb +5 -1
- data/lib/kiso/themes/alert.rb +24 -11
- data/lib/kiso/themes/alert_dialog.rb +78 -0
- data/lib/kiso/themes/aspect_ratio.rb +16 -0
- data/lib/kiso/themes/dashboard.rb +3 -3
- data/lib/kiso/themes/dialog.rb +57 -0
- data/lib/kiso/themes/empty.rb +6 -1
- data/lib/kiso/themes/input_otp.rb +2 -2
- data/lib/kiso/themes/layout.rb +69 -0
- data/lib/kiso/themes/page.rb +295 -0
- data/lib/kiso/themes/skeleton.rb +16 -0
- data/lib/kiso/themes/slider.rb +53 -0
- data/lib/kiso/version.rb +1 -1
- data/lib/kiso.rb +11 -0
- metadata +89 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Alert dialog for confirmations that require an explicit user action.
|
|
4
|
+
# Wraps the native +<dialog>+ element with +role="alertdialog"+.
|
|
5
|
+
# Unlike {Dialog}, cannot be dismissed by backdrop click or Escape key.
|
|
6
|
+
#
|
|
7
|
+
# Reuses the +kiso--dialog+ Stimulus controller with
|
|
8
|
+
# +dismissable: false+.
|
|
9
|
+
#
|
|
10
|
+
# Sub-parts: {AlertDialogContent}, {AlertDialogHeader},
|
|
11
|
+
# {AlertDialogTitle}, {AlertDialogDescription}, {AlertDialogMedia},
|
|
12
|
+
# {AlertDialogFooter}, {AlertDialogAction}, {AlertDialogCancel}
|
|
13
|
+
AlertDialog = ClassVariants.build(
|
|
14
|
+
base: "fixed inset-0 z-50 m-0 h-full w-full max-w-none max-h-none bg-black/50 p-0 " \
|
|
15
|
+
"items-center justify-center backdrop:bg-transparent open:flex"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# The centered panel inside the {AlertDialog} overlay. Supports
|
|
19
|
+
# +size:+ variant (+:default+ or +:sm+).
|
|
20
|
+
AlertDialogContent = ClassVariants.build(
|
|
21
|
+
base: "bg-background text-foreground relative grid w-full max-w-[calc(100%-2rem)] " \
|
|
22
|
+
"gap-4 rounded-lg border p-6 shadow-lg outline-none group/alert-dialog-content",
|
|
23
|
+
variants: {
|
|
24
|
+
size: {
|
|
25
|
+
default: "sm:max-w-lg",
|
|
26
|
+
sm: "max-w-xs"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
defaults: {size: :default}
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Grid container for {AlertDialogTitle}, {AlertDialogDescription},
|
|
33
|
+
# and optional {AlertDialogMedia}. Adapts layout responsively when
|
|
34
|
+
# media is present via +has-[...]+ selectors.
|
|
35
|
+
AlertDialogHeader = ClassVariants.build(
|
|
36
|
+
base: "grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center " \
|
|
37
|
+
"has-[[data-slot=alert-dialog-media]]:grid-rows-[auto_auto_1fr] " \
|
|
38
|
+
"has-[[data-slot=alert-dialog-media]]:gap-x-6 " \
|
|
39
|
+
"sm:group-data-[size=default]/alert-dialog-content:place-items-start " \
|
|
40
|
+
"sm:group-data-[size=default]/alert-dialog-content:text-left " \
|
|
41
|
+
"sm:group-data-[size=default]/alert-dialog-content:has-[[data-slot=alert-dialog-media]]:grid-rows-[auto_1fr]"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Action buttons container. Reversed column on mobile, horizontal
|
|
45
|
+
# on desktop. Grid layout when parent content is +:sm+ size.
|
|
46
|
+
AlertDialogFooter = ClassVariants.build(
|
|
47
|
+
base: "flex flex-col-reverse gap-2 " \
|
|
48
|
+
"group-data-[size=sm]/alert-dialog-content:grid " \
|
|
49
|
+
"group-data-[size=sm]/alert-dialog-content:grid-cols-2 " \
|
|
50
|
+
"sm:flex-row sm:justify-end"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# The alert dialog heading. Renders as +<h2>+. Shifts to column 2
|
|
54
|
+
# when media is present in default size.
|
|
55
|
+
AlertDialogTitle = ClassVariants.build(
|
|
56
|
+
base: "text-lg font-semibold " \
|
|
57
|
+
"sm:group-data-[size=default]/alert-dialog-content:group-has-[[data-slot=alert-dialog-media]]/alert-dialog-content:col-start-2"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Descriptive text below the {AlertDialogTitle}.
|
|
61
|
+
AlertDialogDescription = ClassVariants.build(
|
|
62
|
+
base: "text-muted-foreground text-sm"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Optional icon or image container in the header. Renders as a
|
|
66
|
+
# rounded box with muted background. Spans 2 rows in default size.
|
|
67
|
+
AlertDialogMedia = ClassVariants.build(
|
|
68
|
+
base: "bg-muted mb-2 inline-flex size-16 items-center justify-center rounded-md " \
|
|
69
|
+
"sm:group-data-[size=default]/alert-dialog-content:row-span-2 " \
|
|
70
|
+
"*:[svg:not([class*='size-'])]:size-8"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Action and Cancel buttons are styled directly via
|
|
74
|
+
# {Kiso::Themes::Button} in their partials — no theme constants
|
|
75
|
+
# needed. See +alert_dialog/_action.html.erb+ and
|
|
76
|
+
# +alert_dialog/_cancel.html.erb+.
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Displays content within a desired width-to-height ratio.
|
|
4
|
+
#
|
|
5
|
+
# @example
|
|
6
|
+
# AspectRatio.render
|
|
7
|
+
#
|
|
8
|
+
# No variants — purely structural. The ratio is set via inline style
|
|
9
|
+
# on the partial (`aspect-ratio: <ratio>`).
|
|
10
|
+
#
|
|
11
|
+
# shadcn: Radix AspectRatio primitive with data-slot="aspect-ratio"
|
|
12
|
+
AspectRatio = ClassVariants.build(
|
|
13
|
+
base: "relative w-full"
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -5,7 +5,7 @@ module Kiso
|
|
|
5
5
|
)
|
|
6
6
|
|
|
7
7
|
DashboardNavbar = ClassVariants.build(
|
|
8
|
-
base: "flex items-center gap-3 px-4 border-b border-border bg-background shrink-0 z-
|
|
8
|
+
base: "flex items-center gap-3 px-4 border-b border-border bg-background shrink-0 z-(--z-topbar)"
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
DashboardNavbarToggle = ClassVariants.build(
|
|
@@ -21,11 +21,11 @@ module Kiso
|
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
DashboardSidebarHeader = ClassVariants.build(
|
|
24
|
-
base: "shrink-0 flex
|
|
24
|
+
base: "shrink-0 flex flex-col gap-2 p-2"
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
DashboardSidebarFooter = ClassVariants.build(
|
|
28
|
-
base: "shrink-0 flex
|
|
28
|
+
base: "shrink-0 flex flex-col gap-2 p-2"
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
DashboardSidebarToggle = ClassVariants.build(
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Modal dialog wrapping the native +<dialog>+ element. Opens with
|
|
4
|
+
# +showModal()+ via a Stimulus controller for proper focus trapping,
|
|
5
|
+
# backdrop, and Escape-to-close behavior.
|
|
6
|
+
#
|
|
7
|
+
# The dialog element itself acts as the backdrop overlay (same
|
|
8
|
+
# pattern as {CommandDialog}). A {DialogContent} wrapper inside
|
|
9
|
+
# provides the centered panel.
|
|
10
|
+
#
|
|
11
|
+
# Sub-parts: {DialogContent}, {DialogHeader}, {DialogTitle},
|
|
12
|
+
# {DialogDescription}, {DialogBody}, {DialogFooter}, {DialogClose}
|
|
13
|
+
Dialog = ClassVariants.build(
|
|
14
|
+
base: "fixed inset-0 z-50 m-0 h-full w-full max-w-none max-h-none bg-black/50 p-0 " \
|
|
15
|
+
"items-center justify-center backdrop:bg-transparent open:flex"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# The centered panel inside the {Dialog} overlay.
|
|
19
|
+
DialogContent = ClassVariants.build(
|
|
20
|
+
base: "bg-background text-foreground relative grid w-full max-w-[calc(100%-2rem)] " \
|
|
21
|
+
"gap-4 rounded-lg border p-6 shadow-lg outline-none sm:max-w-lg"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Flex column container for {DialogTitle} and {DialogDescription}.
|
|
25
|
+
DialogHeader = ClassVariants.build(
|
|
26
|
+
base: "flex flex-col gap-2 text-center sm:text-left"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# Reversed column layout on mobile, horizontal on desktop.
|
|
30
|
+
DialogFooter = ClassVariants.build(
|
|
31
|
+
base: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# The dialog heading. Renders as +<h2>+.
|
|
35
|
+
DialogTitle = ClassVariants.build(
|
|
36
|
+
base: "text-lg leading-none font-semibold"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Descriptive text below the {DialogTitle}.
|
|
40
|
+
DialogDescription = ClassVariants.build(
|
|
41
|
+
base: "text-muted-foreground text-sm"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Main content area between header and footer.
|
|
45
|
+
DialogBody = ClassVariants.build(
|
|
46
|
+
base: "text-sm"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Absolutely positioned close button in the top-right corner.
|
|
50
|
+
DialogClose = ClassVariants.build(
|
|
51
|
+
base: "absolute top-4 right-4 rounded-xs opacity-70 transition-opacity " \
|
|
52
|
+
"hover:opacity-100 focus-visible:outline-2 focus-visible:outline-offset-2 " \
|
|
53
|
+
"focus-visible:outline-ring disabled:pointer-events-none " \
|
|
54
|
+
"[&>svg]:size-4 cursor-pointer"
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
end
|
data/lib/kiso/themes/empty.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Kiso
|
|
|
9
9
|
# Empty.render
|
|
10
10
|
#
|
|
11
11
|
# Sub-parts: {EmptyHeader}, {EmptyMedia}, {EmptyTitle}, {EmptyDescription},
|
|
12
|
-
# {EmptyContent}
|
|
12
|
+
# {EmptyActions}, {EmptyContent}
|
|
13
13
|
#
|
|
14
14
|
# shadcn base: flex min-w-0 flex-1 flex-col ... border-dashed p-6 ... md:p-12
|
|
15
15
|
Empty = ClassVariants.build(
|
|
@@ -46,6 +46,11 @@ module Kiso
|
|
|
46
46
|
base: "text-muted-foreground text-sm/relaxed [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4"
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
+
# Centered button group for call-to-action buttons.
|
|
50
|
+
EmptyActions = ClassVariants.build(
|
|
51
|
+
base: "flex flex-wrap items-center justify-center gap-2"
|
|
52
|
+
)
|
|
53
|
+
|
|
49
54
|
# Container for action buttons or other interactive content.
|
|
50
55
|
EmptyContent = ClassVariants.build(
|
|
51
56
|
base: "flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance"
|
|
@@ -21,8 +21,8 @@ module Kiso
|
|
|
21
21
|
# InputOtpSlot.render(size: :md)
|
|
22
22
|
InputOtpSlot = ClassVariants.build(
|
|
23
23
|
base: "border-border relative flex items-center justify-center " \
|
|
24
|
-
"border
|
|
25
|
-
"first:
|
|
24
|
+
"border -ml-px shadow-xs transition-all outline-none " \
|
|
25
|
+
"first:ml-0 first:rounded-l-md last:rounded-r-md " \
|
|
26
26
|
"data-[active=true]:z-10 data-[active=true]:border-primary " \
|
|
27
27
|
"data-[active=true]:ring-[3px] data-[active=true]:ring-primary/50 " \
|
|
28
28
|
"aria-invalid:border-error " \
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Root application wrapper. Provides base structure and sets
|
|
4
|
+
# `text-foreground` for dark mode inheritance.
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# App.render
|
|
8
|
+
#
|
|
9
|
+
# No variants — purely structural.
|
|
10
|
+
App = ClassVariants.build(
|
|
11
|
+
base: "bg-background text-foreground antialiased"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
# Content containment with consistent max-width and padding.
|
|
15
|
+
#
|
|
16
|
+
# @example
|
|
17
|
+
# Container.render(size: :default)
|
|
18
|
+
#
|
|
19
|
+
# Variants:
|
|
20
|
+
# - +size+ — :narrow, :default, :wide, :full
|
|
21
|
+
#
|
|
22
|
+
# Nuxt UI base: w-full max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8
|
|
23
|
+
Container = ClassVariants.build(
|
|
24
|
+
base: "mx-auto w-full px-4 sm:px-6 lg:px-8",
|
|
25
|
+
variants: {
|
|
26
|
+
size: {
|
|
27
|
+
narrow: "max-w-3xl",
|
|
28
|
+
default: "max-w-7xl",
|
|
29
|
+
wide: "max-w-screen-2xl",
|
|
30
|
+
full: "max-w-full"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
defaults: {size: :default}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Site/app header. Semantic `<header>` element.
|
|
37
|
+
#
|
|
38
|
+
# @example
|
|
39
|
+
# Header.render
|
|
40
|
+
#
|
|
41
|
+
# No variants — purely structural.
|
|
42
|
+
#
|
|
43
|
+
# Nuxt UI base: bg-default/75 backdrop-blur border-b border-default
|
|
44
|
+
# h-(--ui-header-height) sticky top-0 z-50
|
|
45
|
+
Header = ClassVariants.build(
|
|
46
|
+
base: "bg-background/75 backdrop-blur border-b border-border sticky top-0 z-50"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Site/app footer. Semantic `<footer>` element.
|
|
50
|
+
#
|
|
51
|
+
# @example
|
|
52
|
+
# Footer.render
|
|
53
|
+
#
|
|
54
|
+
# No variants — purely structural.
|
|
55
|
+
Footer = ClassVariants.build(
|
|
56
|
+
base: ""
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Primary content area wrapper. Semantic `<main>` element.
|
|
60
|
+
#
|
|
61
|
+
# @example
|
|
62
|
+
# Main.render
|
|
63
|
+
#
|
|
64
|
+
# No variants — purely structural.
|
|
65
|
+
Main = ClassVariants.build(
|
|
66
|
+
base: "flex-1"
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Page layout wrapper with optional left/right sidebar grid.
|
|
4
|
+
#
|
|
5
|
+
# Provides a responsive grid that switches from stacked (mobile) to
|
|
6
|
+
# a 10-column grid (desktop). Left and right sidebars each take 2
|
|
7
|
+
# columns, the center adjusts automatically.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# Page.render
|
|
11
|
+
#
|
|
12
|
+
# Sub-parts: {PageLeft}, {PageCenter}, {PageRight}
|
|
13
|
+
#
|
|
14
|
+
# Nuxt UI base: flex flex-col lg:grid lg:grid-cols-10 lg:gap-10
|
|
15
|
+
Page = ClassVariants.build(
|
|
16
|
+
base: "flex flex-col lg:grid lg:grid-cols-10 lg:gap-10"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# Left sidebar slot — 2 columns on desktop.
|
|
20
|
+
#
|
|
21
|
+
# Nuxt UI: lg:col-span-2
|
|
22
|
+
PageLeft = ClassVariants.build(
|
|
23
|
+
base: "lg:col-span-2"
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Center content area — adjusts span based on sidebar presence.
|
|
27
|
+
#
|
|
28
|
+
# Nuxt UI: lg:col-span-8 (default), lg:col-span-6 (both sidebars),
|
|
29
|
+
# lg:col-span-10 (no sidebars)
|
|
30
|
+
PageCenter = ClassVariants.build(
|
|
31
|
+
base: "lg:col-span-8"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Right sidebar slot — 2 columns, ordered first on mobile, last on desktop.
|
|
35
|
+
#
|
|
36
|
+
# Nuxt UI: lg:col-span-2 order-first lg:order-last
|
|
37
|
+
PageRight = ClassVariants.build(
|
|
38
|
+
base: "lg:col-span-2 order-first lg:order-last"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Page header with title, description, and links.
|
|
42
|
+
#
|
|
43
|
+
# Section header for page-level content with border-bottom divider.
|
|
44
|
+
# Supports headline, title, description, and action links.
|
|
45
|
+
#
|
|
46
|
+
# @example
|
|
47
|
+
# PageHeader.render
|
|
48
|
+
#
|
|
49
|
+
# Sub-parts: {PageHeaderHeadline}, {PageHeaderTitle},
|
|
50
|
+
# {PageHeaderDescription}, {PageHeaderLinks}
|
|
51
|
+
#
|
|
52
|
+
# Nuxt UI base: relative border-b border-default py-8
|
|
53
|
+
PageHeader = ClassVariants.build(
|
|
54
|
+
base: "relative border-b border-border py-8 text-foreground"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Inner wrapper for page header content — flex row on desktop.
|
|
58
|
+
#
|
|
59
|
+
# Nuxt UI: flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4
|
|
60
|
+
PageHeaderWrapper = ClassVariants.build(
|
|
61
|
+
base: "flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Headline eyebrow text above the page header title.
|
|
65
|
+
#
|
|
66
|
+
# Nuxt UI: mb-2.5 text-sm font-semibold text-primary flex items-center gap-1.5
|
|
67
|
+
PageHeaderHeadline = ClassVariants.build(
|
|
68
|
+
base: "mb-2.5 text-sm font-semibold text-primary flex items-center gap-1.5"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Page header title — large bold heading.
|
|
72
|
+
#
|
|
73
|
+
# Nuxt UI: text-3xl sm:text-4xl text-pretty font-bold text-highlighted
|
|
74
|
+
PageHeaderTitle = ClassVariants.build(
|
|
75
|
+
base: "text-3xl sm:text-4xl text-pretty font-bold text-foreground"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Page header description text.
|
|
79
|
+
#
|
|
80
|
+
# Nuxt UI: text-lg text-pretty text-muted
|
|
81
|
+
PageHeaderDescription = ClassVariants.build(
|
|
82
|
+
base: "mt-4 text-lg text-pretty text-muted-foreground"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Action links container in page header.
|
|
86
|
+
#
|
|
87
|
+
# Nuxt UI: flex flex-wrap items-center gap-1.5
|
|
88
|
+
PageHeaderLinks = ClassVariants.build(
|
|
89
|
+
base: "flex flex-wrap items-center gap-1.5"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Page body — main content wrapper with vertical spacing.
|
|
93
|
+
#
|
|
94
|
+
# Nuxt UI base: mt-8 pb-24 space-y-12
|
|
95
|
+
PageBody = ClassVariants.build(
|
|
96
|
+
base: "mt-8 pb-24 space-y-12"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Content section with consistent vertical spacing and optional title.
|
|
100
|
+
#
|
|
101
|
+
# Supports horizontal and vertical orientations. Horizontal uses a
|
|
102
|
+
# 2-column grid for side-by-side content. Vertical centers text.
|
|
103
|
+
#
|
|
104
|
+
# @example
|
|
105
|
+
# PageSection.render(orientation: :vertical)
|
|
106
|
+
#
|
|
107
|
+
# Sub-parts: {PageSectionWrapper}, {PageSectionHeader},
|
|
108
|
+
# {PageSectionTitle}, {PageSectionDescription}, {PageSectionBody},
|
|
109
|
+
# {PageSectionLinks}
|
|
110
|
+
#
|
|
111
|
+
# Nuxt UI base: relative isolate
|
|
112
|
+
PageSection = ClassVariants.build(
|
|
113
|
+
base: "relative isolate text-foreground",
|
|
114
|
+
variants: {
|
|
115
|
+
orientation: {
|
|
116
|
+
horizontal: "",
|
|
117
|
+
vertical: ""
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
defaults: {orientation: :horizontal}
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Section inner container — switches to grid on desktop.
|
|
124
|
+
#
|
|
125
|
+
# Nuxt UI: flex flex-col lg:grid py-16 sm:py-24 lg:py-32 gap-8 sm:gap-16
|
|
126
|
+
PageSectionContainer = ClassVariants.build(
|
|
127
|
+
base: "flex flex-col lg:grid py-16 sm:py-24 lg:py-32 gap-8 sm:gap-16",
|
|
128
|
+
variants: {
|
|
129
|
+
orientation: {
|
|
130
|
+
horizontal: "lg:grid-cols-2 lg:items-center",
|
|
131
|
+
vertical: ""
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
defaults: {orientation: :horizontal}
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Section text/content wrapper.
|
|
138
|
+
PageSectionWrapper = ClassVariants.build(
|
|
139
|
+
base: "",
|
|
140
|
+
variants: {
|
|
141
|
+
order: {
|
|
142
|
+
first: "",
|
|
143
|
+
last: "order-last"
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
defaults: {order: :first}
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# Section header for title/description/links grouping.
|
|
150
|
+
PageSectionHeader = ClassVariants.build(
|
|
151
|
+
base: ""
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Section headline eyebrow text.
|
|
155
|
+
#
|
|
156
|
+
# Nuxt UI: mb-3 font-semibold text-primary flex items-center gap-1.5
|
|
157
|
+
PageSectionHeadline = ClassVariants.build(
|
|
158
|
+
base: "mb-3 font-semibold text-primary flex items-center gap-1.5",
|
|
159
|
+
variants: {
|
|
160
|
+
orientation: {
|
|
161
|
+
horizontal: "",
|
|
162
|
+
vertical: "justify-center"
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
defaults: {orientation: :horizontal}
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
# Section title — large bold heading.
|
|
169
|
+
#
|
|
170
|
+
# Nuxt UI: text-3xl sm:text-4xl lg:text-5xl text-pretty tracking-tight font-bold text-highlighted
|
|
171
|
+
PageSectionTitle = ClassVariants.build(
|
|
172
|
+
base: "text-3xl sm:text-4xl lg:text-5xl text-pretty tracking-tight font-bold text-foreground",
|
|
173
|
+
variants: {
|
|
174
|
+
orientation: {
|
|
175
|
+
horizontal: "",
|
|
176
|
+
vertical: "text-center"
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
defaults: {orientation: :horizontal}
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Section description text.
|
|
183
|
+
#
|
|
184
|
+
# Nuxt UI: text-base sm:text-lg text-muted
|
|
185
|
+
PageSectionDescription = ClassVariants.build(
|
|
186
|
+
base: "mt-6 text-base sm:text-lg text-muted-foreground",
|
|
187
|
+
variants: {
|
|
188
|
+
orientation: {
|
|
189
|
+
horizontal: "text-pretty",
|
|
190
|
+
vertical: "text-center text-balance"
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
defaults: {orientation: :horizontal}
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# Section body for additional content.
|
|
197
|
+
PageSectionBody = ClassVariants.build(
|
|
198
|
+
base: "mt-8"
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# Section action links container.
|
|
202
|
+
#
|
|
203
|
+
# Nuxt UI: flex flex-wrap gap-x-6 gap-y-3
|
|
204
|
+
PageSectionLinks = ClassVariants.build(
|
|
205
|
+
base: "mt-8 flex flex-wrap gap-x-6 gap-y-3",
|
|
206
|
+
variants: {
|
|
207
|
+
orientation: {
|
|
208
|
+
horizontal: "",
|
|
209
|
+
vertical: "justify-center"
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
defaults: {orientation: :horizontal}
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Responsive grid for page cards/features.
|
|
216
|
+
#
|
|
217
|
+
# Nuxt UI base: relative grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8
|
|
218
|
+
PageGrid = ClassVariants.build(
|
|
219
|
+
base: "relative grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8"
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# Content card for grid/column layouts.
|
|
223
|
+
#
|
|
224
|
+
# Supports outline, soft, subtle, and ghost variants.
|
|
225
|
+
# Ghost variant has no background or border for minimal styling.
|
|
226
|
+
#
|
|
227
|
+
# @example
|
|
228
|
+
# PageCard.render(variant: :outline)
|
|
229
|
+
#
|
|
230
|
+
# Sub-parts: {PageCardHeader}, {PageCardBody}, {PageCardFooter},
|
|
231
|
+
# {PageCardIcon}, {PageCardTitle}, {PageCardDescription}
|
|
232
|
+
#
|
|
233
|
+
# Nuxt UI base: relative flex rounded-lg
|
|
234
|
+
PageCard = ClassVariants.build(
|
|
235
|
+
base: "relative flex rounded-lg text-foreground",
|
|
236
|
+
variants: {
|
|
237
|
+
variant: {
|
|
238
|
+
outline: "bg-background ring ring-inset ring-border",
|
|
239
|
+
soft: "bg-elevated/50",
|
|
240
|
+
subtle: "bg-elevated/50 ring ring-inset ring-border",
|
|
241
|
+
ghost: ""
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
defaults: {variant: :outline}
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
# Page card inner container with padding.
|
|
248
|
+
#
|
|
249
|
+
# Nuxt UI: relative flex flex-col flex-1 lg:grid gap-x-8 gap-y-4 p-4 sm:p-6
|
|
250
|
+
PageCardContainer = ClassVariants.build(
|
|
251
|
+
base: "relative flex flex-col flex-1 gap-x-8 gap-y-4 p-4 sm:p-6"
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
# Page card content wrapper.
|
|
255
|
+
PageCardWrapper = ClassVariants.build(
|
|
256
|
+
base: "flex flex-col flex-1 items-start"
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
# Page card header area.
|
|
260
|
+
PageCardHeader = ClassVariants.build(
|
|
261
|
+
base: "mb-4"
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
# Page card body — grows to fill available space.
|
|
265
|
+
PageCardBody = ClassVariants.build(
|
|
266
|
+
base: "flex-1"
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
# Page card footer area.
|
|
270
|
+
PageCardFooter = ClassVariants.build(
|
|
271
|
+
base: "pt-4 mt-auto"
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
# Page card leading icon.
|
|
275
|
+
#
|
|
276
|
+
# Nuxt UI: size-5 shrink-0 text-primary
|
|
277
|
+
PageCardIcon = ClassVariants.build(
|
|
278
|
+
base: "inline-flex items-center mb-2.5 [&_svg]:size-5 [&_svg]:shrink-0 [&_svg]:text-primary"
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
# Page card title text.
|
|
282
|
+
#
|
|
283
|
+
# Nuxt UI: text-base text-pretty font-semibold text-highlighted
|
|
284
|
+
PageCardTitle = ClassVariants.build(
|
|
285
|
+
base: "text-base text-pretty font-semibold text-foreground"
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
# Page card description text.
|
|
289
|
+
#
|
|
290
|
+
# Nuxt UI: text-[15px] text-pretty text-muted
|
|
291
|
+
PageCardDescription = ClassVariants.build(
|
|
292
|
+
base: "mt-1 text-sm text-pretty text-muted-foreground"
|
|
293
|
+
)
|
|
294
|
+
end
|
|
295
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Placeholder element displayed while content is loading.
|
|
4
|
+
#
|
|
5
|
+
# @example
|
|
6
|
+
# Skeleton.render
|
|
7
|
+
#
|
|
8
|
+
# No variants — dimensions set by consumer via css_classes.
|
|
9
|
+
#
|
|
10
|
+
# shadcn base: animate-pulse rounded-md bg-accent
|
|
11
|
+
# Nuxt UI base: animate-pulse rounded-md bg-elevated
|
|
12
|
+
Skeleton = ClassVariants.build(
|
|
13
|
+
base: "animate-pulse rounded-md bg-elevated"
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Kiso
|
|
2
|
+
module Themes
|
|
3
|
+
# Range slider with track, filled range, and draggable thumb.
|
|
4
|
+
#
|
|
5
|
+
# @example
|
|
6
|
+
# Slider.render(size: :md)
|
|
7
|
+
#
|
|
8
|
+
# Variants:
|
|
9
|
+
# - +size+ — :sm, :md (default), :lg
|
|
10
|
+
#
|
|
11
|
+
# Sub-parts: {SliderTrack}, {SliderRange}, {SliderThumb}
|
|
12
|
+
#
|
|
13
|
+
# shadcn base: relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50
|
|
14
|
+
Slider = ClassVariants.build(
|
|
15
|
+
base: "relative flex w-full touch-none items-center select-none"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# shadcn: relative grow overflow-hidden rounded-full bg-muted h-1.5 w-full
|
|
19
|
+
SliderTrack = ClassVariants.build(
|
|
20
|
+
base: "relative grow cursor-pointer overflow-hidden rounded-full bg-muted w-full",
|
|
21
|
+
variants: {
|
|
22
|
+
size: {
|
|
23
|
+
sm: "h-1",
|
|
24
|
+
md: "h-1.5",
|
|
25
|
+
lg: "h-2"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
defaults: {size: :md}
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# shadcn: absolute h-full bg-primary
|
|
32
|
+
SliderRange = ClassVariants.build(
|
|
33
|
+
base: "absolute h-full bg-primary"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# shadcn: block size-4 shrink-0 rounded-full border border-primary bg-white shadow-sm
|
|
37
|
+
# ring-ring/50 transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4
|
|
38
|
+
# focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50
|
|
39
|
+
SliderThumb = ClassVariants.build(
|
|
40
|
+
base: "block shrink-0 rounded-full border border-primary bg-white shadow-sm " \
|
|
41
|
+
"ring-ring/50 transition-[color,box-shadow] hover:ring-4 " \
|
|
42
|
+
"focus-visible:ring-4 focus-visible:outline-hidden",
|
|
43
|
+
variants: {
|
|
44
|
+
size: {
|
|
45
|
+
sm: "size-3",
|
|
46
|
+
md: "size-4",
|
|
47
|
+
lg: "size-5"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
defaults: {size: :md}
|
|
51
|
+
)
|
|
52
|
+
end
|
|
53
|
+
end
|
data/lib/kiso/version.rb
CHANGED