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,43 @@
1
+ :root {
2
+ --background: #ffffff;
3
+ --foreground: #1a1a1a;
4
+ --primary: #ea580c;
5
+ --primary-foreground: #fff7ed;
6
+ --secondary: #fff7ed;
7
+ --secondary-foreground: #1a1a1a;
8
+ --destructive: #dc2626;
9
+ --destructive-foreground: #fafafa;
10
+ --muted: #f5f5f4;
11
+ --muted-foreground: #737373;
12
+ --accent: #ffedd5;
13
+ --accent-foreground: #1a1a1a;
14
+ --card: #ffffff;
15
+ --card-foreground: #1a1a1a;
16
+ --popover: #ffffff;
17
+ --popover-foreground: #1a1a1a;
18
+ --border: #e5e5e5;
19
+ --input: #e5e5e5;
20
+ --ring: #ea580c;
21
+ }
22
+
23
+ .dark {
24
+ --background: #1a1a1a;
25
+ --foreground: #fafaf9;
26
+ --primary: #fb923c;
27
+ --primary-foreground: #1a1a1a;
28
+ --secondary: #292524;
29
+ --secondary-foreground: #fafaf9;
30
+ --destructive: #7f1d1d;
31
+ --destructive-foreground: #fafaf9;
32
+ --muted: #292524;
33
+ --muted-foreground: #a8a29e;
34
+ --accent: #292524;
35
+ --accent-foreground: #fafaf9;
36
+ --card: #1a1a1a;
37
+ --card-foreground: #fafaf9;
38
+ --popover: #1a1a1a;
39
+ --popover-foreground: #fafaf9;
40
+ --border: #292524;
41
+ --input: #292524;
42
+ --ring: #fb923c;
43
+ }
@@ -0,0 +1,43 @@
1
+ :root {
2
+ --background: #ffffff;
3
+ --foreground: #1c1917;
4
+ --primary: #e11d48;
5
+ --primary-foreground: #fff1f2;
6
+ --secondary: #fef2f2;
7
+ --secondary-foreground: #1c1917;
8
+ --destructive: #dc2626;
9
+ --destructive-foreground: #fafafa;
10
+ --muted: #f5f5f4;
11
+ --muted-foreground: #78716c;
12
+ --accent: #fef2f2;
13
+ --accent-foreground: #1c1917;
14
+ --card: #ffffff;
15
+ --card-foreground: #1c1917;
16
+ --popover: #ffffff;
17
+ --popover-foreground: #1c1917;
18
+ --border: #e7e5e4;
19
+ --input: #e7e5e4;
20
+ --ring: #e11d48;
21
+ }
22
+
23
+ .dark {
24
+ --background: #1c1917;
25
+ --foreground: #fafaf9;
26
+ --primary: #fb7185;
27
+ --primary-foreground: #1c1917;
28
+ --secondary: #292524;
29
+ --secondary-foreground: #fafaf9;
30
+ --destructive: #7f1d1d;
31
+ --destructive-foreground: #fafaf9;
32
+ --muted: #292524;
33
+ --muted-foreground: #a8a29e;
34
+ --accent: #292524;
35
+ --accent-foreground: #fafaf9;
36
+ --card: #1c1917;
37
+ --card-foreground: #fafaf9;
38
+ --popover: #1c1917;
39
+ --popover-foreground: #fafaf9;
40
+ --border: #292524;
41
+ --input: #292524;
42
+ --ring: #fb7185;
43
+ }
@@ -0,0 +1,43 @@
1
+ :root {
2
+ --background: #ffffff;
3
+ --foreground: #1e1b4b;
4
+ --primary: #7c3aed;
5
+ --primary-foreground: #f5f3ff;
6
+ --secondary: #f5f3ff;
7
+ --secondary-foreground: #1e1b4b;
8
+ --destructive: #ef4444;
9
+ --destructive-foreground: #fafafa;
10
+ --muted: #f5f3ff;
11
+ --muted-foreground: #6b7280;
12
+ --accent: #ede9fe;
13
+ --accent-foreground: #1e1b4b;
14
+ --card: #ffffff;
15
+ --card-foreground: #1e1b4b;
16
+ --popover: #ffffff;
17
+ --popover-foreground: #1e1b4b;
18
+ --border: #e5e7eb;
19
+ --input: #e5e7eb;
20
+ --ring: #7c3aed;
21
+ }
22
+
23
+ .dark {
24
+ --background: #1e1b4b;
25
+ --foreground: #f5f3ff;
26
+ --primary: #a78bfa;
27
+ --primary-foreground: #1e1b4b;
28
+ --secondary: #312e81;
29
+ --secondary-foreground: #f5f3ff;
30
+ --destructive: #7f1d1d;
31
+ --destructive-foreground: #fafafa;
32
+ --muted: #312e81;
33
+ --muted-foreground: #c4b5fd;
34
+ --accent: #312e81;
35
+ --accent-foreground: #f5f3ff;
36
+ --card: #1e1b4b;
37
+ --card-foreground: #f5f3ff;
38
+ --popover: #1e1b4b;
39
+ --popover-foreground: #f5f3ff;
40
+ --border: #312e81;
41
+ --input: #312e81;
42
+ --ring: #a78bfa;
43
+ }
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class OrbitalUi::Accordion::Item < OrbitalUi::Component
4
+ renders_one :trigger
5
+
6
+ attribute :value, :string, required: true
7
+ attribute :expanded, :boolean, default: false
8
+
9
+ orb_template <<-ORB
10
+ <div **html_attributes>
11
+ <Heading as="button" size="sm" class="flex justify-between cursor-pointer w-full py-4 gap-2" data-accordion-trigger>
12
+ <span class="flex items-center gap-2">{{trigger}}</span>
13
+ <Icon name="chevron-down" size="small" class="shrink-0" data-accordion-chevron/>
14
+ </Heading>
15
+ <div class="Orbital-Accordion-Item-Content" data-state={state}>
16
+ <div class="Orbital-Accordion-Item-Inner">
17
+ {{content}}
18
+ </div>
19
+ </div>
20
+ </div>
21
+ ORB
22
+
23
+ private
24
+
25
+ def state
26
+ @expanded ? "open" : "closed"
27
+ end
28
+
29
+ def default_attributes
30
+ super.merge(class: "Orbital-Accordion-Item")
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class OrbitalUi::Accordion < OrbitalUi::Component
4
+ renders_many :items, OrbitalUi::Accordion::Item
5
+
6
+ orb_template <<-ORB
7
+ <div **html_attributes>
8
+ {#for item in items}
9
+ {{item}}
10
+ {/for}
11
+ </div>
12
+ ORB
13
+
14
+ private
15
+
16
+ def default_attributes
17
+ super.merge(
18
+ class: "Orbital-Accordion",
19
+ role: "region",
20
+ data: { controller: "o-accordion" }
21
+ )
22
+ end
23
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Alert < 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
+ attribute :title, :string, default: nil
9
+ attribute :description, :string, default: nil
10
+ attribute :variant, :symbol, default: :default, only: [:default, :success, :warning, :danger, :info]
11
+ attribute :button_text, :string, default: "OK"
12
+
13
+ orb_template <<-ORB
14
+ <Modal open={@open} dismissible={@dismissible} size={@size} **html_attributes>
15
+ <div class="Orbital-Dialog" data-variant={@variant}>
16
+ <button :if={@dismissible}
17
+ type="button"
18
+ data-action="orbital-modal#close"
19
+ class="Orbital-Dialog-Close"
20
+ aria-label="Close">
21
+ <svg class="Orbital-Icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
22
+ <line x1="18" y1="6" x2="6" y2="18"></line>
23
+ <line x1="6" y1="6" x2="18" y2="18"></line>
24
+ </svg>
25
+ </button>
26
+
27
+ <div class="Orbital-Dialog-Header">
28
+ <div class="Orbital-Alert-Content">
29
+ {#if variant_icon}
30
+ <div class="Orbital-Alert-Icon" data-variant={@variant}>
31
+ {{variant_icon}}
32
+ </div>
33
+ {/if}
34
+ <div class="Orbital-Alert-Text">
35
+ {#if @title}
36
+ <h2 class="Orbital-Dialog-Title">{{@title}}</h2>
37
+ {/if}
38
+ {#if @description}
39
+ <p class="Orbital-Dialog-Description">{{@description}}</p>
40
+ {/if}
41
+ </div>
42
+ </div>
43
+ </div>
44
+
45
+ {#if content}
46
+ <div class="Orbital-Dialog-Body">
47
+ {{content}}
48
+ </div>
49
+ {/if}
50
+
51
+ <div class="Orbital-Dialog-Footer">
52
+ <button
53
+ data-action="orbital-modal#close"
54
+ class="Orbital-Button"
55
+ data-variant="default"
56
+ data-size="default"
57
+ type="button">
58
+ {{@button_text}}
59
+ </button>
60
+ </div>
61
+ </div>
62
+ </Modal>
63
+ ORB
64
+
65
+ private
66
+
67
+ def variant_icon
68
+ icon_name = case @variant
69
+ when :success then "circle-check"
70
+ when :warning then "triangle-alert"
71
+ when :danger then "circle-alert"
72
+ when :info then "info"
73
+ end
74
+
75
+ return nil unless icon_name
76
+
77
+ render OrbitalUi::Icon.new(name: icon_name, size: :lg)
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/md5"
4
+
5
+ class OrbitalUi::Avatar < OrbitalUi::Component
6
+ include OrbitalUi::Concerns::IconProp
7
+
8
+ attribute :name, :string, default: nil
9
+ attribute :email, :string, default: nil
10
+ attribute :initials, :string, default: nil
11
+ attribute :size, :symbol, default: :md, only: [:xs, :sm, :md, :lg, :xl]
12
+ attribute :icon, :any, default: "user"
13
+ attribute :round, :boolean, default: true
14
+ attribute :square, :boolean, default: false
15
+
16
+ def call
17
+ content_tag(:div, **html_attributes) do
18
+ if gravatar_url
19
+ tag.img(
20
+ src: gravatar_url,
21
+ alt: @name || "",
22
+ class: "Orbital-Avatar-Image",
23
+ loading: "lazy",
24
+ "data-orbital-avatar-target": "image",
25
+ "data-action": "error->orbital-avatar#imageError"
26
+ ) + fallback_element(hidden: true)
27
+ else
28
+ fallback_element
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def fallback_element(hidden: false)
36
+ opts = { "data-orbital-avatar-target": "fallback" }
37
+ opts[:style] = "display:none;" if hidden
38
+ if @initials.present?
39
+ content_tag(:span, @initials.upcase[0, 2], class: "Orbital-Avatar-Initials", **opts)
40
+ else
41
+ content_tag(:span, class: "Orbital-Avatar-Icon", **opts) do
42
+ render_icon(@icon, size: icon_size)
43
+ end
44
+ end
45
+ end
46
+
47
+ def icon_size
48
+ case @size
49
+ when :xs, :sm then :xs
50
+ when :md then :sm
51
+ when :lg, :xl then :md
52
+ end
53
+ end
54
+
55
+ def gravatar_url
56
+ return nil unless @email.present?
57
+
58
+ hash = Digest::MD5.hexdigest(@email.strip.downcase)
59
+ "https://www.gravatar.com/avatar/#{hash}?d=404&s=#{pixel_size}"
60
+ end
61
+
62
+ def pixel_size
63
+ case @size
64
+ when :xs then 24
65
+ when :sm then 32
66
+ when :md then 40
67
+ when :lg then 48
68
+ when :xl then 64
69
+ end
70
+ end
71
+
72
+ def shape
73
+ @square ? "square" : "round"
74
+ end
75
+
76
+ def default_attributes
77
+ attrs = super.merge(
78
+ class: "Orbital-Avatar",
79
+ "data-size": @size,
80
+ "data-shape": shape,
81
+ "data-controller": gravatar_url ? "orbital-avatar" : nil
82
+ )
83
+ attrs[:title] = @name if @name.present?
84
+ attrs["aria-label"] = @name if @name.present?
85
+ attrs
86
+ end
87
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Badge < Component
5
+ include OrbitalUi::Concerns::IconProp
6
+
7
+ attribute :variant, :symbol, default: :default, only: [:default, :secondary, :destructive, :ghost, :outline]
8
+ attribute :dot, :symbol, default: nil, only: [:default, :success, :warning, :danger, :info, :subdued]
9
+ attribute :icon, :any, default: nil
10
+
11
+ orb_template <<~ORB
12
+ <span **html_attributes>
13
+ {{render_icon}}
14
+ {{content}}
15
+ <span class="Orbital-Badge-Dot" data-tone={@dot} :if={@dot}/>
16
+ </span>
17
+ ORB
18
+
19
+ private
20
+
21
+ def default_attributes
22
+ super.merge(
23
+ class: "Orbital-Badge",
24
+ "data-variant": @variant
25
+ )
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Button < Component
5
+ attribute :variant, :symbol, default: :default, only: [:default, :destructive, :outline, :secondary, :ghost, :link]
6
+ attribute :size, :symbol, default: :default, only: [:sm, :default, :lg, :icon]
7
+ attribute :url, :string, default: nil
8
+ attribute :disabled, :boolean, default: false
9
+ attribute :fullwidth, :boolean, default: false
10
+ attribute :modal, :any, default: nil
11
+
12
+ def call
13
+ build_tag(**html_attributes) do
14
+ content
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def default_attributes
21
+ attrs = super.merge(
22
+ class: "Orbital-Button",
23
+ "data-variant": @variant,
24
+ "data-size": @size,
25
+ "data-disabled": @disabled || nil,
26
+ "data-fullwidth": @fullwidth || nil
27
+ )
28
+
29
+ if @modal.is_a?(String) && %w[true false].exclude?(@modal)
30
+ attrs["data-open-modal"] = @modal
31
+ elsif @modal && @url.present?
32
+ attrs["data-turbo-frame"] = OrbitalUi.configuration.dialog_portal_id
33
+ end
34
+
35
+ attrs
36
+ end
37
+
38
+ def build_tag(**opts)
39
+ if @url.present?
40
+ tag.a(href: @url, **opts) { yield }
41
+ else
42
+ tag.button(**opts) { yield }
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class ButtonGroup < Component
5
+ attribute :orientation, :symbol, default: :horizontal, only: [:horizontal, :vertical]
6
+
7
+ orb_template <<-ORB
8
+ <div **html_attributes>{{content}}</div>
9
+ ORB
10
+
11
+ private
12
+
13
+ def default_attributes
14
+ super.merge(
15
+ class: "Orbital-ButtonGroup",
16
+ "data-orientation": @orientation
17
+ )
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Card
5
+ class Action < Component
6
+ orb_template <<-ORB
7
+ <div **html_attributes>{{content}}</div>
8
+ ORB
9
+
10
+ private
11
+
12
+ def default_attributes
13
+ super.merge(class: "Orbital-Card-Action")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Card
5
+ class Content < Component
6
+ orb_template <<-ORB
7
+ <div **html_attributes>{{content}}</div>
8
+ ORB
9
+
10
+ private
11
+
12
+ def default_attributes
13
+ super.merge(class: "Orbital-Card-Content")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Card
5
+ class Description < Component
6
+ orb_template <<-ORB
7
+ <div **html_attributes>{{content}}</div>
8
+ ORB
9
+
10
+ private
11
+
12
+ def default_attributes
13
+ super.merge(class: "Orbital-Card-Description")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Card
5
+ class Footer < Component
6
+ orb_template <<-ORB
7
+ <div **html_attributes>{{content}}</div>
8
+ ORB
9
+
10
+ private
11
+
12
+ def default_attributes
13
+ super.merge(class: "Orbital-Card-Footer")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Card
5
+ class Header < Component
6
+ renders_one :title, Card::Title
7
+ renders_one :description, Card::Description
8
+ renders_one :action, Card::Action
9
+
10
+ orb_template <<-ORB
11
+ <div **html_attributes>
12
+ {{title}}
13
+ {{description}}
14
+ {{action}}
15
+ </div>
16
+ ORB
17
+
18
+ private
19
+
20
+ def default_attributes
21
+ super.merge(class: "Orbital-Card-Header")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Card
5
+ class Title < Component
6
+ orb_template <<-ORB
7
+ <div **html_attributes>{{content}}</div>
8
+ ORB
9
+
10
+ private
11
+
12
+ def default_attributes
13
+ super.merge(class: "Orbital-Card-Title")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Card < Component
5
+ renders_one :header, Card::Header
6
+ renders_one :footer, Card::Footer
7
+
8
+ attribute :gap, :string
9
+ attribute :padding, :string
10
+
11
+ orb_template <<-ORB
12
+ <div **html_attributes>
13
+ {{header}}
14
+ <div **content_attributes>{{content}}</div>
15
+ {{footer}}
16
+ </div>
17
+ ORB
18
+
19
+ private
20
+
21
+ # A splat, because a bound attribute on an HTML tag would render nil as data-gap="".
22
+ def content_attributes
23
+ { class: "Orbital-Card-Content", "data-gap": @gap, "data-padding": @padding }
24
+ end
25
+
26
+ def default_attributes
27
+ super.merge(class: "Orbital-Card")
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ class OrbitalUi::CheckBox < OrbitalUi::Component
4
+ attribute :name, :string, default: nil
5
+ attribute :value, :string, default: "1"
6
+ attribute :label, :string, default: nil
7
+ attribute :help, :string, default: nil
8
+ attribute :error, :string, default: nil
9
+ attribute :checked, :boolean, default: false
10
+ attribute :disabled, :boolean, default: false
11
+ attribute :id, :string, default: nil
12
+
13
+ orb_template <<-ORB
14
+ <div class="Orbital-CheckBox">
15
+ <label for={input_id} class="Orbital-CheckBox-Label">
16
+ <div class="Orbital-CheckBox-Control">
17
+ {{ tag.input(**html_attributes) }}
18
+ <span class="Orbital-CheckBox-Indicator"/>
19
+ <Icon name="check" size="sm" class="Orbital-CheckBox-Icon" />
20
+ </div>
21
+ <Text>{{ label_text }}</Text>
22
+ </label>
23
+
24
+ {#if @error.present?}
25
+ <Text tone="danger" size="sm">{{ @error }}</Text>
26
+ {/if}
27
+
28
+ {#if @help.present? && !@error.present?}
29
+ <Text tone="subdued" size="sm">{{ @help }}</Text>
30
+ {/if}
31
+ </div>
32
+ ORB
33
+
34
+ private
35
+
36
+ def default_attributes
37
+ super.merge(
38
+ name: @name,
39
+ value: @value,
40
+ id: input_id,
41
+ class: "Orbital-CheckBox-Input",
42
+ type: "checkbox",
43
+ checked: @checked,
44
+ disabled: @disabled
45
+ )
46
+ end
47
+
48
+ def label_text
49
+ @label || @name.to_s.humanize
50
+ end
51
+
52
+ def input_id
53
+ @id ||= SecureRandom.hex(4)
54
+ end
55
+
56
+ def help?
57
+ @help.present?
58
+ end
59
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ class Component < ViewComponent::Base
5
+ # This module imports the attribute DSL for defining attributes on a component
6
+ # as well as the html_attributes method for generating HTML attributes
7
+ include OrbitalUi::Components::Attributes
8
+
9
+ # This module provides a method for joining style names together
10
+ include OrbitalUi::Components::Styles
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OrbitalUi
4
+ module Concerns
5
+ module IconProp
6
+ def render_icon(icon = @icon, size: :sm)
7
+ return nil unless icon
8
+
9
+ opts = icon.is_a?(Hash) ? { size: size }.merge(icon) : { name: icon, size: size }
10
+ render(OrbitalUi::Icon.new(**opts))
11
+ end
12
+ end
13
+ end
14
+ end