nitro_kit 0.2.0 → 0.3.0
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/MIT-LICENSE +20 -0
- data/Rakefile +6 -4
- data/app/components/nitro_kit/accordion.rb +68 -32
- data/app/components/nitro_kit/alert.rb +69 -0
- data/app/components/nitro_kit/avatar.rb +52 -0
- data/app/components/nitro_kit/badge.rb +46 -19
- data/app/components/nitro_kit/button.rb +99 -66
- data/app/components/nitro_kit/button_group.rb +18 -13
- data/app/components/nitro_kit/card.rb +49 -9
- data/app/components/nitro_kit/checkbox.rb +59 -41
- data/app/components/nitro_kit/checkbox_group.rb +38 -0
- data/app/components/nitro_kit/combobox.rb +138 -0
- data/app/components/nitro_kit/component.rb +45 -14
- data/app/components/nitro_kit/datepicker.rb +9 -0
- data/app/components/nitro_kit/dialog.rb +95 -0
- data/app/components/nitro_kit/dropdown.rb +112 -70
- data/app/components/nitro_kit/field.rb +221 -56
- data/app/components/nitro_kit/field_group.rb +12 -6
- data/app/components/nitro_kit/fieldset.rb +42 -7
- data/app/components/nitro_kit/form_builder.rb +45 -22
- data/app/components/nitro_kit/icon.rb +29 -8
- data/app/components/nitro_kit/input.rb +20 -10
- data/app/components/nitro_kit/label.rb +18 -5
- data/app/components/nitro_kit/pagination.rb +98 -0
- data/app/components/nitro_kit/radio_button.rb +28 -27
- data/app/components/nitro_kit/radio_button_group.rb +53 -0
- data/app/components/nitro_kit/select.rb +72 -0
- data/app/components/nitro_kit/switch.rb +49 -39
- data/app/components/nitro_kit/table.rb +56 -0
- data/app/components/nitro_kit/tabs.rb +98 -0
- data/app/components/nitro_kit/textarea.rb +26 -0
- data/app/components/nitro_kit/toast.rb +104 -0
- data/app/components/nitro_kit/tooltip.rb +53 -0
- data/app/helpers/nitro_kit/accordion_helper.rb +2 -0
- data/app/helpers/nitro_kit/alert_helper.rb +11 -0
- data/app/helpers/nitro_kit/avatar_helper.rb +9 -0
- data/app/helpers/nitro_kit/badge_helper.rb +3 -5
- data/app/helpers/nitro_kit/button_group_helper.rb +2 -0
- data/app/helpers/nitro_kit/button_helper.rb +37 -28
- data/app/helpers/nitro_kit/card_helper.rb +2 -0
- data/app/helpers/nitro_kit/checkbox_helper.rb +19 -16
- data/app/helpers/nitro_kit/combobox_helper.rb +9 -0
- data/app/helpers/nitro_kit/datepicker_helper.rb +9 -0
- data/app/helpers/nitro_kit/dialog_helper.rb +9 -0
- data/app/helpers/nitro_kit/dropdown_helper.rb +3 -1
- data/app/helpers/nitro_kit/field_group_helper.rb +9 -0
- data/app/helpers/nitro_kit/field_helper.rb +4 -2
- data/app/helpers/nitro_kit/fieldset_helper.rb +9 -0
- data/app/helpers/nitro_kit/form_helper.rb +13 -0
- data/app/helpers/nitro_kit/icon_helper.rb +3 -1
- data/app/helpers/nitro_kit/input_helper.rb +35 -0
- data/app/helpers/nitro_kit/label_helper.rb +12 -9
- data/app/helpers/nitro_kit/pagination_helper.rb +42 -0
- data/app/helpers/nitro_kit/radio_button_helper.rb +15 -12
- data/app/helpers/nitro_kit/select_helper.rb +24 -0
- data/app/helpers/nitro_kit/switch_helper.rb +4 -10
- data/app/helpers/nitro_kit/table_helper.rb +9 -0
- data/app/helpers/nitro_kit/tabs_helper.rb +9 -0
- data/app/helpers/nitro_kit/textarea_helper.rb +9 -0
- data/app/helpers/nitro_kit/toast_helper.rb +36 -0
- data/app/helpers/nitro_kit/tooltip_helper.rb +9 -0
- data/lib/generators/nitro_kit/add_generator.rb +38 -41
- data/lib/generators/nitro_kit/install_generator.rb +2 -1
- data/lib/nitro_kit/engine.rb +4 -0
- data/lib/nitro_kit/schema_builder.rb +90 -16
- data/lib/nitro_kit/version.rb +1 -1
- data/lib/nitro_kit.rb +39 -1
- data/lib/tasks/nitro_kit_tasks.rake +4 -0
- metadata +37 -10
- data/app/components/nitro_kit/radio_group.rb +0 -35
- data/app/helpers/application_helper.rb +0 -109
- data/lib/nitro_kit/railtie.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d58e573f0c99860c6ede6591c772db3d2399c754a1cb2c25b65632c42ca8a00
|
4
|
+
data.tar.gz: 4796fae213b057ed86d3bcc693c504c7323abe020bcfa920713ea7d9a2e4438a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2865c2a1a86d6cf786eff5a699ce98aabea646c44349ecb387369ee7ba3aaab1b928f28ea1fded788bc95ffeb06926aac017a4fe292e70bbc0e1ecfa7d0dc30f
|
7
|
+
data.tar.gz: 2f8f3fc20b0be34cc8fc07f01fba9ace962dad39926332a50bf65bec062b7d96398bdc790b708fb6c027f2193b542641c5127fd6920f417d359a448a82bff782
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright Mikkel Malmberg
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
1
|
+
require "bundler/setup"
|
3
2
|
|
4
|
-
|
3
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
4
|
+
load "rails/tasks/engine.rake"
|
5
5
|
|
6
|
-
|
6
|
+
load "rails/tasks/statistics.rake"
|
7
|
+
|
8
|
+
require "bundler/gem_tasks"
|
@@ -1,27 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module NitroKit
|
2
4
|
class Accordion < Component
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
].freeze
|
11
|
-
|
12
|
-
CONTENT = [
|
13
|
-
"overflow-hidden transition-all duration-200",
|
14
|
-
"[&[aria-hidden='true']]:h-0 [&[aria-hidden='false']]:h-auto"
|
15
|
-
].freeze
|
16
|
-
|
17
|
-
ARROW = "transition-transform duration-200 text-muted-foreground group-hover/accordion-trigger:text-primary"
|
5
|
+
def initialize(**attrs)
|
6
|
+
super(
|
7
|
+
attrs,
|
8
|
+
class: item_class,
|
9
|
+
data: {controller: "nk--accordion"}
|
10
|
+
)
|
11
|
+
end
|
18
12
|
|
19
13
|
def view_template
|
20
|
-
div(
|
21
|
-
**attrs,
|
22
|
-
class: merge(ITEM, attrs[:class]),
|
23
|
-
data: {controller: "nk--accordion"}
|
24
|
-
) do
|
14
|
+
div(**attrs) do
|
25
15
|
yield
|
26
16
|
end
|
27
17
|
end
|
@@ -34,27 +24,73 @@ module NitroKit
|
|
34
24
|
|
35
25
|
def trigger(text = nil, **attrs)
|
36
26
|
button(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
:
|
41
|
-
:
|
42
|
-
|
43
|
-
|
27
|
+
**mattr(
|
28
|
+
attrs,
|
29
|
+
type: "button",
|
30
|
+
class: trigger_class,
|
31
|
+
data: {
|
32
|
+
action: "nk--accordion#toggle",
|
33
|
+
nk__accordion_target: "trigger"
|
34
|
+
},
|
35
|
+
aria: {expanded: "false"}
|
36
|
+
)
|
44
37
|
) do
|
45
|
-
|
46
|
-
|
38
|
+
block_given? ? yield : plain(text)
|
39
|
+
chevron_icon
|
47
40
|
end
|
48
41
|
end
|
49
42
|
|
50
43
|
def content(**attrs)
|
51
44
|
div(
|
52
|
-
|
53
|
-
|
54
|
-
|
45
|
+
**mattr(
|
46
|
+
attrs,
|
47
|
+
class: content_class,
|
48
|
+
data: {
|
49
|
+
nk__accordion_target: "content"
|
50
|
+
},
|
51
|
+
aria: {hidden: "true"}
|
52
|
+
)
|
55
53
|
) do
|
56
54
|
div(class: "pb-4") { yield }
|
57
55
|
end
|
58
56
|
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def item_class
|
61
|
+
"divide-y"
|
62
|
+
end
|
63
|
+
|
64
|
+
def trigger_class
|
65
|
+
[
|
66
|
+
"flex w-full items-center justify-between py-4 font-medium cursor-pointer",
|
67
|
+
"group/accordion-trigger hover:underline transition-colors",
|
68
|
+
"[&[aria-expanded='true']>svg]:rotate-180",
|
69
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
70
|
+
]
|
71
|
+
end
|
72
|
+
|
73
|
+
def content_class
|
74
|
+
[
|
75
|
+
"overflow-hidden transition-all duration-200",
|
76
|
+
"[&[aria-hidden='true']]:h-0 [&[aria-hidden='false']]:h-auto"
|
77
|
+
]
|
78
|
+
end
|
79
|
+
|
80
|
+
def arrow_class
|
81
|
+
"transition-transform duration-200 text-muted-foreground group-hover/accordion-trigger:text-primary"
|
82
|
+
end
|
83
|
+
|
84
|
+
def chevron_icon
|
85
|
+
svg(
|
86
|
+
class: "transition-transform duration-200 size-4 self-center place-self-end mr-2 pointer-events-none text-muted-foreground group-hover/accordion-trigger:text-primary",
|
87
|
+
viewbox: "0 0 24 24",
|
88
|
+
fill: "none",
|
89
|
+
stroke: "currentColor",
|
90
|
+
stroke_width: 1
|
91
|
+
) do |svg|
|
92
|
+
svg.path(d: "m6 9 6 6 6-6")
|
93
|
+
end
|
94
|
+
end
|
59
95
|
end
|
60
96
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NitroKit
|
4
|
+
class Alert < Component
|
5
|
+
VARIANTS = %i[default warning error success]
|
6
|
+
|
7
|
+
def initialize(variant: :default, **attrs)
|
8
|
+
@variant = variant
|
9
|
+
|
10
|
+
super(
|
11
|
+
attrs,
|
12
|
+
role: "alert",
|
13
|
+
class: [base_class, variant_class]
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :variant
|
18
|
+
|
19
|
+
def view_template
|
20
|
+
div(**attrs) do
|
21
|
+
yield
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def title(text = nil, **attrs, &block)
|
26
|
+
h5(**mattr(attrs, class: title_class)) do
|
27
|
+
text_or_block(text, &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def description(text = nil, **attrs, &block)
|
32
|
+
div(**mattr(attrs, class: description_class)) do
|
33
|
+
text_or_block(text, &block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def base_class
|
40
|
+
[
|
41
|
+
"relative border w-full rounded-md p-5 text-sm space-y-2",
|
42
|
+
"[&>svg~*]:pl-8 [&>svg]:absolute [&>svg]:top-5 [&>svg]:left-5"
|
43
|
+
]
|
44
|
+
end
|
45
|
+
|
46
|
+
def variant_class
|
47
|
+
case variant
|
48
|
+
when :default
|
49
|
+
"border-border bg-background text-foreground"
|
50
|
+
when :warning
|
51
|
+
"bg-yellow-300/20 dark:bg-yellow-300/20 text-yellow-900 dark:text-yellow-100 border-yellow-500/80 dark:border-yellow-400/50"
|
52
|
+
when :success
|
53
|
+
"bg-green-300/20 dark:bg-green-300/20 text-green-900 dark:text-green-100 border-green-500/80 dark:border-green-400/50"
|
54
|
+
when :error
|
55
|
+
"bg-red-300/20 dark:bg-red-300/20 text-red-900 dark:text-red-100 border-red-400/80 dark:border-red-400/50"
|
56
|
+
else
|
57
|
+
raise ArgumentError, "Invalid variant: #{variant}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def title_class
|
62
|
+
"font-medium text-lg leading-5"
|
63
|
+
end
|
64
|
+
|
65
|
+
def description_class
|
66
|
+
""
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NitroKit
|
4
|
+
class Avatar < Component
|
5
|
+
include ActionView::Helpers::AssetUrlHelper
|
6
|
+
|
7
|
+
def initialize(src_arg = nil, src: nil, size: :md, **attrs)
|
8
|
+
@src = src_arg || src
|
9
|
+
@size = size
|
10
|
+
|
11
|
+
super(
|
12
|
+
attrs,
|
13
|
+
class: [container_class, size_classes]
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :src, :size
|
18
|
+
|
19
|
+
def view_template(&block)
|
20
|
+
div(**attrs) do
|
21
|
+
image
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def image
|
26
|
+
helpers.image_tag(src, class: image_class)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def size_classes
|
32
|
+
case size
|
33
|
+
when :sm
|
34
|
+
"size-8"
|
35
|
+
when :md
|
36
|
+
"size-12"
|
37
|
+
when :lg
|
38
|
+
"size-16"
|
39
|
+
else
|
40
|
+
raise ArgumentError, "Invalid size: #{size}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def container_class
|
45
|
+
"inline-flex overflow-hidden rounded-full"
|
46
|
+
end
|
47
|
+
|
48
|
+
def image_class
|
49
|
+
"block size-full bg-muted"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,31 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module NitroKit
|
2
4
|
class Badge < Component
|
3
|
-
|
5
|
+
VARIANTS = %i[default outline]
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def initialize(text = nil, variant: :default, size: :md, **attrs)
|
8
|
+
@text = text
|
9
|
+
@variant = variant
|
10
|
+
@size = size
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
super(
|
13
|
+
attrs,
|
14
|
+
class: [
|
15
|
+
base_class,
|
16
|
+
variant_class,
|
17
|
+
size_class
|
18
|
+
]
|
19
|
+
)
|
20
|
+
end
|
14
21
|
|
15
|
-
|
16
|
-
super(**attrs)
|
22
|
+
attr_reader :text, :variant, :size
|
17
23
|
|
18
|
-
|
19
|
-
|
24
|
+
def view_template(&block)
|
25
|
+
span(**attrs) do
|
26
|
+
text_or_block(text, &block)
|
27
|
+
end
|
20
28
|
end
|
21
29
|
|
22
|
-
|
30
|
+
private
|
31
|
+
|
32
|
+
def base_class
|
33
|
+
"inline-flex items-center gap-x-1.5 rounded-md font-medium"
|
34
|
+
end
|
35
|
+
|
36
|
+
def variant_class
|
37
|
+
case variant
|
38
|
+
when :default
|
39
|
+
"bg-zinc-200 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300"
|
40
|
+
when :outline
|
41
|
+
"border"
|
42
|
+
else
|
43
|
+
raise ArgumentError, "Invalid variant: #{variant}"
|
44
|
+
end
|
45
|
+
end
|
23
46
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
47
|
+
def size_class
|
48
|
+
case size
|
49
|
+
when :sm
|
50
|
+
"text-xs px-1.5 py-0.5"
|
51
|
+
when :md
|
52
|
+
"text-sm px-2 py-0.5"
|
53
|
+
else
|
54
|
+
raise ArgumentError, "Invalid size: #{size}"
|
55
|
+
end
|
29
56
|
end
|
30
57
|
end
|
31
58
|
end
|
@@ -1,88 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module NitroKit
|
2
4
|
class Button < Component
|
3
|
-
|
4
|
-
"inline-flex items-center cursor-pointer shrink-0 justify-center rounded-md border gap-2 font-medium",
|
5
|
-
# Disabled
|
6
|
-
"disabled:opacity-70 disabled:pointer-events-none",
|
7
|
-
# Focus
|
8
|
-
"focus:outline-none focus:ring-[3px] focus:ring-offset-2 focus:ring-ring ring-offset-background",
|
9
|
-
# Icon
|
10
|
-
"[&_svg]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
11
|
-
# If icon only, make square
|
12
|
-
"[&_svg:first-child:last-child]:-mx-2"
|
13
|
-
].freeze
|
14
|
-
|
15
|
-
VARIANTS = {
|
16
|
-
default: [
|
17
|
-
"bg-background text-foreground",
|
18
|
-
"hover:bg-zinc-50 dark:hover:bg-zinc-900"
|
19
|
-
],
|
20
|
-
primary: [
|
21
|
-
"bg-primary text-white dark:text-zinc-950 border-primary",
|
22
|
-
"hover:bg-primary/90 dark:hover:bg-primary/90"
|
23
|
-
],
|
24
|
-
destructive: [
|
25
|
-
"bg-destructive text-white border-destructive",
|
26
|
-
"hover:bg-destructive/90 dark:hover:bg-destructive/90",
|
27
|
-
"disabled:text-white/80"
|
28
|
-
],
|
29
|
-
ghost: [
|
30
|
-
"bg-transparent text-foreground border-transparent",
|
31
|
-
"hover:bg-zinc-100 dark:hover:bg-zinc-900",
|
32
|
-
"disabled:text-muted-foreground"
|
33
|
-
]
|
34
|
-
}.freeze
|
35
|
-
|
36
|
-
SIZES = {
|
37
|
-
base: "px-4 h-9",
|
38
|
-
sm: "px-2.5 h-7 text-sm",
|
39
|
-
xs: "px-1.5 h-6 text-xs"
|
40
|
-
}.freeze
|
5
|
+
VARIANTS = %i[default primary destructive ghost]
|
41
6
|
|
42
7
|
def initialize(
|
8
|
+
text = nil,
|
43
9
|
href: nil,
|
10
|
+
variant: :default,
|
11
|
+
size: :md,
|
44
12
|
icon: nil,
|
45
13
|
icon_right: nil,
|
46
|
-
size: :base,
|
47
|
-
type: :button,
|
48
|
-
variant: :default,
|
49
14
|
**attrs
|
50
15
|
)
|
51
|
-
|
52
|
-
|
16
|
+
@text = text
|
53
17
|
@href = href
|
54
18
|
@icon = icon
|
55
19
|
@icon_right = icon_right
|
56
20
|
@size = size
|
57
|
-
@type = type
|
58
21
|
@variant = variant
|
22
|
+
|
23
|
+
super(
|
24
|
+
attrs,
|
25
|
+
class: [
|
26
|
+
base_class,
|
27
|
+
variant_class,
|
28
|
+
size_class
|
29
|
+
]
|
30
|
+
)
|
59
31
|
end
|
60
32
|
|
61
33
|
attr_reader(
|
34
|
+
:text,
|
62
35
|
:href,
|
63
36
|
:icon,
|
64
37
|
:icon_right,
|
65
38
|
:size,
|
66
|
-
:type,
|
67
39
|
:variant
|
68
40
|
)
|
69
41
|
|
70
42
|
def view_template(&block)
|
71
|
-
class_list = merge(
|
72
|
-
[
|
73
|
-
BASE,
|
74
|
-
VARIANTS[variant],
|
75
|
-
SIZES[size],
|
76
|
-
attrs[:class]
|
77
|
-
]
|
78
|
-
)
|
79
|
-
|
80
43
|
if href
|
81
|
-
a(href:, **attrs
|
44
|
+
a(href:, **attrs) do
|
82
45
|
contents(&block)
|
83
46
|
end
|
84
47
|
else
|
85
|
-
button(type
|
48
|
+
button(type: :button, **attrs) do
|
86
49
|
contents(&block)
|
87
50
|
end
|
88
51
|
end
|
@@ -90,19 +53,89 @@ module NitroKit
|
|
90
53
|
|
91
54
|
private
|
92
55
|
|
93
|
-
def contents
|
94
|
-
|
95
|
-
has_text = text.to_s.present?
|
56
|
+
def contents(&block)
|
57
|
+
has_content = text.present? || block_given?
|
96
58
|
|
97
|
-
if !
|
98
|
-
return
|
99
|
-
elsif icon && !has_text && !icon_right
|
100
|
-
return render(Icon.new(name: icon))
|
59
|
+
if !has_content
|
60
|
+
return render(Icon.new(icon))
|
101
61
|
end
|
102
62
|
|
103
|
-
render(Icon.new(
|
104
|
-
|
105
|
-
|
63
|
+
render(Icon.new(icon)) if icon
|
64
|
+
|
65
|
+
if block_given?
|
66
|
+
yield
|
67
|
+
else
|
68
|
+
span { plain(text) }
|
69
|
+
end
|
70
|
+
|
71
|
+
render(Icon.new(icon_right)) if icon_right
|
72
|
+
end
|
73
|
+
|
74
|
+
def base_class
|
75
|
+
[
|
76
|
+
"inline-flex items-center cursor-pointer shrink-0 justify-center rounded-md border gap-2 font-medium select-none",
|
77
|
+
# Disabled
|
78
|
+
"disabled:opacity-70 disabled:pointer-events-none",
|
79
|
+
# Focus
|
80
|
+
"focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-offset-2 focus-visible:ring-ring ring-offset-background",
|
81
|
+
# Icon
|
82
|
+
"[&_svg]:pointer-events-none [&_svg]:shrink-0"
|
83
|
+
]
|
84
|
+
end
|
85
|
+
|
86
|
+
def variant_class
|
87
|
+
case variant
|
88
|
+
when :default
|
89
|
+
[
|
90
|
+
"bg-background text-foreground border-border",
|
91
|
+
"hover:bg-zinc-50 dark:hover:bg-zinc-900"
|
92
|
+
]
|
93
|
+
when :primary
|
94
|
+
[
|
95
|
+
"bg-primary text-white dark:text-zinc-950 border-primary",
|
96
|
+
"hover:bg-primary/90 dark:hover:bg-primary/90"
|
97
|
+
]
|
98
|
+
when :destructive
|
99
|
+
[
|
100
|
+
"bg-destructive text-white border-destructive",
|
101
|
+
"hover:bg-destructive/90 dark:hover:bg-destructive/90",
|
102
|
+
"disabled:text-white/80"
|
103
|
+
]
|
104
|
+
when :ghost
|
105
|
+
[
|
106
|
+
"bg-transparent text-foreground border-transparent",
|
107
|
+
"hover:bg-zinc-200/50 dark:hover:bg-zinc-900",
|
108
|
+
"disabled:text-muted-foreground"
|
109
|
+
]
|
110
|
+
else
|
111
|
+
raise ArgumentError, "Unknown variant `#{variant}'"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def size_class
|
116
|
+
case size
|
117
|
+
when :xs
|
118
|
+
"px-1.5 h-6 text-xs [&_svg]:size-3"
|
119
|
+
when :sm
|
120
|
+
[
|
121
|
+
"px-2.5 h-7 text-sm [&_svg]:size-3",
|
122
|
+
"[&_svg:first-child:last-child]:-mx-1"
|
123
|
+
]
|
124
|
+
when :md
|
125
|
+
[
|
126
|
+
"px-4 h-10 text-base [&_svg]:size-4",
|
127
|
+
# If icon only, make square
|
128
|
+
"[&_svg:first-child:last-child]:-mx-2"
|
129
|
+
]
|
130
|
+
when :lg
|
131
|
+
[
|
132
|
+
"px-5 h-11 text-lg [&_svg]:size-5",
|
133
|
+
# If icon only, make square
|
134
|
+
"[&_svg:first-child:last-child]:-mx-2"
|
135
|
+
]
|
136
|
+
else
|
137
|
+
raise ArgumentError, "Unknown size `#{size}'"
|
138
|
+
end
|
106
139
|
end
|
107
140
|
end
|
108
141
|
end
|
@@ -1,19 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module NitroKit
|
2
4
|
class ButtonGroup < Component
|
3
|
-
def
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
]
|
14
|
-
),
|
15
|
-
&block
|
5
|
+
def initialize(**attrs)
|
6
|
+
super(
|
7
|
+
attrs,
|
8
|
+
class: [
|
9
|
+
"flex -space-x-px isolate",
|
10
|
+
# Remove rounded corners from middle buttons
|
11
|
+
"[&>*:not(:first-child):not(:last-child)]:rounded-none [&>*:first-child:not(:last-child)]:rounded-r-none [&>*:last-child:not(:first-child)]:rounded-l-none",
|
12
|
+
# Put focused button on top
|
13
|
+
"[&>*]:focus:z-10"
|
14
|
+
]
|
16
15
|
)
|
17
16
|
end
|
17
|
+
|
18
|
+
def view_template
|
19
|
+
div(**attrs) do
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
end
|
18
23
|
end
|
19
24
|
end
|
@@ -1,23 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module NitroKit
|
2
4
|
class Card < Component
|
3
5
|
def initialize(**attrs)
|
4
|
-
|
6
|
+
super(
|
7
|
+
attrs,
|
8
|
+
class: base_class
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
def view_template
|
13
|
+
div(**attrs) do
|
14
|
+
yield
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def title(text = nil, **attrs, &block)
|
19
|
+
h2(**mattr(attrs, class: "text-lg font-bold -mb-2")) do
|
20
|
+
text_or_block(text, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def body(text = nil, **attrs, &block)
|
25
|
+
div(**mattr(attrs, class: "text-muted-foreground text-sm leading-relaxed")) do
|
26
|
+
text_or_block(text, &block)
|
27
|
+
end
|
5
28
|
end
|
6
29
|
|
7
|
-
def
|
8
|
-
div(class: "
|
30
|
+
def footer(text = nil, **attrs, &block)
|
31
|
+
div(**mattr(attrs, class: "flex gap-2 items-center")) do
|
32
|
+
text_or_block(text, &block)
|
33
|
+
end
|
9
34
|
end
|
10
35
|
|
11
|
-
def
|
12
|
-
|
36
|
+
def divider(**attrs)
|
37
|
+
full_width do
|
38
|
+
hr(**attrs)
|
39
|
+
end
|
13
40
|
end
|
14
41
|
|
15
|
-
def
|
16
|
-
div(**attrs
|
42
|
+
def full_width(**attrs)
|
43
|
+
div(**mattr(attrs, data: {slot: "full"}, class: "-mx-(--gap)")) do
|
44
|
+
yield
|
45
|
+
end
|
17
46
|
end
|
18
47
|
|
19
|
-
|
20
|
-
|
48
|
+
private
|
49
|
+
|
50
|
+
def base_class
|
51
|
+
[
|
52
|
+
# Configure spacing with breakpoints
|
53
|
+
"[--gap:calc(var(--spacing)*4)] sm:[--gap:calc(var(--spacing)*6)]",
|
54
|
+
# Base styles
|
55
|
+
"flex flex-col items-stretch rounded-lg bg-background border p-(--gap) gap-(--gap) overflow-hidden",
|
56
|
+
# If a `data-slot=full` is the first thing, move it to the top
|
57
|
+
"[&>[data-slot=full]:first-child]:-mt-(--gap)",
|
58
|
+
# Group for hover, focus
|
59
|
+
"group/card"
|
60
|
+
]
|
21
61
|
end
|
22
62
|
end
|
23
63
|
end
|