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.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -1
  3. data/README.md +16 -3
  4. data/app/assets/tailwind/kiso/dialog.css +46 -0
  5. data/app/assets/tailwind/kiso/engine.css +6 -3
  6. data/app/assets/tailwind/kiso/input-otp.css +17 -0
  7. data/app/assets/tailwind/kiso/palettes/blue.css +65 -0
  8. data/app/assets/tailwind/kiso/palettes/green.css +65 -0
  9. data/app/assets/tailwind/kiso/palettes/orange.css +65 -0
  10. data/app/assets/tailwind/kiso/palettes/violet.css +65 -0
  11. data/app/assets/tailwind/kiso/palettes/zinc.css +65 -0
  12. data/app/assets/tailwind/kiso/slider.css +27 -0
  13. data/app/helpers/kiso/app_component_helper.rb +53 -0
  14. data/app/helpers/kiso/component_helper.rb +110 -24
  15. data/app/helpers/kiso/ui_context_helper.rb +59 -0
  16. data/app/javascript/controllers/kiso/alert_controller.js +33 -0
  17. data/app/javascript/controllers/kiso/dialog_controller.js +140 -0
  18. data/app/javascript/controllers/kiso/index.js +6 -0
  19. data/app/javascript/controllers/kiso/slider_controller.js +276 -0
  20. data/app/views/kiso/components/_alert.html.erb +19 -3
  21. data/app/views/kiso/components/_alert_dialog.html.erb +28 -0
  22. data/app/views/kiso/components/_app.html.erb +7 -0
  23. data/app/views/kiso/components/_aspect_ratio.html.erb +8 -0
  24. data/app/views/kiso/components/_avatar.html.erb +3 -3
  25. data/app/views/kiso/components/_breadcrumb.html.erb +1 -1
  26. data/app/views/kiso/components/_button.html.erb +31 -17
  27. data/app/views/kiso/components/_color_mode_button.html.erb +1 -1
  28. data/app/views/kiso/components/_color_mode_select.html.erb +4 -4
  29. data/app/views/kiso/components/_container.html.erb +7 -0
  30. data/app/views/kiso/components/_dashboard_sidebar.html.erb +1 -1
  31. data/app/views/kiso/components/_dialog.html.erb +11 -0
  32. data/app/views/kiso/components/_footer.html.erb +7 -0
  33. data/app/views/kiso/components/_header.html.erb +7 -0
  34. data/app/views/kiso/components/_main.html.erb +7 -0
  35. data/app/views/kiso/components/_page.html.erb +7 -0
  36. data/app/views/kiso/components/_page_body.html.erb +7 -0
  37. data/app/views/kiso/components/_page_card.html.erb +40 -0
  38. data/app/views/kiso/components/_page_grid.html.erb +7 -0
  39. data/app/views/kiso/components/_page_header.html.erb +38 -0
  40. data/app/views/kiso/components/_page_section.html.erb +11 -0
  41. data/app/views/kiso/components/_pagination.html.erb +1 -1
  42. data/app/views/kiso/components/_select_native.html.erb +3 -3
  43. data/app/views/kiso/components/_skeleton.html.erb +5 -0
  44. data/app/views/kiso/components/_slider.html.erb +42 -0
  45. data/app/views/kiso/components/_switch.html.erb +2 -2
  46. data/app/views/kiso/components/alert/_actions.html.erb +7 -0
  47. data/app/views/kiso/components/alert_dialog/_action.html.erb +8 -0
  48. data/app/views/kiso/components/alert_dialog/_cancel.html.erb +8 -0
  49. data/app/views/kiso/components/alert_dialog/_description.html.erb +8 -0
  50. data/app/views/kiso/components/alert_dialog/_footer.html.erb +7 -0
  51. data/app/views/kiso/components/alert_dialog/_header.html.erb +7 -0
  52. data/app/views/kiso/components/alert_dialog/_media.html.erb +7 -0
  53. data/app/views/kiso/components/alert_dialog/_title.html.erb +8 -0
  54. data/app/views/kiso/components/breadcrumb/_ellipsis.html.erb +1 -1
  55. data/app/views/kiso/components/combobox/_input.html.erb +1 -1
  56. data/app/views/kiso/components/combobox/_item.html.erb +2 -2
  57. data/app/views/kiso/components/combobox/_list.html.erb +2 -1
  58. data/app/views/kiso/components/command/_group.html.erb +2 -2
  59. data/app/views/kiso/components/command/_input.html.erb +3 -2
  60. data/app/views/kiso/components/command/_list.html.erb +2 -1
  61. data/app/views/kiso/components/dashboard_navbar/_toggle.html.erb +1 -1
  62. data/app/views/kiso/components/dashboard_sidebar/_collapse.html.erb +1 -1
  63. data/app/views/kiso/components/dashboard_sidebar/_toggle.html.erb +1 -1
  64. data/app/views/kiso/components/dialog/_body.html.erb +7 -0
  65. data/app/views/kiso/components/dialog/_close.html.erb +10 -0
  66. data/app/views/kiso/components/dialog/_description.html.erb +7 -0
  67. data/app/views/kiso/components/dialog/_footer.html.erb +7 -0
  68. data/app/views/kiso/components/dialog/_header.html.erb +7 -0
  69. data/app/views/kiso/components/dialog/_title.html.erb +7 -0
  70. data/app/views/kiso/components/empty/_actions.html.erb +7 -0
  71. data/app/views/kiso/components/nav/_item.html.erb +2 -2
  72. data/app/views/kiso/components/nav/_section.html.erb +5 -5
  73. data/app/views/kiso/components/page/_center.html.erb +7 -0
  74. data/app/views/kiso/components/page/_left.html.erb +7 -0
  75. data/app/views/kiso/components/page/_right.html.erb +7 -0
  76. data/app/views/kiso/components/page_card/_body.html.erb +7 -0
  77. data/app/views/kiso/components/page_card/_description.html.erb +7 -0
  78. data/app/views/kiso/components/page_card/_footer.html.erb +7 -0
  79. data/app/views/kiso/components/page_card/_header.html.erb +7 -0
  80. data/app/views/kiso/components/page_card/_icon.html.erb +7 -0
  81. data/app/views/kiso/components/page_card/_title.html.erb +7 -0
  82. data/app/views/kiso/components/page_header/_description.html.erb +7 -0
  83. data/app/views/kiso/components/page_header/_headline.html.erb +7 -0
  84. data/app/views/kiso/components/page_header/_links.html.erb +7 -0
  85. data/app/views/kiso/components/page_header/_title.html.erb +7 -0
  86. data/app/views/kiso/components/page_section/_body.html.erb +7 -0
  87. data/app/views/kiso/components/page_section/_description.html.erb +7 -0
  88. data/app/views/kiso/components/page_section/_header.html.erb +7 -0
  89. data/app/views/kiso/components/page_section/_headline.html.erb +7 -0
  90. data/app/views/kiso/components/page_section/_links.html.erb +7 -0
  91. data/app/views/kiso/components/page_section/_title.html.erb +7 -0
  92. data/app/views/kiso/components/page_section/_wrapper.html.erb +7 -0
  93. data/app/views/kiso/components/pagination/_ellipsis.html.erb +1 -1
  94. data/app/views/kiso/components/pagination/_next.html.erb +2 -2
  95. data/app/views/kiso/components/pagination/_previous.html.erb +2 -2
  96. data/app/views/kiso/components/select/_item.html.erb +2 -2
  97. data/config/locales/en.yml +33 -0
  98. data/lib/generators/kiso/component/USAGE +35 -0
  99. data/lib/generators/kiso/component/component_generator.rb +104 -0
  100. data/lib/generators/kiso/component/templates/partial.html.erb.tt +7 -0
  101. data/lib/generators/kiso/component/templates/sub_part_partial.html.erb.tt +7 -0
  102. data/lib/generators/kiso/component/templates/sub_part_theme.rb.tt +21 -0
  103. data/lib/generators/kiso/component/templates/theme.rb.tt +21 -0
  104. data/lib/kiso/configuration.rb +40 -0
  105. data/lib/kiso/engine.rb +105 -1
  106. data/lib/kiso/presets/rounded.rb +136 -0
  107. data/lib/kiso/presets/sharp.rb +178 -0
  108. data/lib/kiso/presets.rb +49 -0
  109. data/lib/kiso/theme_overrides.rb +5 -1
  110. data/lib/kiso/themes/alert.rb +24 -11
  111. data/lib/kiso/themes/alert_dialog.rb +78 -0
  112. data/lib/kiso/themes/aspect_ratio.rb +16 -0
  113. data/lib/kiso/themes/dashboard.rb +3 -3
  114. data/lib/kiso/themes/dialog.rb +57 -0
  115. data/lib/kiso/themes/empty.rb +6 -1
  116. data/lib/kiso/themes/input_otp.rb +2 -2
  117. data/lib/kiso/themes/layout.rb +69 -0
  118. data/lib/kiso/themes/page.rb +295 -0
  119. data/lib/kiso/themes/skeleton.rb +16 -0
  120. data/lib/kiso/themes/slider.rb +53 -0
  121. data/lib/kiso/version.rb +1 -1
  122. data/lib/kiso.rb +11 -0
  123. 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-[--z-topbar]"
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 items-center gap-1.5 px-4"
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 items-center gap-1.5 px-4 py-2"
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
@@ -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-y border-r shadow-xs transition-all outline-none " \
25
- "first:rounded-l-md first:border-l last:rounded-r-md " \
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
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Kiso
4
4
  # @return [String] the current gem version
5
- VERSION = "0.2.2.pre"
5
+ VERSION = "0.4.0.pre"
6
6
  end