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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/README.md +189 -199
  4. data/lib/generators/nanoui/component_generator.rb +0 -52
  5. data/lib/generators/nanoui/install_generator.rb +0 -18
  6. data/lib/generators/nanoui/templates/css/components/alert.css +1 -1
  7. data/lib/generators/nanoui/templates/css/components/button.css +36 -7
  8. data/lib/generators/nanoui/templates/css/components/card.css +2 -1
  9. data/lib/generators/nanoui/templates/css/components/dialog.css +1 -1
  10. data/lib/generators/nanoui/templates/css/components/input.css +62 -8
  11. data/lib/generators/nanoui/templates/css/components/label.css +2 -1
  12. data/lib/generators/nanoui/templates/css/components/select.css +12 -7
  13. data/lib/nanoui/version.rb +1 -1
  14. metadata +1 -22
  15. data/lib/generators/nanoui/templates/css/nanoui.css +0 -33
  16. data/lib/generators/nanoui/templates/css/nanoui.install.css +0 -15
  17. data/lib/generators/nanoui/templates/views/components/_accordion.html.erb +0 -40
  18. data/lib/generators/nanoui/templates/views/components/_alert.html.erb +0 -33
  19. data/lib/generators/nanoui/templates/views/components/_badge.html.erb +0 -18
  20. data/lib/generators/nanoui/templates/views/components/_button.html.erb +0 -27
  21. data/lib/generators/nanoui/templates/views/components/_card.html.erb +0 -43
  22. data/lib/generators/nanoui/templates/views/components/_checkbox.html.erb +0 -36
  23. data/lib/generators/nanoui/templates/views/components/_dialog.html.erb +0 -65
  24. data/lib/generators/nanoui/templates/views/components/_dropdown.html.erb +0 -29
  25. data/lib/generators/nanoui/templates/views/components/_input.html.erb +0 -42
  26. data/lib/generators/nanoui/templates/views/components/_label.html.erb +0 -20
  27. data/lib/generators/nanoui/templates/views/components/_progress.html.erb +0 -29
  28. data/lib/generators/nanoui/templates/views/components/_radio_group.html.erb +0 -46
  29. data/lib/generators/nanoui/templates/views/components/_select.html.erb +0 -67
  30. data/lib/generators/nanoui/templates/views/components/_switch.html.erb +0 -32
  31. data/lib/generators/nanoui/templates/views/components/_table.html.erb +0 -41
  32. data/lib/generators/nanoui/templates/views/components/_tabs.html.erb +0 -46
  33. data/lib/generators/nanoui/templates/views/components/_toast.html.erb +0 -33
  34. data/lib/generators/nanoui/templates/views/components/_toast_container.html.erb +0 -17
  35. data/lib/generators/nanoui/templates/views/components/_tooltip.html.erb +0 -28
@@ -23,7 +23,6 @@ module Nanoui
23
23
  accordion
24
24
  progress
25
25
  ].freeze
26
- COMPONENT_IMPORT_PATTERN = /^\s*@import "components\/_?([^\"]+)\.css";\s*\n?/
27
26
 
28
27
  argument :components, type: :array, default: [], banner: "component [component] ..."
29
28
 
@@ -38,12 +37,6 @@ module Nanoui
38
37
  }.freeze
39
38
 
40
39
  STIMULUS_COMPONENTS = %w[dialog dropdown tooltip toast tabs accordion switch].freeze
41
- PARTIAL_TEMPLATES = COMPONENT_ORDER.each_with_object({}) do |name, partials|
42
- partials[name] = [name]
43
- end.merge(
44
- "radio" => %w[radio_group],
45
- "toast" => %w[toast toast_container]
46
- ).freeze
47
40
 
48
41
  def resolve_components
49
42
  @resolved = if options[:all]
@@ -72,34 +65,6 @@ module Nanoui
72
65
  end
73
66
  end
74
67
 
