flowbite-components 0.1.4 → 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/CHANGELOG.md +28 -4
- data/README.md +23 -4
- data/app/components/flowbite/badge/badge.html.erb +4 -0
- data/app/components/flowbite/badge/dot.rb +45 -0
- data/app/components/flowbite/badge/pill.rb +40 -0
- data/app/components/flowbite/badge.rb +116 -0
- data/app/components/flowbite/breadcrumb/home_icon.rb +28 -0
- data/app/components/flowbite/breadcrumb/item/current.rb +35 -0
- data/app/components/flowbite/breadcrumb/item/first.rb +37 -0
- data/app/components/flowbite/breadcrumb/item.rb +50 -0
- data/app/components/flowbite/breadcrumb/separator_icon.rb +34 -0
- data/app/components/flowbite/breadcrumb.rb +54 -0
- data/app/components/flowbite/button.rb +6 -5
- data/app/components/flowbite/card.rb +15 -1
- data/app/components/flowbite/input/checkbox.rb +2 -2
- data/app/components/flowbite/input/date.rb +2 -2
- data/app/components/flowbite/input/date_time.rb +11 -0
- data/app/components/flowbite/input/email.rb +2 -2
- data/app/components/flowbite/input/file.rb +2 -2
- data/app/components/flowbite/input/hint.rb +6 -1
- data/app/components/flowbite/input/label.rb +1 -1
- data/app/components/flowbite/input/number.rb +2 -2
- data/app/components/flowbite/input/password.rb +2 -2
- data/app/components/flowbite/input/phone.rb +2 -2
- data/app/components/flowbite/input/radio_button.rb +2 -2
- data/app/components/flowbite/input/select.rb +2 -2
- data/app/components/flowbite/input/textarea.rb +2 -2
- data/app/components/flowbite/input/url.rb +2 -2
- data/app/components/flowbite/input/validation_error.rb +1 -1
- data/app/components/flowbite/input.rb +155 -0
- data/app/components/flowbite/input_field/checkbox.rb +7 -7
- data/app/components/flowbite/input_field/date_time.rb +13 -0
- data/app/components/flowbite/input_field/input_field.html.erb +2 -2
- data/app/components/flowbite/input_field/radio_button.rb +9 -15
- data/app/components/flowbite/input_field/select.rb +1 -1
- data/app/components/flowbite/input_field.rb +120 -69
- data/app/components/flowbite/link.rb +2 -0
- data/app/components/flowbite/sidebar/item.rb +68 -0
- data/app/components/flowbite/sidebar/navigation.rb +62 -0
- data/app/components/flowbite/sidebar.rb +62 -0
- data/app/components/flowbite/toast/icon.html.erb +5 -0
- data/app/components/flowbite/toast/icon.rb +57 -0
- data/app/components/flowbite/toast/toast.html.erb +40 -0
- data/app/components/flowbite/toast.rb +37 -0
- data/lib/flowbite/components/version.rb +1 -1
- data/lib/yard/flowbite_viewcomponent.rb +24 -0
- metadata +40 -5
- data/app/components/flowbite/input/field.rb +0 -126
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Flowbite
|
|
4
|
-
# A form element for
|
|
5
|
-
# messages, helper text and whatever else is needed for a user
|
|
6
|
-
# experience.
|
|
4
|
+
# A fully fledged form element for an attribute containing label, input field,
|
|
5
|
+
# error messages, helper text and whatever else is needed for a user-friendly
|
|
6
|
+
# input experience.
|
|
7
7
|
#
|
|
8
8
|
# @see https://flowbite.com/docs/forms/input-field/
|
|
9
9
|
#
|
|
@@ -13,54 +13,55 @@ module Flowbite
|
|
|
13
13
|
# more.
|
|
14
14
|
#
|
|
15
15
|
# Usually you'd use one of the subclasses of this class which implement the
|
|
16
|
-
# different input types, like
|
|
17
|
-
#
|
|
16
|
+
# different input types, like {Flowbite::InputField::Text},
|
|
17
|
+
# {Flowbite::InputField::Email}, etc.
|
|
18
18
|
#
|
|
19
|
-
#
|
|
19
|
+
# To render an input without labels or error messages etc, see
|
|
20
|
+
# {Flowbite::Input} instead and one of its subclasses.
|
|
20
21
|
#
|
|
21
|
-
# @
|
|
22
|
-
#
|
|
22
|
+
# @example Basic usage
|
|
23
|
+
# <% form_for @person do |form| %>
|
|
24
|
+
# <%= render(
|
|
25
|
+
# Flowbite::InputField::Number.new(
|
|
26
|
+
# attribute: :name,
|
|
27
|
+
# form: form
|
|
28
|
+
# )
|
|
29
|
+
# ) %>
|
|
30
|
+
# <% end %>
|
|
23
31
|
#
|
|
24
|
-
# @
|
|
25
|
-
#
|
|
32
|
+
# @example Kitchen sink
|
|
33
|
+
# <% form_for @person do |form| %>
|
|
34
|
+
# <%= render(
|
|
35
|
+
# Flowbite::InputField::Number.new(
|
|
36
|
+
# attribute: :name,
|
|
37
|
+
# class: ["mb-4", "w-full"],
|
|
38
|
+
# disabled: true,
|
|
39
|
+
# form: form,
|
|
40
|
+
# hint: {
|
|
41
|
+
# content: "Please enter your full name.",
|
|
42
|
+
# options: {id: "name-helper-text"}
|
|
43
|
+
# },
|
|
44
|
+
# input: {
|
|
45
|
+
# options: {placeholder: "All of your names here"}
|
|
46
|
+
# },
|
|
47
|
+
# label: {
|
|
48
|
+
# content: "Full name",
|
|
49
|
+
# options: {class: ["mb-2", "font-medium"]}
|
|
50
|
+
# },
|
|
51
|
+
# options: {data: {controller: "form-field"}},
|
|
52
|
+
# size: :lg
|
|
53
|
+
# )
|
|
54
|
+
# ) %>
|
|
55
|
+
# <% end %>
|
|
26
56
|
#
|
|
27
|
-
#
|
|
57
|
+
# @viewcomponent_slot [Flowbite::Input::Hint] hint Helper text displayed
|
|
58
|
+
# below the input field to provide additional context or instructions.
|
|
59
|
+
# @viewcomponent_slot [Flowbite::Input] input The input element itself.
|
|
60
|
+
# Usually auto-generated based on the input type subclass.
|
|
61
|
+
# @viewcomponent_slot [Flowbite::Input::Label] label The label for the input
|
|
62
|
+
# field, rendered above the input element.
|
|
28
63
|
#
|
|
29
|
-
# @
|
|
30
|
-
# additional context or instructions for the user. This is optional. See
|
|
31
|
-
# https://flowbite.com/docs/forms/input-field/#helper-text
|
|
32
|
-
#
|
|
33
|
-
# @param label [Hash] A hash with options for the label. These are passed to
|
|
34
|
-
# Flowbite::Input::Label, see that for details. Can contain:
|
|
35
|
-
# - `content`: The content of the label. If not provided, the label will
|
|
36
|
-
# default to the attribute name.
|
|
37
|
-
# - `options`: A hash of additional options to pass to the label component.
|
|
38
|
-
# This can be used to set the class, for example.
|
|
39
|
-
#
|
|
40
|
-
# @param disabled [Boolean] Whether the input field should be disabled.
|
|
41
|
-
# Defaults to `false`.
|
|
42
|
-
#
|
|
43
|
-
# @param input [Hash] A hash with options for the default input component.
|
|
44
|
-
# These are passed to the input components constructor, so see whatever
|
|
45
|
-
# component is being used for details. Can contain:
|
|
46
|
-
# - `options`: Additional HTML attributes to pass to the input element.
|
|
47
|
-
#
|
|
48
|
-
# @param size [Symbol] The size of the input field. Can be one of `:sm`,
|
|
49
|
-
# `:md`, or `:lg`. Defaults to `:md`.
|
|
50
|
-
#
|
|
51
|
-
# Sample usage
|
|
52
|
-
#
|
|
53
|
-
# <% form_for @person do |form| %>
|
|
54
|
-
# <%= render(
|
|
55
|
-
# Flowbite::InputField::Number.new(
|
|
56
|
-
# :attribute => :name,
|
|
57
|
-
# :form => form
|
|
58
|
-
# )
|
|
59
|
-
# ) %>
|
|
60
|
-
# <% end %>
|
|
61
|
-
#
|
|
62
|
-
# To render an input without labels or error messages etc, use
|
|
63
|
-
# `Flowbite::Input::Field` instead.
|
|
64
|
+
# @lookbook_embed InputFieldPreview
|
|
64
65
|
class InputField < ViewComponent::Base
|
|
65
66
|
renders_one :hint
|
|
66
67
|
renders_one :input
|
|
@@ -75,6 +76,45 @@ module Flowbite
|
|
|
75
76
|
@object.errors[@attribute] || []
|
|
76
77
|
end
|
|
77
78
|
|
|
79
|
+
# @param attribute [Symbol] The name of the attribute to render in this
|
|
80
|
+
# input field.
|
|
81
|
+
#
|
|
82
|
+
# @param form [ActionView::Helpers::FormBuilder] The form builder object that
|
|
83
|
+
# will be used to generate the input field.
|
|
84
|
+
#
|
|
85
|
+
# @param class [String, Array<String>] Additional CSS classes to apply to
|
|
86
|
+
# the input field container, i.e. the outermost element. To add classes to
|
|
87
|
+
# individual components of the InputField, use the +input+, +label+ and
|
|
88
|
+
# +hint+ arguments.
|
|
89
|
+
#
|
|
90
|
+
# @param disabled [Boolean] Whether the input field should be disabled.
|
|
91
|
+
#
|
|
92
|
+
# @param hint [Hash] A hint to display below the input field, providing
|
|
93
|
+
# additional context or instructions for the user. If provided, this Hash
|
|
94
|
+
# is passed to the {Flowbite::Input::Hint} constructor.
|
|
95
|
+
# @option hint [String] content The content of the hint element.
|
|
96
|
+
# @option hint [Hash] options Additional options to pass to the hint
|
|
97
|
+
# component. This can be used to set the class, for example.
|
|
98
|
+
#
|
|
99
|
+
# @param input [Hash] A hash with options for the input component.
|
|
100
|
+
# These are passed to the input component's constructor, see the
|
|
101
|
+
# documentation for whatever input component is being used.
|
|
102
|
+
# See {Flowbite::Input}.
|
|
103
|
+
# @option input [Hash] options Additional HTML attributes to pass to
|
|
104
|
+
# the input element.
|
|
105
|
+
#
|
|
106
|
+
# @param label [Hash] A hash with options for the label element. If
|
|
107
|
+
# provided, this Hash is passed to the {Flowbite::Input::Label}
|
|
108
|
+
# constructor.
|
|
109
|
+
# @option label [String] content The content of the label element.
|
|
110
|
+
# @option label [Hash] options Additional options to pass to the label
|
|
111
|
+
# component. This can be used to set the class, for example.
|
|
112
|
+
#
|
|
113
|
+
# @param options [Hash] Additional HTML attributes to pass to the input
|
|
114
|
+
# field container element.
|
|
115
|
+
#
|
|
116
|
+
# @param size [Symbol] The size of the input field. Can be one of +:sm+,
|
|
117
|
+
# +:default+, or +:lg+.
|
|
78
118
|
def initialize(attribute:, form:, class: nil, disabled: false, hint: nil, input: {}, label: {}, options: {}, size: :default)
|
|
79
119
|
@attribute = attribute
|
|
80
120
|
@class = Array.wrap(binding.local_variable_get(:class))
|
|
@@ -89,7 +129,7 @@ module Flowbite
|
|
|
89
129
|
end
|
|
90
130
|
|
|
91
131
|
def input_component
|
|
92
|
-
::Flowbite::Input
|
|
132
|
+
::Flowbite::Input
|
|
93
133
|
end
|
|
94
134
|
|
|
95
135
|
protected
|
|
@@ -102,6 +142,10 @@ module Flowbite
|
|
|
102
142
|
end
|
|
103
143
|
end
|
|
104
144
|
|
|
145
|
+
def container_options
|
|
146
|
+
@options.merge({class: classes.join(" ")})
|
|
147
|
+
end
|
|
148
|
+
|
|
105
149
|
def default_container_classes
|
|
106
150
|
[]
|
|
107
151
|
end
|
|
@@ -111,11 +155,19 @@ module Flowbite
|
|
|
111
155
|
return unless hint?
|
|
112
156
|
|
|
113
157
|
component = Flowbite::Input::Hint.new(
|
|
158
|
+
**default_hint_arguments
|
|
159
|
+
).with_content(default_hint_content)
|
|
160
|
+
render(component)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# @return [Hash] The keyword arguments for the hint component.
|
|
164
|
+
def default_hint_arguments
|
|
165
|
+
{
|
|
114
166
|
attribute: @attribute,
|
|
167
|
+
class: @hint[:class],
|
|
115
168
|
form: @form,
|
|
116
169
|
options: default_hint_options
|
|
117
|
-
|
|
118
|
-
render(component)
|
|
170
|
+
}
|
|
119
171
|
end
|
|
120
172
|
|
|
121
173
|
def default_hint_content
|
|
@@ -136,23 +188,37 @@ module Flowbite
|
|
|
136
188
|
}.merge(@hint[:options] || {})
|
|
137
189
|
end
|
|
138
190
|
|
|
191
|
+
# Returns the HTML to use for the default input element.
|
|
192
|
+
def default_input
|
|
193
|
+
render(input_component.new(**default_input_arguments))
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# @return [Hash] The keyword arguments for the default input component.
|
|
197
|
+
def default_input_arguments
|
|
198
|
+
{
|
|
199
|
+
attribute: @attribute,
|
|
200
|
+
class: @input[:class],
|
|
201
|
+
disabled: @disabled,
|
|
202
|
+
form: @form,
|
|
203
|
+
options: default_input_options,
|
|
204
|
+
size: @size
|
|
205
|
+
}
|
|
206
|
+
end
|
|
207
|
+
|
|
139
208
|
# Returns a Hash with the default attributes to apply to the input element.
|
|
140
209
|
#
|
|
141
210
|
# The default attributes can be overriden by passing the `input[options]`
|
|
142
211
|
# argument to the constructor.
|
|
143
212
|
def default_input_options
|
|
144
|
-
if hint?
|
|
213
|
+
options = if hint?
|
|
145
214
|
{
|
|
146
215
|
"aria-describedby": id_for_hint_element
|
|
147
216
|
}
|
|
148
217
|
else
|
|
149
218
|
{}
|
|
150
219
|
end
|
|
151
|
-
end
|
|
152
220
|
|
|
153
|
-
|
|
154
|
-
def default_input
|
|
155
|
-
render(input_component.new(**input_arguments))
|
|
221
|
+
options.merge(@input[:options] || {})
|
|
156
222
|
end
|
|
157
223
|
|
|
158
224
|
def default_label
|
|
@@ -197,20 +263,5 @@ module Flowbite
|
|
|
197
263
|
.compact_blank
|
|
198
264
|
.join("_")
|
|
199
265
|
end
|
|
200
|
-
|
|
201
|
-
# @return [Hash] The keyword arguments for the input component.
|
|
202
|
-
def input_arguments
|
|
203
|
-
{
|
|
204
|
-
attribute: @attribute,
|
|
205
|
-
disabled: @disabled,
|
|
206
|
-
form: @form,
|
|
207
|
-
options: input_options,
|
|
208
|
-
size: @size
|
|
209
|
-
}
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
def input_options
|
|
213
|
-
default_input_options.merge(@input[:options] || {})
|
|
214
|
-
end
|
|
215
266
|
end
|
|
216
267
|
end
|
|
@@ -5,6 +5,8 @@ module Flowbite
|
|
|
5
5
|
# to an external website when clicking on an inline text item, button, or card
|
|
6
6
|
#
|
|
7
7
|
# Use this component to add default styles to an inline link element.
|
|
8
|
+
#
|
|
9
|
+
# @lookbook_embed LinkPreview
|
|
8
10
|
class Link < ViewComponent::Base
|
|
9
11
|
attr_reader :href, :options
|
|
10
12
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flowbite
|
|
4
|
+
class Sidebar
|
|
5
|
+
# Renders a sidebar navigation item.
|
|
6
|
+
#
|
|
7
|
+
# Each item renders as a list item containing a link. Optionally, an icon
|
|
8
|
+
# can be provided using the +icon+ slot, which will be displayed before the
|
|
9
|
+
# label text.
|
|
10
|
+
#
|
|
11
|
+
# @example Basic item
|
|
12
|
+
# <%= render Flowbite::Sidebar::Item.new(href: "/dashboard") { "Dashboard" } %>
|
|
13
|
+
#
|
|
14
|
+
# @example Item with icon
|
|
15
|
+
# <%= render(Flowbite::Sidebar::Item.new(href: "/dashboard")) do |item| %>
|
|
16
|
+
# <% item.with_icon do %>
|
|
17
|
+
# <svg class="w-5 h-5" ...>...</svg>
|
|
18
|
+
# <% end %>
|
|
19
|
+
# Dashboard
|
|
20
|
+
# <% end %>
|
|
21
|
+
#
|
|
22
|
+
# @viewcomponent_slot icon An optional icon displayed before the label text.
|
|
23
|
+
class Item < ViewComponent::Base
|
|
24
|
+
renders_one :icon
|
|
25
|
+
|
|
26
|
+
attr_reader :href, :options
|
|
27
|
+
|
|
28
|
+
class << self
|
|
29
|
+
def classes
|
|
30
|
+
[
|
|
31
|
+
"flex", "items-center", "px-2", "py-1.5", "text-body",
|
|
32
|
+
"rounded-base", "hover:bg-neutral-tertiary", "hover:text-fg-brand", "group"
|
|
33
|
+
]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @param class [Array<String>] Additional CSS classes for the link element.
|
|
38
|
+
# @param href [String] The URL for the navigation link.
|
|
39
|
+
# @param options [Hash] Additional HTML attributes for the link element.
|
|
40
|
+
def initialize(href:, class: nil, **options)
|
|
41
|
+
super()
|
|
42
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
43
|
+
@href = href
|
|
44
|
+
@options = options
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def call
|
|
48
|
+
content_tag(:li) do
|
|
49
|
+
link_options = {class: link_classes}.merge(options)
|
|
50
|
+
content_tag(:a, href: href, **link_options) do
|
|
51
|
+
concat(icon) if icon?
|
|
52
|
+
concat(content_tag(:span, content, class: label_classes))
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def label_classes
|
|
60
|
+
"ms-3" if icon?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def link_classes
|
|
64
|
+
self.class.classes + @class
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flowbite
|
|
4
|
+
class Sidebar
|
|
5
|
+
# Renders the navigation list for a sidebar.
|
|
6
|
+
#
|
|
7
|
+
# This component renders a +<ul>+ with navigation items. It can be used
|
|
8
|
+
# inside a {Flowbite::Sidebar} for a fixed-position sidebar, or standalone
|
|
9
|
+
# in any layout that needs sidebar-style navigation.
|
|
10
|
+
#
|
|
11
|
+
# @example Inside a Sidebar
|
|
12
|
+
# <%= render(Flowbite::Sidebar.new) do %>
|
|
13
|
+
# <%= render(Flowbite::Sidebar::Navigation.new) do |nav| %>
|
|
14
|
+
# <% nav.with_item do %>
|
|
15
|
+
# <%= render(Flowbite::Sidebar::Item.new(href: "/")) { "Home" } %>
|
|
16
|
+
# <% end %>
|
|
17
|
+
# <% end %>
|
|
18
|
+
# <% end %>
|
|
19
|
+
#
|
|
20
|
+
# @example Standalone
|
|
21
|
+
# <%= render(Flowbite::Sidebar::Navigation.new) do |nav| %>
|
|
22
|
+
# <% nav.with_item do %>
|
|
23
|
+
# <%= render(Flowbite::Sidebar::Item.new(href: "/")) { "Home" } %>
|
|
24
|
+
# <% end %>
|
|
25
|
+
# <% end %>
|
|
26
|
+
class Navigation < ViewComponent::Base
|
|
27
|
+
renders_many :items
|
|
28
|
+
|
|
29
|
+
class << self
|
|
30
|
+
def classes
|
|
31
|
+
["space-y-2", "font-medium"]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @param class [Array<String>] Additional CSS classes for the list element.
|
|
36
|
+
# @param options [Hash] Additional HTML options for the list element.
|
|
37
|
+
def initialize(class: nil, **options)
|
|
38
|
+
super()
|
|
39
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
40
|
+
@options = options
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def call
|
|
44
|
+
content_tag(:ul, list_options) do
|
|
45
|
+
items.each do |item|
|
|
46
|
+
concat(item)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def list_classes
|
|
54
|
+
self.class.classes + @class
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def list_options
|
|
58
|
+
{class: list_classes}.merge(@options)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flowbite
|
|
4
|
+
# Renders a fixed-position sidebar container.
|
|
5
|
+
#
|
|
6
|
+
# Use {Flowbite::Sidebar} as the outer shell and
|
|
7
|
+
# {Flowbite::Sidebar::Navigation} inside it to render the list of
|
|
8
|
+
# {Flowbite::Sidebar::Item}s.
|
|
9
|
+
#
|
|
10
|
+
# @example Usage
|
|
11
|
+
# <%= render(Flowbite::Sidebar.new) do %>
|
|
12
|
+
# <%= render(Flowbite::Sidebar::Navigation.new) do |nav| %>
|
|
13
|
+
# <% nav.with_item do %>
|
|
14
|
+
# <%= render(Flowbite::Sidebar::Item.new(href: "/dashboard")) { "Dashboard" } %>
|
|
15
|
+
# <% end %>
|
|
16
|
+
# <% end %>
|
|
17
|
+
# <% end %>
|
|
18
|
+
#
|
|
19
|
+
# @see https://flowbite.com/docs/components/sidebar/
|
|
20
|
+
# @lookbook_embed SidebarPreview
|
|
21
|
+
class Sidebar < ViewComponent::Base
|
|
22
|
+
class << self
|
|
23
|
+
def classes
|
|
24
|
+
[
|
|
25
|
+
"fixed", "top-0", "left-0", "z-40", "w-64", "h-screen",
|
|
26
|
+
"transition-transform", "-translate-x-full", "sm:translate-x-0"
|
|
27
|
+
]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @param class [Array<String>] Additional CSS classes for the sidebar
|
|
32
|
+
# container.
|
|
33
|
+
# @param options [Hash] Additional HTML options for the sidebar container.
|
|
34
|
+
def initialize(class: nil, **options)
|
|
35
|
+
super()
|
|
36
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
37
|
+
@options = options
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def call
|
|
41
|
+
content_tag(:aside, aside_options) do
|
|
42
|
+
content_tag(:div, class: wrapper_classes) do
|
|
43
|
+
content
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def aside_classes
|
|
51
|
+
self.class.classes + @class
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def aside_options
|
|
55
|
+
{class: aside_classes, "aria-label": "Sidebar"}.merge(@options)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def wrapper_classes
|
|
59
|
+
["h-full", "px-3", "py-4", "overflow-y-auto", "bg-neutral-primary-soft"]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flowbite
|
|
4
|
+
class Toast
|
|
5
|
+
# Renders an icon for a toast notification.
|
|
6
|
+
#
|
|
7
|
+
# @param style [Symbol] The color style of the icon (:default, :success, :danger, :warning).
|
|
8
|
+
class Icon < ViewComponent::Base
|
|
9
|
+
class << self
|
|
10
|
+
def classes(style: :default)
|
|
11
|
+
styles.fetch(style).fetch(:classes)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def svg_path(style: :default)
|
|
15
|
+
styles.fetch(style).fetch(:svg_path)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# rubocop:disable Layout/LineLength
|
|
19
|
+
def styles
|
|
20
|
+
{
|
|
21
|
+
default: {
|
|
22
|
+
classes: ["inline-flex", "items-center", "justify-center", "shrink-0", "w-8", "h-8", "text-blue-500", "bg-blue-100", "rounded-lg", "dark:bg-blue-800", "dark:text-blue-200"],
|
|
23
|
+
svg_path: "M15.147 15.085a7.159 7.159 0 0 1-6.189 3.307A6.713 6.713 0 0 1 3.1 15.444c-2.679-4.513.287-8.737.888-9.548A4.373 4.373 0 0 0 5 1.608c1.287.953 6.445 3.218 5.537 10.5 1.5-1.122 2.706-3.01 2.853-6.14 1.433 1.049 3.993 5.395 1.757 9.117Z"
|
|
24
|
+
},
|
|
25
|
+
success: {
|
|
26
|
+
classes: ["inline-flex", "items-center", "justify-center", "shrink-0", "w-8", "h-8", "text-green-500", "bg-green-100", "rounded-lg", "dark:bg-green-800", "dark:text-green-200"],
|
|
27
|
+
svg_path: "M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z"
|
|
28
|
+
},
|
|
29
|
+
danger: {
|
|
30
|
+
classes: ["inline-flex", "items-center", "justify-center", "shrink-0", "w-8", "h-8", "text-red-500", "bg-red-100", "rounded-lg", "dark:bg-red-800", "dark:text-red-200"],
|
|
31
|
+
svg_path: "M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 11.793a1 1 0 1 1-1.414 1.414L10 11.414l-2.293 2.293a1 1 0 0 1-1.414-1.414L8.586 10 6.293 7.707a1 1 0 0 1 1.414-1.414L10 8.586l2.293-2.293a1 1 0 0 1 1.414 1.414L11.414 10l2.293 2.293Z"
|
|
32
|
+
},
|
|
33
|
+
warning: {
|
|
34
|
+
classes: ["inline-flex", "items-center", "justify-center", "shrink-0", "w-8", "h-8", "text-orange-500", "bg-orange-100", "rounded-lg", "dark:bg-orange-700", "dark:text-orange-200"],
|
|
35
|
+
svg_path: "M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM10 15a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-4a1 1 0 0 1-2 0V6a1 1 0 0 1 2 0v5Z"
|
|
36
|
+
}
|
|
37
|
+
}.freeze
|
|
38
|
+
end
|
|
39
|
+
# rubocop:enable Layout/LineLength
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
attr_reader :style
|
|
43
|
+
|
|
44
|
+
def initialize(style: :default)
|
|
45
|
+
@style = style
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def container_classes
|
|
49
|
+
self.class.classes(style: style)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def svg_path
|
|
53
|
+
self.class.svg_path(style: style)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<%= tag.div(
|
|
2
|
+
class: container_classes.join(" "),
|
|
3
|
+
role: "alert",
|
|
4
|
+
**options,
|
|
5
|
+
) do %>
|
|
6
|
+
<%= render Flowbite::Toast::Icon.new(style: style) %>
|
|
7
|
+
|
|
8
|
+
<div class="ms-3 text-sm font-normal"><%= message %></div>
|
|
9
|
+
|
|
10
|
+
<% if dismissible %>
|
|
11
|
+
<%# Styles from https://flowbite.com/docs/components/toast/#default-toast %>
|
|
12
|
+
<button
|
|
13
|
+
type="button"
|
|
14
|
+
class="
|
|
15
|
+
ms-auto flex items-center justify-center text-body
|
|
16
|
+
hover:text-heading bg-transparent box-border border
|
|
17
|
+
border-transparent hover:bg-neutral-secondary-medium focus:ring-4
|
|
18
|
+
focus:ring-neutral-tertiary font-medium leading-5 rounded text-sm
|
|
19
|
+
h-8 w-8 focus:outline-none
|
|
20
|
+
"
|
|
21
|
+
aria-label="Close"
|
|
22
|
+
>
|
|
23
|
+
<svg
|
|
24
|
+
class="w-3 h-3"
|
|
25
|
+
aria-hidden="true"
|
|
26
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
27
|
+
fill="none"
|
|
28
|
+
viewBox="0 0 14 14"
|
|
29
|
+
>
|
|
30
|
+
<path
|
|
31
|
+
stroke="currentColor"
|
|
32
|
+
stroke-linecap="round"
|
|
33
|
+
stroke-linejoin="round"
|
|
34
|
+
stroke-width="2"
|
|
35
|
+
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
|
|
36
|
+
/>
|
|
37
|
+
</svg>
|
|
38
|
+
</button>
|
|
39
|
+
<% end %>
|
|
40
|
+
<% end %>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flowbite
|
|
4
|
+
# Renders a toast notification element.
|
|
5
|
+
#
|
|
6
|
+
# @example Usage
|
|
7
|
+
# <%= render(Flowbite::Toast.new(message: "Something has happened!")) %>
|
|
8
|
+
#
|
|
9
|
+
# @see https://flowbite.com/docs/components/toast/
|
|
10
|
+
# @lookbook_embed ToastPreview
|
|
11
|
+
class Toast < ViewComponent::Base
|
|
12
|
+
class << self
|
|
13
|
+
def classes
|
|
14
|
+
["flex", "items-center", "w-full", "max-w-xs", "p-4", "text-body", "bg-neutral-primary-soft", "rounded-base", "shadow-xs", "border", "border-default"]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
attr_reader :dismissible, :message, :options, :style
|
|
19
|
+
|
|
20
|
+
# @param class [Array<String>] Additional CSS classes for the toast container.
|
|
21
|
+
# @param dismissible [Boolean] Whether the toast can be dismissed (default: true).
|
|
22
|
+
# @param message [String] The message to display in the toast.
|
|
23
|
+
# @param options [Hash] Additional HTML options for the toast container.
|
|
24
|
+
# @param style [Symbol] The color style of the toast (:default, :success, :danger, :warning).
|
|
25
|
+
def initialize(message:, dismissible: true, style: :default, class: nil, **options)
|
|
26
|
+
@message = message
|
|
27
|
+
@style = style
|
|
28
|
+
@dismissible = dismissible
|
|
29
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
30
|
+
@options = options
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def container_classes
|
|
34
|
+
self.class.classes + @class
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# YARD plugin for documenting ViewComponent slots
|
|
4
|
+
#
|
|
5
|
+
# This plugin adds a @viewcomponent_slot tag that can be used to document
|
|
6
|
+
# slots defined with renders_one and renders_many in ViewComponent classes.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# # @viewcomponent_slot [Flowbite::Card::Title] title The title of the card
|
|
10
|
+
# renders_one :title
|
|
11
|
+
#
|
|
12
|
+
# # @viewcomponent_slot [Flowbite::Breadcrumb::Item] items The breadcrumb items
|
|
13
|
+
# renders_many :items
|
|
14
|
+
#
|
|
15
|
+
# The tag accepts:
|
|
16
|
+
# - Types (optional): The component class(es) that can be rendered in the slot
|
|
17
|
+
# - Name (required): The slot name (matching the symbol passed to renders_one/renders_many)
|
|
18
|
+
# - Description (optional): A description of what the slot is for
|
|
19
|
+
|
|
20
|
+
YARD::Tags::Library.define_tag(
|
|
21
|
+
"ViewComponent Slot",
|
|
22
|
+
:viewcomponent_slot,
|
|
23
|
+
:with_types_and_name
|
|
24
|
+
)
|