nanoui 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/CHANGELOG.md +18 -0
- data/README.md +189 -199
- data/lib/generators/nanoui/component_generator.rb +0 -52
- data/lib/generators/nanoui/install_generator.rb +0 -18
- data/lib/generators/nanoui/templates/css/components/alert.css +1 -1
- data/lib/generators/nanoui/templates/css/components/button.css +36 -7
- data/lib/generators/nanoui/templates/css/components/card.css +2 -1
- data/lib/generators/nanoui/templates/css/components/dialog.css +1 -1
- data/lib/generators/nanoui/templates/css/components/input.css +62 -8
- data/lib/generators/nanoui/templates/css/components/label.css +2 -1
- data/lib/generators/nanoui/templates/css/components/select.css +12 -7
- data/lib/nanoui/version.rb +1 -1
- metadata +1 -22
- data/lib/generators/nanoui/templates/css/nanoui.css +0 -33
- data/lib/generators/nanoui/templates/css/nanoui.install.css +0 -15
- data/lib/generators/nanoui/templates/views/components/_accordion.html.erb +0 -40
- data/lib/generators/nanoui/templates/views/components/_alert.html.erb +0 -33
- data/lib/generators/nanoui/templates/views/components/_badge.html.erb +0 -18
- data/lib/generators/nanoui/templates/views/components/_button.html.erb +0 -27
- data/lib/generators/nanoui/templates/views/components/_card.html.erb +0 -43
- data/lib/generators/nanoui/templates/views/components/_checkbox.html.erb +0 -36
- data/lib/generators/nanoui/templates/views/components/_dialog.html.erb +0 -65
- data/lib/generators/nanoui/templates/views/components/_dropdown.html.erb +0 -29
- data/lib/generators/nanoui/templates/views/components/_input.html.erb +0 -42
- data/lib/generators/nanoui/templates/views/components/_label.html.erb +0 -20
- data/lib/generators/nanoui/templates/views/components/_progress.html.erb +0 -29
- data/lib/generators/nanoui/templates/views/components/_radio_group.html.erb +0 -46
- data/lib/generators/nanoui/templates/views/components/_select.html.erb +0 -67
- data/lib/generators/nanoui/templates/views/components/_switch.html.erb +0 -32
- data/lib/generators/nanoui/templates/views/components/_table.html.erb +0 -41
- data/lib/generators/nanoui/templates/views/components/_tabs.html.erb +0 -46
- data/lib/generators/nanoui/templates/views/components/_toast.html.erb +0 -33
- data/lib/generators/nanoui/templates/views/components/_toast_container.html.erb +0 -17
- data/lib/generators/nanoui/templates/views/components/_tooltip.html.erb +0 -28
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Checkbox
|
|
2
|
-
Options: label, id (auto), checked (false), disabled (false), error (false), name, value, class, html
|
|
3
|
-
Usage:
|
|
4
|
-
render "components/checkbox", label: "Accept terms", name: "tos", required: true
|
|
5
|
-
render "components/checkbox", label: "Remember me", checked: true
|
|
6
|
-
%>
|
|
7
|
-
<%
|
|
8
|
-
label_text = local_assigns.fetch(:label, "")
|
|
9
|
-
input_id = local_assigns.fetch(:id, "checkbox-#{SecureRandom.hex(4)}")
|
|
10
|
-
checked = local_assigns.fetch(:checked, false)
|
|
11
|
-
disabled = local_assigns.fetch(:disabled, false)
|
|
12
|
-
error = local_assigns.fetch(:error, false)
|
|
13
|
-
name = local_assigns.fetch(:name, nil)
|
|
14
|
-
value = local_assigns.fetch(:value, "1")
|
|
15
|
-
classes = local_assigns.fetch(:class, "")
|
|
16
|
-
|
|
17
|
-
css = ["nano-checkbox"]
|
|
18
|
-
css << "nano-checkbox--error" if error
|
|
19
|
-
css << classes if classes.present?
|
|
20
|
-
%>
|
|
21
|
-
|
|
22
|
-
<div class="<%= css.join(" ").strip %>">
|
|
23
|
-
<%
|
|
24
|
-
checkbox_attributes = {
|
|
25
|
-
type: "checkbox",
|
|
26
|
-
id: input_id,
|
|
27
|
-
class: "nano-checkbox__input",
|
|
28
|
-
value: value
|
|
29
|
-
}
|
|
30
|
-
checkbox_attributes[:name] = name if name
|
|
31
|
-
checkbox_attributes[:checked] = true if checked
|
|
32
|
-
checkbox_attributes[:disabled] = true if disabled
|
|
33
|
-
%>
|
|
34
|
-
<%= tag.input(**checkbox_attributes) %>
|
|
35
|
-
<label for="<%= input_id %>" class="nano-checkbox__label"><%= label_text %></label>
|
|
36
|
-
</div>
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Dialog (native <dialog> with Stimulus)
|
|
2
|
-
Options: size (sm, md, lg, full), title, description, title_id (auto), trigger, footer, class
|
|
3
|
-
Usage:
|
|
4
|
-
render "components/dialog",
|
|
5
|
-
title: "Edit Profile",
|
|
6
|
-
description: "Update your info.",
|
|
7
|
-
trigger: render("components/button") { "Open" },
|
|
8
|
-
footer: render("components/button", variant: "outline", html: { data: { action: "nanoui-dialog#close" } }) { "Cancel" } do
|
|
9
|
-
"Dialog body content here"
|
|
10
|
-
end
|
|
11
|
-
%>
|
|
12
|
-
<%
|
|
13
|
-
size = local_assigns.fetch(:size, "md")
|
|
14
|
-
title = local_assigns.fetch(:title, "")
|
|
15
|
-
desc = local_assigns.fetch(:description, nil)
|
|
16
|
-
title_id = local_assigns.fetch(:title_id, "dialog-title-#{SecureRandom.hex(4)}")
|
|
17
|
-
trigger = local_assigns.fetch(:trigger, nil)
|
|
18
|
-
footer = local_assigns.fetch(:footer, nil)
|
|
19
|
-
classes = local_assigns.fetch(:class, "")
|
|
20
|
-
|
|
21
|
-
css = ["nano-dialog"]
|
|
22
|
-
css << "nano-dialog--#{size}" unless size == "md"
|
|
23
|
-
css << classes if classes.present?
|
|
24
|
-
%>
|
|
25
|
-
|
|
26
|
-
<div data-controller="nanoui-dialog">
|
|
27
|
-
<% if trigger %>
|
|
28
|
-
<div class="nano-dialog__trigger" data-action="click->nanoui-dialog#open">
|
|
29
|
-
<%= trigger %>
|
|
30
|
-
</div>
|
|
31
|
-
<% end %>
|
|
32
|
-
|
|
33
|
-
<dialog data-nanoui-dialog-target="modal"
|
|
34
|
-
data-action="click->nanoui-dialog#clickBackdrop cancel->nanoui-dialog#cancel"
|
|
35
|
-
class="<%= css.join(" ").strip %>"
|
|
36
|
-
aria-labelledby="<%= title_id %>">
|
|
37
|
-
<div class="nano-dialog__content">
|
|
38
|
-
<header class="nano-dialog__header">
|
|
39
|
-
<h2 id="<%= title_id %>" class="nano-dialog__title"><%= title %></h2>
|
|
40
|
-
<% if desc %>
|
|
41
|
-
<p class="nano-dialog__description"><%= desc %></p>
|
|
42
|
-
<% end %>
|
|
43
|
-
</header>
|
|
44
|
-
|
|
45
|
-
<div class="nano-dialog__body">
|
|
46
|
-
<%= yield %>
|
|
47
|
-
</div>
|
|
48
|
-
|
|
49
|
-
<% if footer %>
|
|
50
|
-
<footer class="nano-dialog__footer">
|
|
51
|
-
<%= footer %>
|
|
52
|
-
</footer>
|
|
53
|
-
<% end %>
|
|
54
|
-
|
|
55
|
-
<button data-action="nanoui-dialog#close" class="nano-dialog__close"
|
|
56
|
-
type="button" aria-label="Close dialog">
|
|
57
|
-
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="16" height="16"
|
|
58
|
-
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
59
|
-
stroke-linecap="round" stroke-linejoin="round">
|
|
60
|
-
<path d="M18 6 6 18"/><path d="m6 6 12 12"/>
|
|
61
|
-
</svg>
|
|
62
|
-
</button>
|
|
63
|
-
</div>
|
|
64
|
-
</dialog>
|
|
65
|
-
</div>
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Dropdown (Stimulus-powered)
|
|
2
|
-
Options: trigger, class
|
|
3
|
-
Usage:
|
|
4
|
-
render "components/dropdown",
|
|
5
|
-
trigger: render("components/button", variant: "outline") { "Options" } do
|
|
6
|
-
'<button class="nano-dropdown__item">Profile</button>
|
|
7
|
-
<button class="nano-dropdown__item">Settings</button>
|
|
8
|
-
<div class="nano-dropdown__separator"></div>
|
|
9
|
-
<button class="nano-dropdown__item">Log out</button>'.html_safe
|
|
10
|
-
end
|
|
11
|
-
%>
|
|
12
|
-
<%
|
|
13
|
-
classes = local_assigns.fetch(:class, "")
|
|
14
|
-
trigger = local_assigns.fetch(:trigger, nil)
|
|
15
|
-
css = "nano-dropdown"
|
|
16
|
-
css += " #{classes}" if classes.present?
|
|
17
|
-
%>
|
|
18
|
-
|
|
19
|
-
<div class="<%= css.strip %>" data-controller="nanoui-dropdown">
|
|
20
|
-
<div data-action="click->nanoui-dropdown#toggle keydown->nanoui-dropdown#activateTrigger"
|
|
21
|
-
data-nanoui-dropdown-target="trigger"
|
|
22
|
-
class="nano-dropdown__trigger">
|
|
23
|
-
<%= trigger || content_tag(:button, "Options", type: "button", class: "nano-btn nano-btn--outline") %>
|
|
24
|
-
</div>
|
|
25
|
-
|
|
26
|
-
<div class="nano-dropdown__content" data-nanoui-dropdown-target="content">
|
|
27
|
-
<%= yield %>
|
|
28
|
-
</div>
|
|
29
|
-
</div>
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Input (wrapped in .nano-field with optional label and error)
|
|
2
|
-
Options: label, required (false), error, type ("text"), id (auto), class, html
|
|
3
|
-
Usage:
|
|
4
|
-
render "components/input", label: "Email", type: "email", required: true
|
|
5
|
-
render "components/input", label: "Name", error: "Required", html: { placeholder: "Jane" }
|
|
6
|
-
%>
|
|
7
|
-
<%
|
|
8
|
-
label_text = local_assigns.fetch(:label, nil)
|
|
9
|
-
required = local_assigns.fetch(:required, false)
|
|
10
|
-
error = local_assigns.fetch(:error, nil)
|
|
11
|
-
type = local_assigns.fetch(:type, "text")
|
|
12
|
-
input_id = local_assigns.fetch(:id, "input-#{SecureRandom.hex(4)}")
|
|
13
|
-
classes = local_assigns.fetch(:class, "")
|
|
14
|
-
html = local_assigns.fetch(:html, {}).symbolize_keys
|
|
15
|
-
|
|
16
|
-
css = ["nano-input"]
|
|
17
|
-
css << "nano-input--error" if error
|
|
18
|
-
css << classes if classes.present?
|
|
19
|
-
error_id = "#{input_id}-error" if error
|
|
20
|
-
input_attributes = {
|
|
21
|
-
id: input_id,
|
|
22
|
-
type: type,
|
|
23
|
-
class: css.join(" ")
|
|
24
|
-
}.merge(html)
|
|
25
|
-
input_attributes[:required] = true if required
|
|
26
|
-
if error
|
|
27
|
-
input_attributes[:"aria-invalid"] = true
|
|
28
|
-
input_attributes[:"aria-describedby"] = error_id
|
|
29
|
-
end
|
|
30
|
-
%>
|
|
31
|
-
|
|
32
|
-
<div class="nano-field">
|
|
33
|
-
<% if label_text %>
|
|
34
|
-
<label for="<%= input_id %>" class="nano-label<%= " nano-label--required" if required %>"><%= label_text %></label>
|
|
35
|
-
<% end %>
|
|
36
|
-
|
|
37
|
-
<%= tag.input(**input_attributes) %>
|
|
38
|
-
|
|
39
|
-
<% if error %>
|
|
40
|
-
<p id="<%= error_id %>" class="nano-field__error" role="alert"><%= error %></p>
|
|
41
|
-
<% end %>
|
|
42
|
-
</div>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Label
|
|
2
|
-
Options: for, required (false), class
|
|
3
|
-
Usage:
|
|
4
|
-
render "components/label", for: "email", required: true do "Email" end
|
|
5
|
-
%>
|
|
6
|
-
<%
|
|
7
|
-
label_for = local_assigns.fetch(:for, nil)
|
|
8
|
-
required = local_assigns.fetch(:required, false)
|
|
9
|
-
classes = local_assigns.fetch(:class, "")
|
|
10
|
-
|
|
11
|
-
css = "nano-label"
|
|
12
|
-
css += " nano-label--required" if required
|
|
13
|
-
css += " #{classes}" if classes.present?
|
|
14
|
-
label_attributes = { class: css.strip }
|
|
15
|
-
label_attributes[:for] = label_for if label_for
|
|
16
|
-
%>
|
|
17
|
-
|
|
18
|
-
<%= content_tag(:label, label_attributes) do %>
|
|
19
|
-
<%= yield %>
|
|
20
|
-
<% end %>
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Progress (native <progress>)
|
|
2
|
-
Variants: default, success, warning, destructive
|
|
3
|
-
Options: value, max (100), variant, label, aria_label, class
|
|
4
|
-
Usage:
|
|
5
|
-
render "components/progress", value: 65, label: "65%", aria_label: "Upload progress"
|
|
6
|
-
render "components/progress", value: 100, variant: "success", label: "Complete"
|
|
7
|
-
%>
|
|
8
|
-
<%
|
|
9
|
-
value = local_assigns.fetch(:value, nil)
|
|
10
|
-
max = local_assigns.fetch(:max, 100)
|
|
11
|
-
variant = local_assigns.fetch(:variant, nil)
|
|
12
|
-
label = local_assigns.fetch(:label, nil)
|
|
13
|
-
aria_label = local_assigns.fetch(:aria_label, "Progress")
|
|
14
|
-
classes = local_assigns.fetch(:class, "")
|
|
15
|
-
|
|
16
|
-
css = ["nano-progress"]
|
|
17
|
-
css << "nano-progress--#{variant}" if variant
|
|
18
|
-
css << classes if classes.present?
|
|
19
|
-
%>
|
|
20
|
-
|
|
21
|
-
<div class="<%= css.join(" ").strip %>">
|
|
22
|
-
<progress class="nano-progress__bar"
|
|
23
|
-
<% if value %> value="<%= value %>"<% end %>
|
|
24
|
-
max="<%= max %>"
|
|
25
|
-
aria-label="<%= aria_label %>"><%= "#{value}%" if value %></progress>
|
|
26
|
-
<% if label %>
|
|
27
|
-
<span class="nano-progress__label" aria-hidden="true"><%= label %></span>
|
|
28
|
-
<% end %>
|
|
29
|
-
</div>
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Radio Group
|
|
2
|
-
Options: legend, name, options (array of {label:, value:, checked:, disabled:}), error (false), class
|
|
3
|
-
Usage:
|
|
4
|
-
render "components/radio_group",
|
|
5
|
-
legend: "Plan",
|
|
6
|
-
name: "plan",
|
|
7
|
-
options: [
|
|
8
|
-
{ label: "Free", value: "free", checked: true },
|
|
9
|
-
{ label: "Pro", value: "pro" },
|
|
10
|
-
{ label: "Enterprise", value: "enterprise" }
|
|
11
|
-
]
|
|
12
|
-
%>
|
|
13
|
-
<%
|
|
14
|
-
legend_text = local_assigns.fetch(:legend, nil)
|
|
15
|
-
name = local_assigns.fetch(:name, "radio-#{SecureRandom.hex(4)}")
|
|
16
|
-
options = local_assigns.fetch(:options, [])
|
|
17
|
-
error = local_assigns.fetch(:error, false)
|
|
18
|
-
classes = local_assigns.fetch(:class, "")
|
|
19
|
-
|
|
20
|
-
css = "nano-radio-group"
|
|
21
|
-
css += " #{classes}" if classes.present?
|
|
22
|
-
%>
|
|
23
|
-
|
|
24
|
-
<fieldset class="<%= css.strip %>">
|
|
25
|
-
<% if legend_text %>
|
|
26
|
-
<legend class="nano-radio-group__legend"><%= legend_text %></legend>
|
|
27
|
-
<% end %>
|
|
28
|
-
|
|
29
|
-
<% options.each_with_index do |opt, i| %>
|
|
30
|
-
<%
|
|
31
|
-
radio_id = "#{name}-#{i}"
|
|
32
|
-
radio_css = "nano-radio"
|
|
33
|
-
radio_css += " nano-radio--error" if error
|
|
34
|
-
%>
|
|
35
|
-
<div class="<%= radio_css %>">
|
|
36
|
-
<input type="radio"
|
|
37
|
-
id="<%= radio_id %>"
|
|
38
|
-
name="<%= name %>"
|
|
39
|
-
value="<%= opt[:value] %>"
|
|
40
|
-
class="nano-radio__input"
|
|
41
|
-
<%= "checked" if opt[:checked] %>
|
|
42
|
-
<%= "disabled" if opt[:disabled] %>>
|
|
43
|
-
<label for="<%= radio_id %>" class="nano-radio__label"><%= opt[:label] %></label>
|
|
44
|
-
</div>
|
|
45
|
-
<% end %>
|
|
46
|
-
</fieldset>
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Select (wrapped in .nano-field with optional label and error)
|
|
2
|
-
Options: label, required (false), error, options (array of strings or {label:, value:}),
|
|
3
|
-
placeholder, id (auto), name, disabled, class, html
|
|
4
|
-
Usage:
|
|
5
|
-
render "components/select",
|
|
6
|
-
label: "Country",
|
|
7
|
-
placeholder: "Select a country",
|
|
8
|
-
options: ["United States", "Canada", "United Kingdom"]
|
|
9
|
-
|
|
10
|
-
render "components/select",
|
|
11
|
-
label: "Role",
|
|
12
|
-
required: true,
|
|
13
|
-
options: [
|
|
14
|
-
{ label: "Admin", value: "admin" },
|
|
15
|
-
{ label: "Editor", value: "editor" }
|
|
16
|
-
]
|
|
17
|
-
%>
|
|
18
|
-
<%
|
|
19
|
-
label_text = local_assigns.fetch(:label, nil)
|
|
20
|
-
required = local_assigns.fetch(:required, false)
|
|
21
|
-
error = local_assigns.fetch(:error, nil)
|
|
22
|
-
opts = local_assigns.fetch(:options, [])
|
|
23
|
-
placeholder = local_assigns.fetch(:placeholder, nil)
|
|
24
|
-
select_id = local_assigns.fetch(:id, "select-#{SecureRandom.hex(4)}")
|
|
25
|
-
name = local_assigns.fetch(:name, nil)
|
|
26
|
-
disabled = local_assigns.fetch(:disabled, false)
|
|
27
|
-
classes = local_assigns.fetch(:class, "")
|
|
28
|
-
|
|
29
|
-
css = ["nano-select"]
|
|
30
|
-
css << "nano-select--error" if error
|
|
31
|
-
css << classes if classes.present?
|
|
32
|
-
error_id = "#{select_id}-error" if error
|
|
33
|
-
select_attributes = {
|
|
34
|
-
id: select_id,
|
|
35
|
-
class: css.join(" ")
|
|
36
|
-
}
|
|
37
|
-
select_attributes[:name] = name if name
|
|
38
|
-
select_attributes[:required] = true if required
|
|
39
|
-
select_attributes[:disabled] = true if disabled
|
|
40
|
-
if error
|
|
41
|
-
select_attributes[:"aria-invalid"] = true
|
|
42
|
-
select_attributes[:"aria-describedby"] = error_id
|
|
43
|
-
end
|
|
44
|
-
%>
|
|
45
|
-
|
|
46
|
-
<div class="nano-field">
|
|
47
|
-
<% if label_text %>
|
|
48
|
-
<label for="<%= select_id %>" class="nano-label<%= " nano-label--required" if required %>"><%= label_text %></label>
|
|
49
|
-
<% end %>
|
|
50
|
-
|
|
51
|
-
<%= content_tag(:select, select_attributes) do %>
|
|
52
|
-
<% if placeholder %>
|
|
53
|
-
<option value="" disabled selected><%= placeholder %></option>
|
|
54
|
-
<% end %>
|
|
55
|
-
<% opts.each do |opt| %>
|
|
56
|
-
<% if opt.is_a?(Hash) %>
|
|
57
|
-
<option value="<%= opt[:value] %>"><%= opt[:label] %></option>
|
|
58
|
-
<% else %>
|
|
59
|
-
<option><%= opt %></option>
|
|
60
|
-
<% end %>
|
|
61
|
-
<% end %>
|
|
62
|
-
<% end %>
|
|
63
|
-
|
|
64
|
-
<% if error %>
|
|
65
|
-
<p id="<%= error_id %>" class="nano-field__error" role="alert"><%= error %></p>
|
|
66
|
-
<% end %>
|
|
67
|
-
</div>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Switch
|
|
2
|
-
Options: checked (false), disabled (false), label (sr-only text), class, html
|
|
3
|
-
Usage:
|
|
4
|
-
render "components/switch", label: "Enable notifications"
|
|
5
|
-
render "components/switch", label: "Dark mode", checked: true
|
|
6
|
-
%>
|
|
7
|
-
<%
|
|
8
|
-
checked = local_assigns.fetch(:checked, false)
|
|
9
|
-
disabled = local_assigns.fetch(:disabled, false)
|
|
10
|
-
label = local_assigns.fetch(:label, "Toggle")
|
|
11
|
-
classes = local_assigns.fetch(:class, "")
|
|
12
|
-
html = local_assigns.fetch(:html, {}).symbolize_keys
|
|
13
|
-
|
|
14
|
-
css = "nano-switch"
|
|
15
|
-
css += " #{classes}" if classes.present?
|
|
16
|
-
switch_attributes = {
|
|
17
|
-
type: "button",
|
|
18
|
-
role: "switch",
|
|
19
|
-
:"aria-checked" => checked,
|
|
20
|
-
class: css.strip,
|
|
21
|
-
data: {
|
|
22
|
-
controller: "nanoui-switch",
|
|
23
|
-
action: "nanoui-switch#toggle"
|
|
24
|
-
}
|
|
25
|
-
}.merge(html)
|
|
26
|
-
switch_attributes[:disabled] = true if disabled
|
|
27
|
-
%>
|
|
28
|
-
|
|
29
|
-
<%= content_tag(:button, switch_attributes) do %>
|
|
30
|
-
<span class="nano-switch__thumb"></span>
|
|
31
|
-
<span class="nano-sr-only"><%= label %></span>
|
|
32
|
-
<% end %>
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Table
|
|
2
|
-
Variants: striped, hoverable
|
|
3
|
-
Options: headers (array of strings), striped (false), hoverable (false), class
|
|
4
|
-
Yields: default (tbody rows)
|
|
5
|
-
Usage:
|
|
6
|
-
render "components/table", headers: ["Name", "Email", "Status"], striped: true, hoverable: true do
|
|
7
|
-
'<tr class="nano-table__row">
|
|
8
|
-
<td class="nano-table__cell">Jane</td>
|
|
9
|
-
<td class="nano-table__cell">jane@example.com</td>
|
|
10
|
-
<td class="nano-table__cell">Active</td>
|
|
11
|
-
</tr>'.html_safe
|
|
12
|
-
end
|
|
13
|
-
%>
|
|
14
|
-
<%
|
|
15
|
-
headers = local_assigns.fetch(:headers, [])
|
|
16
|
-
striped = local_assigns.fetch(:striped, false)
|
|
17
|
-
hoverable = local_assigns.fetch(:hoverable, false)
|
|
18
|
-
classes = local_assigns.fetch(:class, "")
|
|
19
|
-
|
|
20
|
-
css = ["nano-table"]
|
|
21
|
-
css << "nano-table--striped" if striped
|
|
22
|
-
css << "nano-table--hoverable" if hoverable
|
|
23
|
-
css << classes if classes.present?
|
|
24
|
-
%>
|
|
25
|
-
|
|
26
|
-
<div class="nano-table-wrapper">
|
|
27
|
-
<table class="<%= css.join(" ").strip %>">
|
|
28
|
-
<% if headers.any? %>
|
|
29
|
-
<thead class="nano-table__head">
|
|
30
|
-
<tr>
|
|
31
|
-
<% headers.each do |h| %>
|
|
32
|
-
<th scope="col" class="nano-table__header"><%= h %></th>
|
|
33
|
-
<% end %>
|
|
34
|
-
</tr>
|
|
35
|
-
</thead>
|
|
36
|
-
<% end %>
|
|
37
|
-
<tbody class="nano-table__body">
|
|
38
|
-
<%= yield %>
|
|
39
|
-
</tbody>
|
|
40
|
-
</table>
|
|
41
|
-
</div>
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Tabs (WAI-ARIA tabs with Stimulus)
|
|
2
|
-
Options: tabs (array of {id:, label:, content:, active:}), label ("Tabs"), hash (false), class
|
|
3
|
-
Usage:
|
|
4
|
-
render "components/tabs", label: "Settings", tabs: [
|
|
5
|
-
{ id: "general", label: "General", content: "General settings...", active: true },
|
|
6
|
-
{ id: "security", label: "Security", content: "Security settings..." },
|
|
7
|
-
{ id: "billing", label: "Billing", content: "Billing info..." }
|
|
8
|
-
]
|
|
9
|
-
%>
|
|
10
|
-
<%
|
|
11
|
-
tabs_data = local_assigns.fetch(:tabs, [])
|
|
12
|
-
aria_label = local_assigns.fetch(:label, "Tabs")
|
|
13
|
-
hash = local_assigns.fetch(:hash, false)
|
|
14
|
-
classes = local_assigns.fetch(:class, "")
|
|
15
|
-
|
|
16
|
-
css = "nano-tabs"
|
|
17
|
-
css += " #{classes}" if classes.present?
|
|
18
|
-
%>
|
|
19
|
-
|
|
20
|
-
<div class="<%= css.strip %>"
|
|
21
|
-
data-controller="nanoui-tabs"
|
|
22
|
-
data-nanoui-tabs-hash-value="<%= hash %>">
|
|
23
|
-
<div role="tablist" class="nano-tabs__list" aria-label="<%= aria_label %>">
|
|
24
|
-
<% tabs_data.each_with_index do |tab, i| %>
|
|
25
|
-
<button role="tab"
|
|
26
|
-
id="tab-<%= tab[:id] %>"
|
|
27
|
-
class="nano-tabs__trigger"
|
|
28
|
-
aria-selected="<%= tab[:active] ? "true" : "false" %>"
|
|
29
|
-
aria-controls="panel-<%= tab[:id] %>"
|
|
30
|
-
<%= "tabindex=\"-1\"" unless tab[:active] %>
|
|
31
|
-
data-action="nanoui-tabs#select keydown->nanoui-tabs#navigate"
|
|
32
|
-
data-nanoui-tabs-target="tab"><%= tab[:label] %></button>
|
|
33
|
-
<% end %>
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
<% tabs_data.each do |tab| %>
|
|
37
|
-
<div role="tabpanel"
|
|
38
|
-
id="panel-<%= tab[:id] %>"
|
|
39
|
-
class="nano-tabs__panel"
|
|
40
|
-
aria-labelledby="tab-<%= tab[:id] %>"
|
|
41
|
-
data-nanoui-tabs-target="panel"
|
|
42
|
-
<%= "hidden" unless tab[:active] %>>
|
|
43
|
-
<%= tab[:content] if tab[:content] %>
|
|
44
|
-
</div>
|
|
45
|
-
<% end %>
|
|
46
|
-
</div>
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Toast (single toast item, placed inside .nano-toast-container)
|
|
2
|
-
Variants: default, success, destructive, warning
|
|
3
|
-
Options: variant, title, description, class
|
|
4
|
-
Usage:
|
|
5
|
-
render "components/toast", variant: "success", title: "Saved!", description: "Changes applied."
|
|
6
|
-
%>
|
|
7
|
-
<%
|
|
8
|
-
variant = local_assigns.fetch(:variant, nil)
|
|
9
|
-
title = local_assigns.fetch(:title, "")
|
|
10
|
-
desc = local_assigns.fetch(:description, nil)
|
|
11
|
-
classes = local_assigns.fetch(:class, "")
|
|
12
|
-
|
|
13
|
-
css = ["nano-toast"]
|
|
14
|
-
css << "nano-toast--#{variant}" if variant
|
|
15
|
-
css << classes if classes.present?
|
|
16
|
-
%>
|
|
17
|
-
|
|
18
|
-
<output class="<%= css.join(" ").strip %>" role="status" data-nanoui-toast-target="item">
|
|
19
|
-
<div class="nano-toast__content">
|
|
20
|
-
<p class="nano-toast__title"><%= title %></p>
|
|
21
|
-
<% if desc %>
|
|
22
|
-
<p class="nano-toast__description"><%= desc %></p>
|
|
23
|
-
<% end %>
|
|
24
|
-
</div>
|
|
25
|
-
<button class="nano-toast__close" data-action="nanoui-toast#dismiss"
|
|
26
|
-
type="button" aria-label="Dismiss notification">
|
|
27
|
-
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="14" height="14"
|
|
28
|
-
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
29
|
-
stroke-linecap="round" stroke-linejoin="round">
|
|
30
|
-
<path d="M18 6 6 18"/><path d="m6 6 12 12"/>
|
|
31
|
-
</svg>
|
|
32
|
-
</button>
|
|
33
|
-
</output>
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Toast Container (place once in your layout)
|
|
2
|
-
Options: duration (5000ms auto-dismiss), class
|
|
3
|
-
Usage (in application.html.erb):
|
|
4
|
-
render "components/toast_container"
|
|
5
|
-
%>
|
|
6
|
-
<%
|
|
7
|
-
duration = local_assigns.fetch(:duration, 5000)
|
|
8
|
-
classes = local_assigns.fetch(:class, "")
|
|
9
|
-
css = "nano-toast-container"
|
|
10
|
-
css += " #{classes}" if classes.present?
|
|
11
|
-
%>
|
|
12
|
-
|
|
13
|
-
<div class="<%= css.strip %>"
|
|
14
|
-
data-controller="nanoui-toast"
|
|
15
|
-
data-nanoui-toast-duration-value="<%= duration %>"
|
|
16
|
-
aria-live="polite">
|
|
17
|
-
</div>
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
<%# NanoUI Tooltip (Stimulus-powered)
|
|
2
|
-
Options: text, position (top, bottom, left, right), delay (200), class
|
|
3
|
-
Yields: default (trigger content)
|
|
4
|
-
Usage:
|
|
5
|
-
render "components/tooltip", text: "Add to favorites", position: "top" do
|
|
6
|
-
render "components/button", variant: "primary", size: "icon" do
|
|
7
|
-
'<svg>...</svg>'.html_safe
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
%>
|
|
11
|
-
<%
|
|
12
|
-
text = local_assigns.fetch(:text, "")
|
|
13
|
-
position = local_assigns.fetch(:position, "top")
|
|
14
|
-
delay = local_assigns.fetch(:delay, 200)
|
|
15
|
-
classes = local_assigns.fetch(:class, "")
|
|
16
|
-
|
|
17
|
-
css = ["nano-tooltip"]
|
|
18
|
-
css << "nano-tooltip--#{position}" unless position == "top"
|
|
19
|
-
css << classes if classes.present?
|
|
20
|
-
%>
|
|
21
|
-
|
|
22
|
-
<div class="<%= css.join(" ").strip %>"
|
|
23
|
-
data-controller="nanoui-tooltip"
|
|
24
|
-
data-nanoui-tooltip-delay-value="<%= delay %>"
|
|
25
|
-
data-action="mouseenter->nanoui-tooltip#show mouseleave->nanoui-tooltip#hide focusin->nanoui-tooltip#show focusout->nanoui-tooltip#hide">
|
|
26
|
-
<%= yield %>
|
|
27
|
-
<div class="nano-tooltip__content" role="tooltip" data-nanoui-tooltip-target="content"><%= text %></div>
|
|
28
|
-
</div>
|