relay_ui 0.2.3 → 0.4.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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -13
  3. data/lib/relay_ui/engine.rb +14 -10
  4. data/lib/relay_ui/version.rb +1 -1
  5. data/lib/rui/badges/base.rb +5 -1
  6. data/lib/rui/badges/blue.rb +3 -1
  7. data/lib/rui/badges/gray.rb +3 -1
  8. data/lib/rui/badges/green.rb +3 -1
  9. data/lib/rui/badges/purple.rb +3 -1
  10. data/lib/rui/badges/red.rb +3 -1
  11. data/lib/rui/badges/yellow.rb +3 -1
  12. data/lib/rui/badges.rb +3 -0
  13. data/lib/rui/base.rb +3 -8
  14. data/lib/rui/buttons/base.rb +12 -9
  15. data/lib/rui/buttons/destructive.rb +3 -1
  16. data/lib/rui/buttons/ghost.rb +3 -1
  17. data/lib/rui/buttons/outline.rb +3 -1
  18. data/lib/rui/buttons/primary.rb +6 -1
  19. data/lib/rui/buttons/secondary.rb +3 -1
  20. data/lib/rui/buttons.rb +3 -0
  21. data/lib/rui/card.rb +92 -0
  22. data/lib/rui/flash.rb +51 -0
  23. data/lib/rui/forms/checkbox.rb +25 -0
  24. data/lib/rui/forms/email.rb +19 -0
  25. data/lib/rui/forms/field_group.rb +5 -0
  26. data/lib/rui/forms/helpers.rb +19 -0
  27. data/lib/rui/forms/label.rb +7 -0
  28. data/lib/rui/forms/password.rb +18 -0
  29. data/lib/rui/forms/phone.rb +18 -0
  30. data/lib/rui/forms/radio.rb +22 -0
  31. data/lib/rui/forms/select.rb +24 -0
  32. data/lib/rui/forms/tailwind_form_builder.rb +142 -0
  33. data/lib/rui/forms/text.rb +17 -0
  34. data/lib/rui/forms/textarea.rb +18 -0
  35. data/lib/rui/forms.rb +3 -0
  36. data/lib/rui/helpers.rb +3 -0
  37. data/lib/rui/icon.rb +3 -1
  38. data/lib/rui/layout/body.rb +7 -0
  39. data/lib/rui/layout/main.rb +5 -0
  40. data/lib/rui/layout/page.rb +5 -0
  41. data/lib/rui/layout.rb +3 -0
  42. data/lib/rui/links/base.rb +5 -3
  43. data/lib/rui/links/destructive.rb +3 -1
  44. data/lib/rui/links/ghost.rb +3 -1
  45. data/lib/rui/links/outline.rb +3 -1
  46. data/lib/rui/links/primary.rb +3 -1
  47. data/lib/rui/links/secondary.rb +3 -1
  48. data/lib/rui/links.rb +3 -0
  49. data/lib/rui/markdown/generator.rb +2 -1
  50. data/lib/rui/markdown/safe.rb +3 -1
  51. data/lib/rui/markdown/safe_renderer.rb +3 -1
  52. data/lib/rui/markdown/unsafe.rb +3 -1
  53. data/lib/rui/markdown/unsafe_renderer.rb +9 -1
  54. data/lib/rui/markdown.rb +3 -0
  55. data/lib/rui/navigation/menu_button.rb +7 -0
  56. data/lib/rui/navigation/sidebar.rb +43 -0
  57. data/lib/rui/navigation/top.rb +19 -0
  58. data/lib/rui/navigation.rb +2 -50
  59. data/lib/rui/slideout.rb +9 -9
  60. data/lib/rui/table.rb +44 -0
  61. data/lib/rui/tailwind_merger.rb +17 -0
  62. data/lib/rui/text.rb +5 -3
  63. metadata +87 -3
  64. data/dist/relay_ui/relay_ui.css +0 -595
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 26bbb6690e73af9858e034ddd1f4165dc3e566da75a598df32697bfbda4eb326
4
- data.tar.gz: a717467cf909cb32f506d9dd5f8cd0931256b6c8e05de7dfa02634ff943fadd2
3
+ metadata.gz: 5bd18a48694c8b8d66e4183e74a7bee705ace0d0b821adba7e037750a49124cb
4
+ data.tar.gz: d972223721bae1f638121a4ec446cf4eb26ed70f4a6358ab956e1e0273e1d709
5
5
  SHA512:
