orbital_ui 0.3.1

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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +224 -0
  4. data/app/assets/config/orbital_ui_manifest.js +2 -0
  5. data/app/assets/javascripts/orbital_ui/index.js +6 -0
  6. data/app/assets/javascripts/orbital_ui/index.js.map +1 -0
  7. data/app/assets/stylesheets/orbital_ui/index.css +3 -0
  8. data/app/assets/stylesheets/orbital_ui/index.css.map +1 -0
  9. data/app/assets/stylesheets/orbital_ui/theme.css +113 -0
  10. data/app/assets/stylesheets/orbital_ui/themes/blue.css +43 -0
  11. data/app/assets/stylesheets/orbital_ui/themes/green.css +43 -0
  12. data/app/assets/stylesheets/orbital_ui/themes/orange.css +43 -0
  13. data/app/assets/stylesheets/orbital_ui/themes/rose.css +43 -0
  14. data/app/assets/stylesheets/orbital_ui/themes/violet.css +43 -0
  15. data/app/components/orbital_ui/accordion/item.rb +32 -0
  16. data/app/components/orbital_ui/accordion.rb +23 -0
  17. data/app/components/orbital_ui/alert.rb +80 -0
  18. data/app/components/orbital_ui/avatar.rb +87 -0
  19. data/app/components/orbital_ui/badge.rb +28 -0
  20. data/app/components/orbital_ui/button.rb +46 -0
  21. data/app/components/orbital_ui/button_group.rb +20 -0
  22. data/app/components/orbital_ui/card/action.rb +17 -0
  23. data/app/components/orbital_ui/card/content.rb +17 -0
  24. data/app/components/orbital_ui/card/description.rb +17 -0
  25. data/app/components/orbital_ui/card/footer.rb +17 -0
  26. data/app/components/orbital_ui/card/header.rb +25 -0
  27. data/app/components/orbital_ui/card/title.rb +17 -0
  28. data/app/components/orbital_ui/card.rb +30 -0
  29. data/app/components/orbital_ui/check_box.rb +59 -0
  30. data/app/components/orbital_ui/component.rb +12 -0
  31. data/app/components/orbital_ui/concerns/icon_prop.rb +14 -0
  32. data/app/components/orbital_ui/confirmation_dialog.rb +142 -0
  33. data/app/components/orbital_ui/delete_dialog.rb +143 -0
  34. data/app/components/orbital_ui/dialog.rb +46 -0
  35. data/app/components/orbital_ui/dialog_frame.rb +17 -0
  36. data/app/components/orbital_ui/dropdown.rb +58 -0
  37. data/app/components/orbital_ui/expander.rb +20 -0
  38. data/app/components/orbital_ui/grid.rb +22 -0
  39. data/app/components/orbital_ui/heading.rb +65 -0
  40. data/app/components/orbital_ui/icon.rb +21 -0
  41. data/app/components/orbital_ui/image.rb +26 -0
  42. data/app/components/orbital_ui/inline_stack.rb +31 -0
  43. data/app/components/orbital_ui/kbd.rb +15 -0
  44. data/app/components/orbital_ui/kbd_group.rb +15 -0
  45. data/app/components/orbital_ui/menu/item.rb +74 -0
  46. data/app/components/orbital_ui/menu/label.rb +20 -0
  47. data/app/components/orbital_ui/menu/separator.rb +21 -0
  48. data/app/components/orbital_ui/menu/sub.rb +68 -0
  49. data/app/components/orbital_ui/menu.rb +36 -0
  50. data/app/components/orbital_ui/modal.rb +36 -0
  51. data/app/components/orbital_ui/modal_frame.rb +17 -0
  52. data/app/components/orbital_ui/navigation_menu.rb +51 -0
  53. data/app/components/orbital_ui/popcard.rb +18 -0
  54. data/app/components/orbital_ui/popover.rb +50 -0
  55. data/app/components/orbital_ui/progress_bar.rb +33 -0
  56. data/app/components/orbital_ui/prose.rb +15 -0
  57. data/app/components/orbital_ui/select.rb +140 -0
  58. data/app/components/orbital_ui/separator.rb +22 -0
  59. data/app/components/orbital_ui/spinner.rb +14 -0
  60. data/app/components/orbital_ui/stack.rb +29 -0
  61. data/app/components/orbital_ui/text.rb +41 -0
  62. data/app/components/orbital_ui/text_field.rb +132 -0
  63. data/app/components/orbital_ui/tooltip.rb +42 -0
  64. data/app/components/orbital_ui/typography.rb +38 -0
  65. data/lib/orbital_ui/attribute_utils.rb +152 -0
  66. data/lib/orbital_ui/components/attributes.rb +164 -0
  67. data/lib/orbital_ui/components/styles.rb +40 -0
  68. data/lib/orbital_ui/engine.rb +7 -0
  69. data/lib/orbital_ui/icons.rb +17312 -0
  70. data/lib/orbital_ui/type/any.rb +17 -0
  71. data/lib/orbital_ui/type/array.rb +27 -0
  72. data/lib/orbital_ui/type/breakpoints.rb +46 -0
  73. data/lib/orbital_ui/type/symbol.rb +17 -0
  74. data/lib/orbital_ui/version.rb +5 -0
  75. data/lib/orbital_ui.rb +49 -0
  76. metadata +162 -0
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Menu
5
+ class Item < Component
6
+ include OrbitalUi::Concerns::IconProp
7
+
8
+ attribute :url, :string, default: nil
9
+ attribute :disabled, :boolean, default: false
10
+ attribute :selected, :boolean, default: false
11
+ attribute :active, :boolean, default: false
12
+ attribute :destructive, :boolean, default: false
13
+ attribute :modal, :any, default: nil
14
+ attribute :shortcut, :string, default: nil
15
+ attribute :icon, :any, default: nil
16
+
17
+ renders_one :icon_slot, OrbitalUi::Icon
18
+
19
+ def call
20
+ content_tag tag_name, **html_attributes do
21
+ safe_join([
22
+ render_icon,
23
+ icon_slot,
24
+ content_tag(:span, content, class: "Orbital-Menu-Item-Content"),
25
+ (@shortcut ? render(OrbitalUi::Text.new(size: :sm, tone: :subdued)) { @shortcut } : nil),
26
+ check_icon
27
+ ].compact)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def check_icon
34
+ content_tag(
35
+ :svg,
36
+ class: "Orbital-Menu-Item-Check", width: "16", height: "16", viewBox: "0 0 24 24",
37
+ fill: "none", stroke: "currentColor", "stroke-width": "2",
38
+ "stroke-linecap": "round", "stroke-linejoin": "round"
39
+ ) do
40
+ tag.polyline(points: "20 6 9 17 4 12")
41
+ end
42
+ end
43
+
44
+ def tag_name
45
+ @url.present? ? :a : :button
46
+ end
47
+
48
+ def default_attributes
49
+ attrs = super.merge(
50
+ class: "Orbital-Menu-Item",
51
+ role: "menuitem",
52
+ tabindex: "-1",
53
+ "data-disabled": @disabled || nil,
54
+ "data-selected": @selected || nil,
55
+ "data-active": @active || nil,
56
+ "data-destructive": @destructive || nil,
57
+ "aria-disabled": @disabled ? "true" : nil,
58
+ "data-orbital-menu-target": "item"
59
+ )
60
+
61
+ attrs[:href] = @url if @url.present?
62
+ attrs[:type] = "button" unless @url.present?
63
+
64
+ if @modal.is_a?(String) && %w[true false].exclude?(@modal)
65
+ attrs["data-open-modal"] = @modal
66
+ elsif @modal && @url.present?
67
+ attrs["data-turbo-frame"] = OrbitalUi.configuration.dialog_portal_id
68
+ end
69
+
70
+ attrs
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Menu
5
+ class Label < Component
6
+ orb_template <<-ORB
7
+ <div **html_attributes>{{content}}</div>
8
+ ORB
9
+
10
+ private
11
+
12
+ def default_attributes
13
+ super.merge(
14
+ class: "Orbital-Menu-Label",
15
+ role: "presentation"
16
+ )
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Menu
5
+ class Separator < Component
6
+ orb_template <<-ORB
7
+ <div **html_attributes></div>
8
+ ORB
9
+
10
+ private
11
+
12
+ def default_attributes
13
+ super.merge(
14
+ class: "Orbital-Menu-Separator",
15
+ role: "separator",
16
+ "aria-orientation": "horizontal"
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Menu
5
+ class Sub < Component
6
+ include OrbitalUi::Concerns::IconProp
7
+
8
+ attribute :label, :string, required: true
9
+ attribute :icon, :any, default: nil
10
+
11
+ renders_many :items, types: {
12
+ item: { renders: Menu::Item, as: :item },
13
+ label: { renders: Menu::Label, as: :label },
14
+ separator: { renders: Menu::Separator, as: :separator }
15
+ }
16
+
17
+ def call
18
+ content_tag(:div, **html_attributes) do
19
+ safe_join([trigger_button, sub_content])
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def trigger_button
26
+ content_tag(:button,
27
+ class: "Orbital-Menu-Item Orbital-Menu-Sub-Trigger",
28
+ role: "menuitem",
29
+ tabindex: "-1",
30
+ "aria-haspopup": "true",
31
+ "aria-expanded": "false",
32
+ "data-orbital-menu-target": "item",
33
+ "data-orbital-menu-sub-target": "trigger",
34
+ "data-action": "click->orbital-menu-sub#toggle") do
35
+ safe_join([
36
+ render_icon,
37
+ content_tag(:span, @label, class: "Orbital-Menu-Item-Content"),
38
+ render(OrbitalUi::Icon.new(name: "chevron-right", size: :sm, class: "Orbital-Menu-Sub-Icon"))
39
+ ].compact)
40
+ end
41
+ end
42
+
43
+ def sub_content
44
+ content_tag(:div,
45
+ class: "Orbital-Menu-Sub-Content",
46
+ role: "menu",
47
+ "data-orbital-menu-sub-target": "content",
48
+ "data-action": "keydown->orbital-menu-sub#handleKeydown") do
49
+ safe_join(items)
50
+ end
51
+ end
52
+
53
+ def expanded
54
+ @expanded || "false"
55
+ end
56
+
57
+ def default_attributes
58
+ super.merge(
59
+ class: "Orbital-Menu-Sub",
60
+ "data-state": "closed",
61
+ data: {
62
+ controller: "orbital-menu-sub"
63
+ }
64
+ )
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Menu < Component
5
+ renders_many :menu_items, types: {
6
+ item: { renders: Menu::Item, as: :item },
7
+ label: { renders: Menu::Label, as: :label },
8
+ separator: { renders: Menu::Separator, as: :separator },
9
+ sub: { renders: Menu::Sub, as: :sub }
10
+ }
11
+
12
+ attribute :orientation, :symbol, default: :vertical, only: [:vertical, :horizontal]
13
+
14
+ orb_template <<-ORB
15
+ <div **html_attributes>
16
+ {#for menu_item in menu_items}
17
+ {{menu_item}}
18
+ {/for}
19
+ </div>
20
+ ORB
21
+
22
+ private
23
+
24
+ def default_attributes
25
+ super.merge(
26
+ class: "Orbital-Menu",
27
+ role: "menu",
28
+ "data-orientation": @orientation,
29
+ data: {
30
+ controller: "orbital-menu",
31
+ action: "keydown->orbital-menu#handleKeydown"
32
+ }
33
+ )
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Modal < Component
5
+ attribute :open, :boolean, default: false
6
+ attribute :dismissible, :boolean, default: true
7
+ attribute :size, :symbol, default: :default, only: [:sm, :default, :lg, :xl, :full]
8
+
9
+ orb_template <<~ORB
10
+ <div **html_attributes>
11
+ <div class="Orbital-Modal-Backdrop" data-action="click->orbital-modal#backdropClick"></div>
12
+ <div class="Orbital-Modal-Container">
13
+ <div class="Orbital-Modal-Panel" data-size={@size} data-orbital-modal-target="panel">
14
+ {{content}}
15
+ </div>
16
+ </div>
17
+ </div>
18
+ ORB
19
+
20
+ private
21
+
22
+ def default_attributes
23
+ super.merge(
24
+ class: "Orbital-Modal",
25
+ role: "dialog",
26
+ "aria-modal": "true",
27
+ data: {
28
+ controller: "orbital-modal",
29
+ "orbital-modal-open-value": @open.to_s,
30
+ "orbital-modal-dismissible-value": @dismissible.to_s,
31
+ state: @open ? "open" : "closed"
32
+ }
33
+ )
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class ModalFrame < Component
5
+ orb_template <<~ORB
6
+ <turbo-frame id={portal_id}>
7
+ {{content}}
8
+ </turbo-frame>
9
+ ORB
10
+
11
+ private
12
+
13
+ def portal_id
14
+ OrbitalUi.configuration.dialog_portal_id
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ class OrbitalUi::NavigationMenu < OrbitalUi::Component
4
+ renders_one :brand
5
+ renders_one :mobile
6
+
7
+ def call
8
+ popover_id = "nav-mobile-#{SecureRandom.hex(4)}"
9
+ has_mobile = mobile?
10
+
11
+ content_tag :nav, **html_attributes do
12
+ safe_join([
13
+ brand,
14
+ has_mobile ? mobile_trigger(popover_id) : nil,
15
+ nav_content,
16
+ has_mobile ? mobile_popover(popover_id) : nil
17
+ ].compact)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def mobile_trigger(popover_id)
24
+ content_tag(:button,
25
+ class: "Orbital-NavigationMenu-Toggle",
26
+ popovertarget: popover_id,
27
+ popovertargetaction: "toggle",
28
+ style: "anchor-name: --nav-toggle-#{popover_id}",
29
+ "aria-label": "Menu") do
30
+ render OrbitalUi::Icon.new(name: "menu", size: :md)
31
+ end
32
+ end
33
+
34
+ def nav_content
35
+ content_tag(:div, class: "Orbital-NavigationMenu-Content") do
36
+ content
37
+ end
38
+ end
39
+
40
+ def mobile_popover(popover_id)
41
+ tag.div(mobile,
42
+ id: popover_id,
43
+ popover: "auto",
44
+ class: "Orbital-NavigationMenu-Mobile",
45
+ style: "position-anchor: --nav-toggle-#{popover_id}")
46
+ end
47
+
48
+ def default_attributes
49
+ super.merge(class: "Orbital-NavigationMenu")
50
+ end
51
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Popcard < Popover
5
+ attribute :on, :symbol, default: :hover, only: [:click, :hover]
6
+ attribute :position, :symbol, default: :n, only: [:auto, :n, :ne, :e, :se, :s, :sw, :w, :nw]
7
+
8
+ private
9
+
10
+ def default_attributes
11
+ super.merge(class: "Orbital-Popcard-Container")
12
+ end
13
+
14
+ def content_class
15
+ "Orbital-Popcard"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Popover < Component
5
+ attribute :id, :string, default: -> { "popover-#{SecureRandom.hex(4)}" }
6
+ attribute :on, :symbol, default: :click, only: [:click, :hover]
7
+ attribute :position, :symbol, default: :auto, only: [:auto, :n, :ne, :e, :se, :s, :sw, :w, :nw]
8
+
9
+ renders_one :trigger
10
+
11
+ orb_template <<-ORB
12
+ <div **html_attributes>
13
+ {#if trigger}
14
+ <div
15
+ data-orbital-popover-target="trigger">
16
+ {{trigger}}
17
+ </div>
18
+ {/if}
19
+ {#if content}
20
+ <div
21
+ popover
22
+ id={@id}
23
+ data-orbital-popover-target="content"
24
+ class={content_class}
25
+ data-position={@position}>
26
+ {{content}}
27
+ </div>
28
+ {/if}
29
+ </div>
30
+ ORB
31
+
32
+ private
33
+
34
+ def content_class
35
+ "Orbital-Popover"
36
+ end
37
+
38
+ def default_attributes
39
+ super.merge(
40
+ class: "Orbital-Popover-Container",
41
+ data: {
42
+ controller: "orbital-popover",
43
+ "orbital-popover-trigger-value": @on,
44
+ "orbital-popover-position-value": @position,
45
+ state: "closed"
46
+ }
47
+ )
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class ProgressBar < Component
5
+ attribute :value, :float, default: 0
6
+ attribute :max, :float, default: 100
7
+ attribute :size, :symbol, default: :md, only: %i[xs sm md lg xl]
8
+
9
+ orb_template <<-ORB
10
+ <div **html_attributes>
11
+ <div class="Orbital-ProgressBar-Fill" style={fill_style}></div>
12
+ </div>
13
+ ORB
14
+
15
+ private
16
+
17
+ def fill_style
18
+ percent = @max.to_f.positive? ? (@value.to_f / @max * 100).clamp(0, 100).round(1) : 0
19
+ "width: #{percent}%"
20
+ end
21
+
22
+ def default_attributes
23
+ super.merge(
24
+ class: "Orbital-ProgressBar",
25
+ "data-size": @size,
26
+ role: "progressbar",
27
+ "aria-valuenow": @value,
28
+ "aria-valuemin": 0,
29
+ "aria-valuemax": @max
30
+ )
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class OrbitalUi::Prose < OrbitalUi::Component
4
+ def call
5
+ content_tag :div, **html_attributes do
6
+ content
7
+ end
8
+ end
9
+
10
+ private
11
+
12
+ def default_attributes
13
+ super.merge(class: "Orbital-Prose")
14
+ end
15
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Select < Component
5
+ attribute :options, :array, default: []
6
+ attribute :selected, :string, default: nil
7
+ attribute :placeholder, :string, default: "Select..."
8
+ attribute :name, :string, default: nil
9
+ attribute :id, :string, default: nil
10
+ attribute :label, :string, default: nil
11
+ attribute :labelHidden, :boolean, default: false
12
+ attribute :help, :string, default: nil
13
+ attribute :error, :string, default: nil
14
+ attribute :disabled, :boolean, default: false
15
+ attribute :required, :boolean, default: false
16
+ attribute :position, :symbol, default: :s
17
+ attribute :fullwidth, :boolean, default: false
18
+
19
+ orb_template <<-ORB
20
+ <div class="Orbital-Field" data-fullwidth={@fullwidth || nil}>
21
+ <label for={input_id} class="Orbital-Field-Label" data-hidden={@labelHidden || nil} :if={render_label?}>
22
+ <Text size="sm" weight=medium>{{label_text}}</Text>
23
+ </label>
24
+
25
+ <div **html_attributes>
26
+ <input
27
+ type="hidden"
28
+ id={input_id}
29
+ name={@name}
30
+ value={@selected}
31
+ data-orbital-select-target="input"
32
+ class="Orbital-Select-Input"
33
+ />
34
+
35
+ <Dropdown
36
+ position={@position}
37
+ fullwidth
38
+ id={dropdown_id}>
39
+
40
+ <Dropdown:Trigger>
41
+ <Button
42
+ variant="outline"
43
+ disabled={@disabled}
44
+ class={button_classes}>
45
+ <span
46
+ data-orbital-select-target="label"
47
+ class={label_classes}>
48
+ {{display_label}}
49
+ </span>
50
+ <Icon name="chevron-down" size="sm"/>
51
+ </Button>
52
+ </Dropdown:Trigger>
53
+
54
+ <Menu>
55
+ {#for option in @options}
56
+ <Menu::Item
57
+ data-value={option[:value]}
58
+ data-label={option[:label]}
59
+ disabled={option[:disabled] || false}
60
+ selected={option[:value] == @selected}
61
+ data-action="click->orbital-select#handleItemClick">
62
+ {{option[:label]}}
63
+ </Menu::Item>
64
+ {/for}
65
+ </Menu>
66
+ </Dropdown>
67
+ </div>
68
+
69
+ <div class="Orbital-Field-Help leading-none" :if={help? || error?}>
70
+ {% if error? %}
71
+ <Text size="sm" weight=medium tone="danger" class="leading-none!">{{ @error }}</Text>
72
+ {% else %}
73
+ <Text size="sm" tone="subdued" class="leading-none!">{{ @help }}</Text>
74
+ {% end %}
75
+ </div>
76
+ </div>
77
+ ORB
78
+
79
+ private
80
+
81
+ def default_attributes
82
+ super.merge(
83
+ class: class_names(
84
+ "Orbital-Select",
85
+ "Orbital-Select--fullwidth": @fullwidth
86
+ ),
87
+ data: {
88
+ controller: "orbital-select",
89
+ "orbital-select-selected-value": @selected,
90
+ error: error? || nil
91
+ }
92
+ )
93
+ end
94
+
95
+ def input_id
96
+ @id ||= "select-#{SecureRandom.hex(4)}"
97
+ end
98
+
99
+ def dropdown_id
100
+ "#{input_id}-dropdown"
101
+ end
102
+
103
+ def label_text
104
+ @label || @name.to_s.humanize
105
+ end
106
+
107
+ def render_label?
108
+ (@label.present? || @name.present?) && !@labelHidden
109
+ end
110
+
111
+ def selected_option
112
+ @options.find { |opt| opt[:value] == @selected }
113
+ end
114
+
115
+ def display_label
116
+ selected_option ? selected_option[:label] : @placeholder
117
+ end
118
+
119
+ def label_classes
120
+ class_names(
121
+ selected_option ? "Orbital-Select-Label" : "Orbital-Select-Placeholder"
122
+ )
123
+ end
124
+
125
+ def button_classes
126
+ class_names(
127
+ "Orbital-Select-Trigger",
128
+ "border-red-500": error?
129
+ )
130
+ end
131
+
132
+ def help?
133
+ @help.present?
134
+ end
135
+
136
+ def error?
137
+ @error.present?
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Separator < Component
5
+ attribute :orientation, :symbol, only: %i[horizontal vertical], default: :horizontal
6
+ attribute :decorative, :boolean, default: true
7
+
8
+ orb_template <<-ORB
9
+ <div **html_attributes></div>
10
+ ORB
11
+
12
+ private
13
+
14
+ def default_attributes
15
+ super.merge(
16
+ class: "Orbital-Separator",
17
+ "data-orientation": @orientation,
18
+ role: @decorative ? "none" : "separator"
19
+ )
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class OrbitalUi::Spinner < OrbitalUi::Component
4
+ attribute :size, :string, default: "md" # sm, md, lg
5
+ attribute :tone, :string, default: "primary" # primary, secondary, accent
6
+ attribute :kind, :string, only: %w[notch dots], default: "notch"
7
+
8
+ orb_template <<-ORB
9
+ <div class="Orbital-Spinner" data-kind={@kind} data-size={@size} role="status" aria-live="polite" aria-busy="true">
10
+ <span class="sr-only">Loading...</span>
11
+ <Icon name="loader-circle" size={@size}/>
12
+ </div>
13
+ ORB
14
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Stack < Component
5
+ attribute :gap, :string, default: "4"
6
+ attribute :align, :symbol, default: :stretch, only: %i[start center end stretch]
7
+ attribute :justify, :symbol, default: :start, only: %i[start center end between around evenly]
8
+ attribute :padding, :string
9
+ attribute :dividers, :boolean, default: false
10
+
11
+ orb_template <<-ORB
12
+ <div **html_attributes>{{content}}</div>
13
+ ORB
14
+
15
+ private
16
+
17
+ def default_attributes
18
+ attrs = super.merge(
19
+ class: "Orbital-Stack",
20
+ "data-gap": @gap,
21
+ "data-align": @align,
22
+ "data-justify": @justify,
23
+ "data-padding": @padding
24
+ )
25
+ attrs[:"data-dividers"] = true if @dividers
26
+ attrs
27
+ end
28
+ end
29
+ end