75
- def copy_partials
76
- @resolved.each do |name|
77
- PARTIAL_TEMPLATES.fetch(name, [name]).each do |partial_name|
78
- source = "views/components/_#{partial_name}.html.erb"
79
- next unless File.exist?(File.join(self.class.source_root, source))
80
-
81
- copy_file source, "app/views/components/_#{partial_name}.html.erb"
82
- end
83
- end
84
- end
85
-
86
- def update_nanoui_css
87
- nanoui_css = "app/assets/stylesheets/nanoui/nanoui.css"
88
- return unless File.exist?(nanoui_css)
89
-
90
- content = File.read(nanoui_css)
91
- content_without_component_imports = content.gsub(COMPONENT_IMPORT_PATTERN, "")
92
- component_section = ["/* Components */", component_imports].reject(&:empty?).join("\n")
93
-
94
- updated_content = if content_without_component_imports.include?("/* Components */")
95
- content_without_component_imports.sub("/* Components */", component_section)
96
- else
97
- "#{content_without_component_imports.rstrip}\n\n#{component_section}\n"
98
- end
99
-
100
- File.write(nanoui_css, updated_content)
101
- end
102
-
103
68
  def print_summary
104
69
  say ""
105
70
  say "NanoUI components installed:", :green
@@ -110,23 +75,6 @@ module Nanoui
110
75
  end
111
76
  say ""
112
77
  end
113
-
114
- private
115
-
116
- def component_imports
117
- installed_components.map { |name| "@import \"components/#{name}.css\";" }.join("\n")
118
- end
119
-
120
- def installed_components
121
- component_dir = "app/assets/stylesheets/nanoui/components"
122
- names = Dir.glob(File.join(component_dir, "*.css")).map do |path|
123
- File.basename(path, ".css").delete_prefix("_")
124
- end
125
-
126
- names.uniq.sort_by do |name|
127
- [COMPONENT_ORDER.index(name) || COMPONENT_ORDER.length, name]
128
- end
129
- end
130
78
  end
131
79
  end
132
80
  end
@@ -3,34 +3,16 @@ module Nanoui
3
3
  class InstallGenerator < Rails::Generators::Base
4
4
  source_root File.expand_path("templates", __dir__)
5
5
 
6
- APPLICATION_IMPORT = '@import "nanoui/nanoui.css";'.freeze
7
- LEADING_CSS_HEADER_PATTERN = /\A((?:\s|\/\*.*?\*\/\s*)*(?:@charset\s+[^;]+;\s*)?(?:@import\s+[^;]+;\s*)*)/m.freeze
8
-
9
6
  desc "Install NanoUI foundation (base styles, fonts)"
10
7
 
11
8
  def copy_base
12
9
  directory "css/base", "app/assets/stylesheets/nanoui/base"
13
10
  end
14
11
 
15
- def copy_entry_point
16
- copy_file "css/nanoui.install.css", "app/assets/stylesheets/nanoui/nanoui.css"
17
- end
18
-
19
12
  def copy_fonts
20
13
  directory "css/fonts", "app/assets/stylesheets/nanoui/fonts"
21
14
  end
22
15
 
23
- def add_import_to_application_css
24
- application_css = "app/assets/stylesheets/application.css"
25
- return unless File.exist?(application_css)
26
-
27
- content = File.read(application_css)
28
- return if content.include?(APPLICATION_IMPORT)
29
-
30
- updated_content = content.sub(LEADING_CSS_HEADER_PATTERN, "\\1#{APPLICATION_IMPORT}\n")
31
- File.write(application_css, updated_content)
32
- end
33
-
34
16
  def print_instructions
35
17
  say ""
36
18
  say "NanoUI installed!", :green
@@ -35,7 +35,7 @@
35
35
  .nano-alert__description {
36
36
  font-size: var(--text-sm);
37
37
  line-height: var(--leading-normal);
38
- color: hsl(var(--color-muted-foreground));
38
+ color: hsl(var(--color-foreground));
39
39
  }
40
40
 