6
- metadata.gz: 6b210e15c31c9dc210e201c67862410d2b768c7cf4f7a838dcc07b92c0925c782a25abbe4323d3c12eb9930c694eba1ed1a16205da3be220f42a6ef36e6c9042
7
- data.tar.gz: 76d07201379e1e1bfbff8cb914b58012d8868a2dcee91146856bedca312ad07f20e1e7de1de07ce256b20bd9a8547ed6492e44de165588f435c9749b172265e3
6
+ metadata.gz: 7429340803af5c5c886cec99ae2bd8c78a65033c3f1037318359acdf275c0907f67fb09423ecf3c8ba29a6916b62d3c3e82576863b0de8f10f47eef43e273e39
7
+ data.tar.gz: 595e27eab36b6c538b96fe30aff5d8d3b3637516a5723e48ff907a39dd845e683af8df449688f49cf79a59febad94dc0ad8eb09cf92c9726c06e8b14b449771d
data/README.md CHANGED
@@ -25,13 +25,6 @@ All of RelayUI's components are housed in the `RUI::` namespace. This turns your
25
25
 
26
26
  With this in mind, we prefer pulling basic variants up to the model level. Whereas many UI kits may specify variants via parameters (eg: `Component.new(variant: :primary)`), we prefer to give major variants class-level importance. So, we'll opt for patterns like `RUI::Buttons::Primary` and `RUI::Buttons::Secondary` instead.
27
27
 
28
- ## Using TailwindCSS
29
-
30
- RelayUI uses [TailwindCSS v4](https://tailwindcss.com/) for styling under the hood. One of the challenges we aimed to solve is how to include the styles Tailwind provides in a way that doesn't collide with any other CSS styles or frameworks being used. For example, we wanted to make sure RelayUI still worked well in projects that used Tailwind v3, or even Bootstrap.
31
-
32
- For that reason, we've decided to prefix our CSS classes with `rui:`. This way, RelayUI is able to come out of the box with all of the styles you need to make our components work, but you can choose to use any CSS framework you want and not risk any CSS class conflicts or collisions.
33
- STRING
34
-
35
28
  # Installation
36
29
 
37
30
  ### First, add the gem to your `Gemfile`:
@@ -52,12 +45,6 @@ bundle install
52
45
  gem install relay_ui
53
46
  ```
54
47
 
55
- ### Include the gem's stylesheet in your application layout:
56
-
57
- ```ruby
58
- stylesheet_link_tag "relay_ui/relay_ui", media: "all"
59
- ```
60
-
61
48
  That's it! All of the basic functionality of the UI kit is now available to you. For certain components that require additional elements (like stimulus controllers), you'll need to include those separately. They will be documented in the component's usage instructions.
62
49
 
63
50
  # Usage
@@ -1,18 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rui/forms/tailwind_form_builder"
4
+
3
5
  module RUI
4
- class Engine < ::Rails::Engine
5
- isolate_namespace RUI
6
+ if defined?(Rails)
7
+ class Engine < ::Rails::Engine
8
+ isolate_namespace RUI
6
9
 
7
- initializer "relay_ui.assets.precompile" do |app|
8
- app.config.assets.paths << root.join("dist")
9
- end
10
+ initializer "relay_ui.set_default_form_builder" do |app|
11
+ app.config.action_view.default_form_builder = RUI::Forms::TailwindFormBuilder
12
+ end
10
13
 
11
- initializer "relay_ui.autoload.components" do
12
- Rails.autoloaders.main.push_dir(
13
- "#{Gem::Specification.find_by_name('relay_ui').gem_dir}/lib/rui",
14
- namespace: RUI
15
- )
14
+ initializer "relay_ui.autoload.components" do
15
+ Rails.autoloaders.main.push_dir(
16
+ "#{Gem::Specification.find_by_name('relay_ui').gem_dir}/lib/rui",
17
+ namespace: RUI
18
+ )
19
+ end
16
20
  end
17
21
  end
18
22
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RUI
4
- VERSION = "0.2.3"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Badges::Base < RUI::Base
2
4
  def view_template
3
- span(class: "rui:px-3 rui:py-0.5 rui:text-xs rui:rounded-full #{variant_classes}") { yield }
5
+ div do
6
+ span(class: "whitespace-nowrap px-3 py-0.5 text-xs rounded-full text-center font-medium #{variant_classes}") { yield }
7
+ end
4
8
  end
5
9
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Badges::Blue < RUI::Badges::Base
2
4
  private
3
5
 
4
- def variant_classes = "rui:bg-blue-100 rui:text-blue-700"
6
+ def variant_classes = "bg-blue-100 text-blue-700"
5
7
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Badges::Gray < RUI::Badges::Base
2
4
  private
3
5
 
4
- def variant_classes = "rui:bg-gray-100 rui:text-gray-700"
6
+ def variant_classes = "bg-gray-100 text-gray-700"
5
7
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Badges::Green < RUI::Badges::Base
2
4
  private
3
5
 
4
- def variant_classes = "rui:bg-green-100 rui:text-green-700"
6
+ def variant_classes = "bg-green-100 text-green-700"
5
7
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Badges::Purple < RUI::Badges::Base
2
4
  private
3
5
 
4
- def variant_classes = "rui:bg-purple-100 rui:text-purple-700"
6
+ def variant_classes = "bg-purple-100 text-purple-700"
5
7
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Badges::Red < RUI::Badges::Base
2
4
  private
3
5
 
4
- def variant_classes = "rui:bg-red-100 rui:text-red-700"
6
+ def variant_classes = "bg-red-100 text-red-700"
5
7
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Badges::Yellow < RUI::Badges::Base
2
4
  private
3
5
 
4
- def variant_classes = "rui:bg-yellow-100 rui:text-yellow-700"
6
+ def variant_classes = "bg-yellow-100 text-yellow-700"
5
7
  end
data/lib/rui/badges.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RUI::Badges; end
data/lib/rui/base.rb CHANGED
@@ -1,13 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class RUI::Base < Phlex::HTML
4
- include Components
5
- include Phlex::Rails::Helpers::Routes
6
-
7
- if Rails.env.development?
8
- def before_template
9
- comment { "Before #{self.class.name}" }
10
- super
11
- end
4
+ def initialize(**attrs, &)
5
+ @attrs = attrs
6
+ super(&)
12
7
  end
13
8
  end
@@ -1,18 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Buttons::Base < RUI::Base
2
- def initialize(icon: nil, data: {})
4
+ def initialize(icon: nil, **attrs)
3
5
  @icon = icon
4
- @data = data
6
+ @attrs = attrs
5
7
  end
6
8
 
9
+ # Style string public for use in forms
10
+ STYLE = "inline-block px-2 py-1 hover:cursor-pointer rounded-md transition duration-200 ease-in-out".freeze
11
+
7
12
  def view_template
8
- button(class: classes, data: @data) do
9
- div(class: "rui:flex rui:flex-row rui:items-center rui:gap-2") do
13
+ button(class: classes, **@attrs) do
14
+ div(class: "flex flex-row items-center gap-2") do
10
15
  if @icon
11
- div(class: "rui:size-4 rui:my-1") do
16
+ div(class: "size-4 my-1") do
12
17
  render RUI::Icon.new(@icon)
13
18
  end
14
19
  end
15
- span { yield } if block_given?
20
+ span(class: "text-nowrap") { yield } if block_given?
16
21
  end
17
22
  end
18
23
  end
@@ -20,8 +25,6 @@ class RUI::Buttons::Base < RUI::Base
20
25
  private
21
26
 
22
27
  def classes
23
- "#{base_classes} #{variant_classes}"
28
+ "#{STYLE} #{variant_classes}"
24
29
  end
25
-
26
- def base_classes = "rui:inline-block rui:px-3 rui:py-1 rui:hover:cursor-pointer rui:rounded rui:transition rui:duration-200 rui:ease-in-out"
27
30
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Buttons::Destructive < RUI::Buttons::Base
2
4
  private
3
5
 
4
- def variant_classes = "rui:bg-red-700 rui:hover:bg-red-900 rui:text-white"
6
+ def variant_classes = "bg-red-700 hover:bg-red-900 text-white border border-red-700 hover:border-red-900"
5
7
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Buttons::Ghost < RUI::Buttons::Base
2
4
  private
3
5
 
4
- def variant_classes = "rui:hover:bg-zinc-100"
6
+ def variant_classes = "hover:bg-zinc-100"
5
7
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Buttons::Outline < RUI::Buttons::Base
2
4
  private
3
5
 
4
- def variant_classes = "rui:border rui:rounded rui:border-zinc-700 rui:hover:border-zinc-900 rui:text-zinc-700 rui:hover:text-zinc-900 rui:hover:bg-zinc-100"
6
+ def variant_classes = "border rounded border-zinc-300 hover:border-zinc-700 text-zinc-700"
5
7
  end
@@ -1,5 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Buttons::Primary < RUI::Buttons::Base
4
+ # Style string public for use in forms
5
+ STYLE = "bg-blue-700 hover:bg-blue-900 text-white border border-blue-700 hover:border-blue-900".freeze
6
+
2
7
  private
3
8
 
4
- def variant_classes = "rui:bg-blue-700 rui:hover:bg-blue-900 rui:text-white"
9
+ def variant_classes = STYLE
5
10
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Buttons::Secondary < RUI::Buttons::Base
2
4
  private
3
5
 
4
- def variant_classes = "rui:bg-zinc-700 rui:hover:bg-zinc-900 rui:text-white"
6
+ def variant_classes = "bg-zinc-700 hover:bg-zinc-900 text-white border border-zinc-700 hover:border-zinc-900"
5
7
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RUI::Buttons; end
data/lib/rui/card.rb ADDED
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Card < RUI::Base
4
+ def view_template(&)
5
+ div(role: "region", aria: { label: "Card" }, **@attrs) do
6
+ div(
7
+ class: "#{padding(capture(&))} flex flex-col gap-4 border border-zinc-300 rounded-lg overflow-hidden",
8
+ data: { component: "card" },
9
+ &
10
+ )
11
+ end
12
+ end
13
+
14
+ def header(&)
15
+ render Header.new(&)
16
+ end
17
+
18
+ def image(&)
19
+ img(src: capture(&))
20
+ end
21
+
22
+ def body(&)
23
+ div(class: "px-4", &)
24
+ end
25
+
26
+ def footer(&)
27
+ render Footer.new(&)
28
+ end
29
+
30
+ class Header < RUI::Base
31
+ def view_template(&)
32
+ header(class: "flex flex-row justify-between items-center gap-4 px-4", &)
33
+ end
34
+
35
+ def thumbnail(&)
36
+ img(src: capture(&), class: "inline-block rounded-full size-10")
37
+ end
38
+
39
+ def titles(&)
40
+ render Titles.new(&)
41
+ end
42
+
43
+ def actions(&)
44
+ div(class: "flex flex-row gap-2 items-center", &)
45
+ end
46
+
47
+ class Titles < RUI::Base
48
+ def view_template(&)
49
+ div(class: "grow shrink basis-0 flex flex-col", &)
50
+ end
51
+
52
+ def title(&)
53
+ h2(class: "text-xl font-semibold", &)
54
+ end
55
+
56
+ def subtitle(&)
57
+ h3(class: "text-lg", &)
58
+ end
59
+ end
60
+ end
61
+
62
+ class Footer < RUI::Base
63
+ def view_template(&)
64
+ footer(class: "flex flex-row justify-end items-center gap-4 px-4", &)
65
+ end
66
+
67
+ def actions(&)
68
+ render Actions.new(&)
69
+ end
70
+
71
+ class Actions < RUI::Base
72
+ def view_template(&)
73
+ div(class: "flex flex-row gap-2 items-center", &)
74
+ end
75
+
76
+ def action(href: "#", **kwargs, &)
77
+ a(href:, class: "text-blue-700 hover:underline uppercase text-sm font-semibold", **kwargs, &)
78
+ end
79
+ end
80
+ end
81
+
82
+ private
83
+
84
+ def padding(content)
85
+ return if content.empty?
86
+ padding = []
87
+ doc = Nokogiri::HTML::DocumentFragment.parse(content)
88
+ padding << "pt-4" if doc.children.first.name != "img"
89
+ padding << "pb-4" if doc.children.last.name != "img"
90
+ padding.join(" ")
91
+ end
92
+ end
data/lib/rui/flash.rb ADDED
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Flash < RUI::Base
4
+ def initialize(variant = "alert")
5
+ @variant = variant
6
+ end
7
+
8
+ def view_template
9
+ div(role: "alert", data: { controller: "flash" }, class: "lg:max-w-lg border p-3 lg:px-5 lg:py-3 rounded-lg opacity-0 transition-opacity duration-100 ease-in-out " + classes) do
10
+ div(class: "flex flex-row items-center justify-between gap-3") do
11
+ div(class: "w-6") { render RUI::Icon.new(icon) }
12
+ p(class: "w-full") { yield }
13
+ button(class: "w-6 hover:cursor-pointer", data: { action: "flash#close" }) do
14
+ render RUI::Icon.new("x")
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def classes = {
23
+ "notice" => "bg-blue-50 text-blue-900 border-blue-500",
24
+ "success" => "bg-green-50 text-green-900 border-green-500",
25
+ "alert" => "bg-yellow-50 text-yellow-900 border-yellow-500",
26
+ "failure" => "bg-red-50 text-red-900 border-red-500"
27
+ }.fetch @variant, "bg-zinc-50 text-zinc-900 border-zinc-500"
28
+
29
+ def icon = {
30
+ "notice" => "info-circle",
31
+ "success" => "circle-check",
32
+ "alert" => "alert-triangle",
33
+ "failure" => "flag"
34
+ }.fetch @variant, "alert-circle-filled"
35
+
36
+ class Wrapper < RUI::Base
37
+ def view_template(&)
38
+ div(class: "fixed left-0 lg:left-auto bottom-0 right-0 m-5 lg:m-10 flex flex-col gap-3", &)
39
+ end
40
+ end
41
+
42
+ module Helper
43
+ def success(message)
44
+ flash[:success] = message
45
+ end
46
+
47
+ def failure(message)
48
+ flash[:failure] = message
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Forms::Checkbox < RUI::Base
4
+ def initialize(**kwargs)
5
+ @kwargs = kwargs
6
+ end
7
+
8
+ def view_template(&)
9
+ div(class: "flex flex-row gap-3 items-center") do
10
+ input(
11
+ type: "hidden",
12
+ value: "0",
13
+ autocomplete: "off",
14
+ **@kwargs
15
+ )
16
+ input(
17
+ type: "checkbox",
18
+ value: "1",
19
+ class: "appearance-none size-4 border border-zinc-300 rounded hover:border-zinc-500 hover:cursor-pointer checked:bg-blue-700",
20
+ **@kwargs
21
+ )
22
+ render RUI::Forms::Label.new(&) if block_given?
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Forms::Email < RUI::Base
4
+ def initialize(**kwargs)
5
+ @kwargs = kwargs
6
+ end
7
+
8
+ def view_template(&)
9
+ render RUI::Forms::FieldGroup.new do
10
+ render RUI::Forms::Label.new(&) if block_given?
11
+ input(
12
+ type: "email",
13
+ class: "border border-zinc-300 hover:border-zinc-400 rounded px-2 py-1",
14
+ **@kwargs
15
+ )
16
+ end
17
+ div
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ class RUI::Forms::FieldGroup < RUI::Base
2
+ def view_template(&)
3
+ div(class: "flex flex-col gap-1", &)
4
+ end
5
+ end
@@ -0,0 +1,19 @@
1
+ module RUI::Forms::Helpers
2
+ DEFAULT_CLASSES = "flex flex-col gap-4".freeze
3
+
4
+ def rui_form_with(**options, &block)
5
+ if options.present? && options[:html][:class].present?
6
+ form_with_merged_classes(options[:html][:class], **options, &block)
7
+ else
8
+ # TODO: Remove reference to builder
9
+ form_with(**options.merge(builder: TailwindFormBuilder, html: { class: DEFAULT_CLASSES }), &block)
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def form_with_merged_classes(provided_classes, **options, &block)
16
+ css = RUI::TailwindMerger.instance.merge(DEFAULT_CLASSES, provided_classes)
17
+ form_with(**options.merge(html: { class: css }), &block)
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Forms::Label < RUI::Base
4
+ def view_template(&)
5
+ label(class: "text-sm font-semibold", &)
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Forms::Password < RUI::Base
4
+ def initialize(**kwargs)
5
+ @kwargs = kwargs
6
+ end
7
+
8
+ def view_template(&)
9
+ render RUI::Forms::FieldGroup.new do
10
+ render RUI::Forms::Label.new(&) if block_given?
11
+ input(
12
+ type: "password",
13
+ class: "border border-zinc-300 hover:border-zinc-400 rounded px-2 py-1",
14
+ **@kwargs
15
+ )
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Forms::Phone < RUI::Base
4
+ def initialize(**kwargs)
5
+ @kwargs = kwargs
6
+ end
7
+
8
+ def view_template(&)
9
+ render RUI::Forms::FieldGroup.new do
10
+ render RUI::Forms::Label.new(&) if block_given?
11
+ input(
12
+ type: :tel,
13
+ class: "border border-zinc-300 hover:border-zinc-400 rounded px-2 py-1",
14
+ **@kwargs
15
+ )
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Forms::Radio < RUI::Base
4
+ def initialize(label:, &)
5
+ @label = label
6
+ super(&)
7
+ end
8
+
9
+ def view_template
10
+ render RUI::Forms::FieldGroup.new do
11
+ render RUI::Forms::Label.new { @label }
12
+ yield
13
+ end
14
+ end
15
+
16
+ def option(**attrs, &)
17
+ div(class: "flex flex-row gap-3 items-center") do
18
+ input(class: "hover:cursor-pointer", type: :radio, **attrs)
19
+ label(&)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Forms::Select < RUI::Base
4
+ def initialize(label:, **attrs, &)
5
+ @label = label
6
+ @attrs = attrs
7
+ super(&)
8
+ end
9
+
10
+ def view_template(&)
11
+ render RUI::Forms::FieldGroup.new do
12
+ render RUI::Forms::Label.new { @label }
13
+ select(
14
+ class: "border border-zinc-300 hover:border-zinc-400 rounded px-2 py-1.5 hover:cursor-pointer",
15
+ **@attrs,
16
+ &
17
+ )
18
+ end
19
+ end
20
+
21
+ def option(**attrs, &)
22
+ tag(:option, **attrs, &)
23
+ end
24
+ end