41
41
  .nano-alert--destructive {
@@ -1,4 +1,8 @@
1
- .nano-btn {
1
+ .nano-btn,
2
+ button,
3
+ input[type="submit"],
4
+ input[type="button"],
5
+ input[type="reset"] {
2
6
  display: inline-flex;
3
7
  align-items: center;
4
8
  justify-content: center;
@@ -13,15 +17,34 @@
13
17
  transition: background-color var(--duration-fast) var(--ease-default),
14
18
  color var(--duration-fast) var(--ease-default);
15
19
  padding: var(--space-2-5) var(--space-4);
20
+ background-color: hsl(var(--color-primary));
21
+ color: hsl(var(--color-primary-foreground));
16
22
  }
17
23
 
18
- .nano-btn:focus-visible {
24
+ .nano-btn:hover,
25
+ button:hover,
26
+ input[type="submit"]:hover,
27
+ input[type="button"]:hover,
28
+ input[type="reset"]:hover {
29
+ background-color: hsl(var(--color-primary) / 0.9);
30
+ }
31
+
32
+ .nano-btn:focus-visible,
33
+ button:focus-visible,
34
+ input[type="submit"]:focus-visible,
35
+ input[type="button"]:focus-visible,
36
+ input[type="reset"]:focus-visible {
19
37
  outline: 2px solid hsl(var(--color-ring));
20
38
  outline-offset: 2px;
21
39
  }
22
40
 
23
41
  .nano-btn:disabled,
24
- .nano-btn[aria-disabled="true"] {
42
+ .nano-btn[aria-disabled="true"],
43
+ button:disabled,
44
+ button[aria-disabled="true"],
45
+ input[type="submit"]:disabled,
46
+ input[type="button"]:disabled,
47
+ input[type="reset"]:disabled {
25
48
  pointer-events: none;
26
49
  opacity: 0.5;
27
50
  }
@@ -38,10 +61,11 @@
38
61
  .nano-btn--secondary {
39
62
  background-color: hsl(var(--color-secondary));
40
63
  color: hsl(var(--color-secondary-foreground));
64
+ border: 1px solid hsl(var(--color-border));
41
65
  }
42
66
 
43
67
  .nano-btn--secondary:hover {
44
- background-color: hsl(var(--color-secondary) / 0.8);
68
+ background-color: hsl(var(--color-muted-foreground) / 0.15);
45
69
  }
46
70
 
47
71
  .nano-btn--destructive {
@@ -75,13 +99,14 @@
75
99
  .nano-btn--link {
76
100
  background-color: transparent;
77
101
  color: hsl(var(--color-primary));
78
- text-decoration: underline;
102
+ text-decoration: underline dashed;
79
103
  text-underline-offset: 4px;
80
104
  padding: 0;
81
105
  }
82
106
 
83
107
  .nano-btn--link:hover {
84
- text-decoration-thickness: 2px;
108
+ background-color: transparent;
109
+ text-decoration-style: solid;
85
110
  }
86
111
 
87
112
  .nano-btn--sm {
@@ -109,7 +134,11 @@
109
134
  to { transform: rotate(360deg); }
110
135
  }
111
136
 
112
- .nano-btn svg {
137
+ .nano-btn svg,
138
+ button svg,
139
+ input[type="submit"] svg,
140
+ input[type="button"] svg,
141
+ input[type="reset"] svg {
113
142
  width: 1em;
114
143
  height: 1em;
115
144
  flex-shrink: 0;
@@ -33,7 +33,7 @@
33
33
 
34
34
  .nano-card__description {
35
35
  font-size: var(--text-sm);
36
- color: hsl(var(--color-muted-foreground));
36
+ color: hsl(var(--color-foreground));
37
37
  }
38
38
 
39
39
  .nano-card__content {
@@ -43,6 +43,7 @@
43
43
  .nano-card__footer {
44
44
  display: flex;
45
45
  align-items: center;
46
+ gap: var(--space-2);
46
47
  padding: var(--space-6);
47
48
  padding-top: 0;
48
49
  }
@@ -58,6 +58,7 @@
58
58
  gap: var(--space-1-5);
59
59
  padding: var(--space-6);
60
60
  padding-bottom: 0;
61
+ padding-right: var(--space-12);
61
62
  }
62
63
 
63
64
  .nano-dialog__title {
@@ -82,7 +83,6 @@
82
83
  justify-content: flex-end;
83
84
  gap: var(--space-2);
84
85
  padding: var(--space-6);
85
- padding-top: 0;
86
86
  }
87
87
 
88
88
  .nano-dialog__close {
@@ -1,4 +1,17 @@
1
- .nano-input {
1
+ .nano-input,
2
+ input[type="text"],
3
+ input[type="email"],
4
+ input[type="password"],
5
+ input[type="search"],
6
+ input[type="tel"],
7
+ input[type="url"],
8
+ input[type="number"],
9
+ input[type="date"],
10
+ input[type="datetime-local"],
11
+ input[type="month"],
12
+ input[type="week"],
13
+ input[type="time"],
14
+ textarea {
2
15
  display: block;
3
16
  width: 100%;
4
17
  padding: var(--space-2) var(--space-3);
@@ -13,17 +26,56 @@
13
26
  box-shadow var(--duration-fast) var(--ease-default);
14
27
  }
15
28
 
16
- .nano-input::placeholder {
29
+ .nano-input::placeholder,
30
+ input[type="text"]::placeholder,
31
+ input[type="email"]::placeholder,
32
+ input[type="password"]::placeholder,
33
+ input[type="search"]::placeholder,
34
+ input[type="tel"]::placeholder,
35
+ input[type="url"]::placeholder,
36
+ input[type="number"]::placeholder,
37
+ input[type="date"]::placeholder,
38
+ input[type="datetime-local"]::placeholder,
39
+ input[type="month"]::placeholder,
40
+ input[type="week"]::placeholder,
41
+ input[type="time"]::placeholder,
42
+ textarea::placeholder {
17
43
  color: hsl(var(--color-muted-foreground));
18
44
  }
19
45
 
20
- .nano-input:focus {
21
- outline: none;
46
+ .nano-input:focus,
47
+ input[type="text"]:focus,
48
+ input[type="email"]:focus,
49
+ input[type="password"]:focus,
50
+ input[type="search"]:focus,
51
+ input[type="tel"]:focus,
52
+ input[type="url"]:focus,
53
+ input[type="number"]:focus,
54
+ input[type="date"]:focus,
55
+ input[type="datetime-local"]:focus,
56
+ input[type="month"]:focus,
57
+ input[type="week"]:focus,
58
+ input[type="time"]:focus,
59
+ textarea:focus {
22
60
  border-color: hsl(var(--color-input-focus));
23
- box-shadow: 0 0 0 2px hsl(var(--color-ring) / 0.2);
61
+ outline: 2px solid hsl(var(--color-input-focus));
62
+ outline-offset: -1px;
24
63
  }
25
64
 
26
- .nano-input:disabled {
65
+ .nano-input:disabled,
66
+ input[type="text"]:disabled,
67
+ input[type="email"]:disabled,
68
+ input[type="password"]:disabled,
69
+ input[type="search"]:disabled,
70
+ input[type="tel"]:disabled,
71
+ input[type="url"]:disabled,
72
+ input[type="number"]:disabled,
73
+ input[type="date"]:disabled,
74
+ input[type="datetime-local"]:disabled,
75
+ input[type="month"]:disabled,
76
+ input[type="week"]:disabled,
77
+ input[type="time"]:disabled,
78
+ textarea:disabled {
27
79
  opacity: 0.5;
28
80
  cursor: not-allowed;
29
81
  }
@@ -36,10 +88,12 @@
36
88
  .nano-input--error:focus,
37
89
  .nano-input[aria-invalid="true"]:focus {
38
90
  border-color: hsl(var(--color-destructive));
39
- box-shadow: 0 0 0 2px hsl(var(--color-destructive) / 0.2);
91
+ outline: 2px solid hsl(var(--color-destructive));
92
+ outline-offset: -1px;
40
93
  }
41
94
 
42
- textarea.nano-input {
95
+ textarea.nano-input,
96
+ textarea {
43
97
  min-height: 5rem;
44
98
  resize: vertical;
45
99
  }
@@ -1,4 +1,5 @@
1
- .nano-label {
1
+ .nano-label,
2
+ label {
2
3
  font-size: var(--text-sm);
3
4
  font-weight: var(--font-medium);
4
5
  line-height: var(--leading-none);
@@ -1,4 +1,5 @@
1
- .nano-select {
1
+ .nano-select,
2
+ select {
2
3
  display: block;
3
4
  width: 100%;
4
5
  padding: var(--space-2) var(--space-8) var(--space-2) var(--space-3);
@@ -18,13 +19,15 @@
18
19
  box-shadow var(--duration-fast) var(--ease-default);
19
20
  }
20
21
 
21
- .nano-select:focus {
22
- outline: none;
22
+ .nano-select:focus,
23
+ select:focus {
23
24
  border-color: hsl(var(--color-input-focus));
24
- box-shadow: 0 0 0 2px hsl(var(--color-ring) / 0.2);
25
+ outline: 2px solid hsl(var(--color-input-focus));
26
+ outline-offset: -1px;
25
27
  }
26
28
 
27
- .nano-select:disabled {
29
+ .nano-select:disabled,
30
+ select:disabled {
28
31
  opacity: 0.5;
29
32
  cursor: not-allowed;
30
33
  }
@@ -37,9 +40,11 @@
37
40
  .nano-select--error:focus,
38
41
  .nano-select[aria-invalid="true"]:focus {
39
42
  border-color: hsl(var(--color-destructive));
40
- box-shadow: 0 0 0 2px hsl(var(--color-destructive) / 0.2);
43
+ outline: 2px solid hsl(var(--color-destructive));
44
+ outline-offset: -1px;
41
45
  }
42
46
 
43
- .dark .nano-select {
47
+ .dark .nano-select,
48
+ .dark select {
44
49
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
45
50
  }
@@ -1,3 +1,3 @@
1
1
  module Nanoui
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nanoui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Omerovic
@@ -79,8 +79,6 @@ files:
79
79
  - lib/generators/nanoui/templates/css/components/toast.css
80
80
  - lib/generators/nanoui/templates/css/components/tooltip.css
81
81
  - lib/generators/nanoui/templates/css/fonts/inter-variable.ttf
82
- - lib/generators/nanoui/templates/css/nanoui.css
83
- - lib/generators/nanoui/templates/css/nanoui.install.css
84
82
  - lib/generators/nanoui/templates/js/controllers/accordion_controller.js
85
83
  - lib/generators/nanoui/templates/js/controllers/dialog_controller.js
86
84
  - lib/generators/nanoui/templates/js/controllers/dropdown_controller.js
@@ -88,25 +86,6 @@ files:
88
86
  - lib/generators/nanoui/templates/js/controllers/tabs_controller.js
89
87
  - lib/generators/nanoui/templates/js/controllers/toast_controller.js
90
88
  - lib/generators/nanoui/templates/js/controllers/tooltip_controller.js
91
- - lib/generators/nanoui/templates/views/components/_accordion.html.erb
92
- - lib/generators/nanoui/templates/views/components/_alert.html.erb
93
- - lib/generators/nanoui/templates/views/components/_badge.html.erb
94
- - lib/generators/nanoui/templates/views/components/_button.html.erb
95
- - lib/generators/nanoui/templates/views/components/_card.html.erb
96
- - lib/generators/nanoui/templates/views/components/_checkbox.html.erb
97
- - lib/generators/nanoui/templates/views/components/_dialog.html.erb
98
- - lib/generators/nanoui/templates/views/components/_dropdown.html.erb
99
- - lib/generators/nanoui/templates/views/components/_input.html.erb
100
- - lib/generators/nanoui/templates/views/components/_label.html.erb
101
- - lib/generators/nanoui/templates/views/components/_progress.html.erb
102
- - lib/generators/nanoui/templates/views/components/_radio_group.html.erb
103
- - lib/generators/nanoui/templates/views/components/_select.html.erb
104
- - lib/generators/nanoui/templates/views/components/_switch.html.erb
105
- - lib/generators/nanoui/templates/views/components/_table.html.erb
106
- - lib/generators/nanoui/templates/views/components/_tabs.html.erb
107
- - lib/generators/nanoui/templates/views/components/_toast.html.erb
108
- - lib/generators/nanoui/templates/views/components/_toast_container.html.erb
109
- - lib/generators/nanoui/templates/views/components/_tooltip.html.erb
110
89
  - lib/nanoui.rb
111
90
  - lib/nanoui/version.rb
112
91
  homepage: https://github.com/chille1987/nanoui
@@ -1,33 +0,0 @@
1
- /* NanoUI — Vanilla CSS + Stimulus Component Library */
2
-
3
- /* Base */
4
- @import "base/01_reset.css";
5
- @import "base/02_fonts.css";
6
- @import "base/03_colors.css";
7
- @import "base/04_typography.css";
8
- @import "base/05_spacing.css";
9
- @import "base/06_radius.css";
10
- @import "base/07_shadows.css";
11
- @import "base/08_transitions.css";
12
- @import "base/09_z-index.css";
13
- @import "base/10_globals.css";
14
-
15
- /* Components */
16
- @import "components/button.css";
17
- @import "components/input.css";
18
- @import "components/label.css";
19
- @import "components/card.css";
20
- @import "components/checkbox.css";
21
- @import "components/radio.css";
22
- @import "components/switch.css";
23
- @import "components/select.css";
24
- @import "components/badge.css";
25
- @import "components/alert.css";
26
- @import "components/dialog.css";
27
- @import "components/dropdown.css";
28
- @import "components/tooltip.css";
29
- @import "components/toast.css";
30
- @import "components/table.css";
31
- @import "components/tabs.css";
32
- @import "components/accordion.css";
33
- @import "components/progress.css";
@@ -1,15 +0,0 @@
1
- /* NanoUI — Vanilla CSS + Stimulus Component Library */
2
-
3
- /* Base */
4
- @import "base/01_reset.css";
5
- @import "base/02_fonts.css";
6
- @import "base/03_colors.css";
7
- @import "base/04_typography.css";
8
- @import "base/05_spacing.css";
9
- @import "base/06_radius.css";
10
- @import "base/07_shadows.css";
11
- @import "base/08_transitions.css";
12
- @import "base/09_z-index.css";
13
- @import "base/10_globals.css";
14
-
15
- /* Components */
@@ -1,40 +0,0 @@
1
- <%# NanoUI Accordion (native <details>/<summary> with Stimulus)
2
- Options: items (array of {title:, content:, open:}), single (false), class
3
- Usage:
4
- render "components/accordion", single: true, items: [
5
- { title: "Is it free?", content: "Yes, MIT licensed.", open: true },
6
- { title: "Build step?", content: "No, vanilla CSS." },
7
- { title: "Dark mode?", content: "Add .dark class to html." }
8
- ]
9
- %>
10
- <%
11
- items = local_assigns.fetch(:items, [])
12
- single = local_assigns.fetch(:single, false)
13
- classes = local_assigns.fetch(:class, "")
14
-
15
- css = "nano-accordion"
16
- css += " #{classes}" if classes.present?
17
- %>
18
-
19
- <div class="<%= css.strip %>"
20
- data-controller="nanoui-accordion"
21
- data-nanoui-accordion-single-value="<%= single %>">
22
- <% items.each do |item| %>
23
- <details class="nano-accordion__item"
24
- data-nanoui-accordion-target="item"
25
- data-action="toggle->nanoui-accordion#toggle"
26
- <%= "open" if item[:open] %>>
27
- <summary class="nano-accordion__trigger">
28
- <span><%= item[:title] %></span>
29
- <svg class="nano-accordion__icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16"
30
- viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
31
- stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
32
- <path d="m6 9 6 6 6-6"/>
33
- </svg>
34
- </summary>
35
- <div class="nano-accordion__content">
36
- <p><%= item[:content] %></p>
37
- </div>
38
- </details>
39
- <% end %>
40
- </div>
@@ -1,33 +0,0 @@
1
- <%# NanoUI Alert
2
- Variants: default, destructive, success, warning
3
- Options: variant, title, icon, class
4
- Usage:
5
- render "components/alert", variant: "success", title: "Saved!" do
6
- "Your changes have been saved."
7
- end
8
- %>
9
- <%
10
- variant = local_assigns.fetch(:variant, nil)
11
- title = local_assigns.fetch(:title, nil)
12
- icon = local_assigns.fetch(:icon, nil)
13
- classes = local_assigns.fetch(:class, "")
14
-
15
- css = ["nano-alert"]
16
- css << "nano-alert--#{variant}" if variant
17
- css << classes if classes.present?
18
- %>
19
-
20
- <div class="<%= css.join(" ").strip %>" role="alert">
21
- <% if icon %>
22
- <div class="nano-alert__icon">
23
- <%= icon %>
24
- </div>
25
- <% end %>
26
-
27
- <div class="nano-alert__content">
28
- <% if title %>
29
- <p class="nano-alert__title"><%= title %></p>
30
- <% end %>
31
- <p class="nano-alert__description"><%= yield %></p>
32
- </div>
33
- </div>
@@ -1,18 +0,0 @@
1
- <%# NanoUI Badge
2
- Variants: primary (default), secondary, destructive, outline, success, warning
3
- Options: variant, class, html
4
- Usage:
5
- render "components/badge", variant: "success" do "Active" end
6
- %>
7
- <%
8
- variant = local_assigns.fetch(:variant, "primary")
9
- classes = local_assigns.fetch(:class, "")
10
- html = local_assigns.fetch(:html, {}).symbolize_keys
11
-
12
- css = "nano-badge nano-badge--#{variant}"
13
- css += " #{classes}" if classes.present?
14
- %>
15
-
16
- <%= content_tag(:span, { class: css.strip }.merge(html)) do %>
17
- <%= yield %>
18
- <% end %>
@@ -1,27 +0,0 @@
1
- <%# NanoUI Button
2
- Variants: primary (default), secondary, destructive, outline, ghost, link
3
- Sizes: sm, md (default), lg, icon
4
- Options: tag (:button), href (auto-switches to :a), class, html (extra attrs)
5
- Usage:
6
- render "components/button", variant: "primary" do "Save" end
7
- render "components/button", variant: "outline", size: "sm" do "Cancel" end
8
- render "components/button", href: "/about" do "Learn More" end
9
- %>
10
- <%
11
- variant = local_assigns.fetch(:variant, "primary")
12
- size = local_assigns.fetch(:size, nil)
13
- tag = local_assigns.fetch(:tag, :button)
14
- href = local_assigns.fetch(:href, nil)
15
- classes = local_assigns.fetch(:class, "")
16
- html = local_assigns.fetch(:html, {}).symbolize_keys
17
-
18
- css = ["nano-btn", "nano-btn--#{variant}"]
19
- css << "nano-btn--#{size}" if size
20
- css << classes if classes.present?
21
- tag = :a if href
22
- html[:type] = "button" if tag == :button && !html.key?(:type)
23
- %>
24
-
25
- <%= content_tag(tag, href: href, class: css.join(" ").strip, **html) do %>
26
- <%= yield %>
27
- <% end %>
@@ -1,43 +0,0 @@
1
- <%# NanoUI Card
2
- Variants: default, elevated, bordered
3
- Options: variant, tag (:article), title, description, footer, class, html
4
- Usage:
5
- render "components/card",
6
- title: "My Card",
7
- description: "Subtitle",
8
- footer: render("components/button", variant: "primary") { "Save" } do
9
- "Card body content"
10
- end
11
- %>
12
- <%
13
- variant = local_assigns.fetch(:variant, nil)
14
- tag = local_assigns.fetch(:tag, :article)
15
- title = local_assigns.fetch(:title, nil)
16
- desc = local_assigns.fetch(:description, nil)
17
- footer = local_assigns.fetch(:footer, nil)
18
- classes = local_assigns.fetch(:class, "")
19
- html = local_assigns.fetch(:html, {}).symbolize_keys
20
-
21
- css = ["nano-card"]
22
- css << "nano-card--#{variant}" if variant
23
- css << classes if classes.present?
24
- %>
25
-
26
- <%= content_tag(tag, class: css.join(" ").strip, **html) do %>
27
- <% if title || desc %>
28
- <div class="nano-card__header">
29
- <% if title %><h3 class="nano-card__title"><%= title %></h3><% end %>
30
- <% if desc %><p class="nano-card__description"><%= desc %></p><% end %>
31
- </div>
32
- <% end %>
33
-
34
- <div class="nano-card__content">
35
- <%= yield %>
36
- </div>
37
-
38
- <% if footer %>
39
- <div class="nano-card__footer">
40
- <%= footer %>
41
- </div>
42
- <% end %>
43
- <% end %>