ruby_ui 1.0.2 → 1.1.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/LICENSE.txt +1 -1
- data/README.md +4 -0
- data/lib/generators/ruby_ui/install/docs_generator.rb +33 -0
- data/lib/ruby_ui/accordion/accordion_docs.rb +53 -0
- data/lib/ruby_ui/alert/alert_docs.rb +135 -0
- data/lib/ruby_ui/alert_dialog/alert_dialog_docs.rb +35 -0
- data/lib/ruby_ui/aspect_ratio/aspect_ratio_docs.rb +64 -0
- data/lib/ruby_ui/avatar/avatar_docs.rb +92 -0
- data/lib/ruby_ui/badge/badge_docs.rb +80 -0
- data/lib/ruby_ui/breadcrumb/breadcrumb_docs.rb +116 -0
- data/lib/ruby_ui/button/button_docs.rb +143 -0
- data/lib/ruby_ui/calendar/calendar_docs.rb +34 -0
- data/lib/ruby_ui/card/card_docs.rb +114 -0
- data/lib/ruby_ui/carousel/carousel_docs.rb +104 -0
- data/lib/ruby_ui/chart/chart_docs.rb +115 -0
- data/lib/ruby_ui/checkbox/checkbox.rb +2 -2
- data/lib/ruby_ui/checkbox/checkbox_docs.rb +41 -0
- data/lib/ruby_ui/clipboard/clipboard_docs.rb +30 -0
- data/lib/ruby_ui/codeblock/codeblock_docs.rb +55 -0
- data/lib/ruby_ui/collapsible/collapsible_docs.rb +96 -0
- data/lib/ruby_ui/combobox/combobox_controller.js +16 -1
- data/lib/ruby_ui/combobox/combobox_docs.rb +151 -0
- data/lib/ruby_ui/combobox/combobox_popover.rb +2 -1
- data/lib/ruby_ui/combobox/combobox_toggle_all_checkbox.rb +3 -2
- data/lib/ruby_ui/combobox/combobox_trigger.rb +1 -1
- data/lib/ruby_ui/command/command_docs.rb +154 -0
- data/lib/ruby_ui/context_menu/context_menu.rb +1 -1
- data/lib/ruby_ui/context_menu/context_menu_docs.rb +85 -0
- data/lib/ruby_ui/dialog/dialog_docs.rb +102 -0
- data/lib/ruby_ui/docs/base.rb +90 -0
- data/lib/ruby_ui/docs/component_setup_tabs.rb +15 -0
- data/lib/ruby_ui/docs/components_table.rb +13 -0
- data/lib/ruby_ui/docs/header.rb +17 -0
- data/lib/ruby_ui/docs/sidebar_examples.rb +22 -0
- data/lib/ruby_ui/docs/visual_code_example.rb +22 -0
- data/lib/ruby_ui/dropdown_menu/dropdown_menu_docs.rb +212 -0
- data/lib/ruby_ui/form/form_docs.rb +178 -0
- data/lib/ruby_ui/form/form_field.rb +1 -1
- data/lib/ruby_ui/form/form_field_error.rb +1 -1
- data/lib/ruby_ui/form/form_field_hint.rb +1 -1
- data/lib/ruby_ui/form/form_field_label.rb +1 -1
- data/lib/ruby_ui/hover_card/hover_card_docs.rb +71 -0
- data/lib/ruby_ui/input/input.rb +4 -3
- data/lib/ruby_ui/input/input_docs.rb +68 -0
- data/lib/ruby_ui/link/link_docs.rb +106 -0
- data/lib/ruby_ui/masked_input/masked_input_docs.rb +47 -0
- data/lib/ruby_ui/pagination/pagination_docs.rb +127 -0
- data/lib/ruby_ui/popover/popover_docs.rb +971 -0
- data/lib/ruby_ui/progress/progress_docs.rb +27 -0
- data/lib/ruby_ui/radio_button/radio_button.rb +1 -1
- data/lib/ruby_ui/radio_button/radio_button_docs.rb +53 -0
- data/lib/ruby_ui/select/select_docs.rb +129 -0
- data/lib/ruby_ui/separator/separator_docs.rb +36 -0
- data/lib/ruby_ui/sheet/sheet_content.rb +1 -1
- data/lib/ruby_ui/sheet/sheet_docs.rb +76 -0
- data/lib/ruby_ui/shortcut_key/shortcut_key_docs.rb +29 -0
- data/lib/ruby_ui/sidebar/sidebar_docs.rb +176 -0
- data/lib/ruby_ui/skeleton/skeleton_docs.rb +29 -0
- data/lib/ruby_ui/switch/switch_docs.rb +46 -0
- data/lib/ruby_ui/table/table_docs.rb +102 -0
- data/lib/ruby_ui/tabs/tabs_docs.rb +211 -0
- data/lib/ruby_ui/textarea/textarea_docs.rb +54 -0
- data/lib/ruby_ui/theme_toggle/theme_toggle_docs.rb +71 -0
- data/lib/ruby_ui/tooltip/tooltip_docs.rb +52 -0
- data/lib/ruby_ui/typography/typography_docs.rb +107 -0
- data/lib/ruby_ui.rb +1 -1
- metadata +53 -6
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Views
|
|
4
|
+
class Base < Phlex::HTML
|
|
5
|
+
def Heading(level:, &)
|
|
6
|
+
tag = :"h#{level}"
|
|
7
|
+
send(tag, &)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def component_files(component_name)
|
|
11
|
+
[]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Text helper for wrapping paragraphs
|
|
15
|
+
def Text(&)
|
|
16
|
+
p(&)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# InlineLink helper for documentation links
|
|
20
|
+
def InlineLink(href:, target: nil, class: nil, &)
|
|
21
|
+
a(href: href, target: target, class: binding.local_variable_get(:class), &)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Alert component helpers
|
|
25
|
+
def Alert(&)
|
|
26
|
+
div(&)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def AlertTitle(&)
|
|
30
|
+
h4(&)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def AlertDescription(&)
|
|
34
|
+
p(&)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Route helper stubs - return "#" as placeholder
|
|
38
|
+
def docs_sheet_path
|
|
39
|
+
"#"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def docs_separator_path
|
|
43
|
+
"#"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def docs_accordion_path
|
|
47
|
+
"#"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def docs_alert_path
|
|
51
|
+
"#"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def docs_alert_dialog_path
|
|
55
|
+
"#"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def docs_aspect_ratio_path
|
|
59
|
+
"#"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def docs_avatar_path
|
|
63
|
+
"#"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def docs_badge_path
|
|
67
|
+
"#"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def docs_installation_path
|
|
71
|
+
"#"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# InlineCode helper for typography examples
|
|
75
|
+
def InlineCode(&)
|
|
76
|
+
code(&)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Module-level components stub
|
|
82
|
+
module Components
|
|
83
|
+
def self.Heading(level:, &block)
|
|
84
|
+
# Stub for module-level Heading calls
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def self.TypographyList(items:, numbered: false)
|
|
88
|
+
# Stub for TypographyList component
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Components
|
|
4
|
+
module ComponentSetup
|
|
5
|
+
class Tabs < Phlex::HTML
|
|
6
|
+
def initialize(component_name:)
|
|
7
|
+
@component_name = component_name
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template
|
|
11
|
+
# Minimal stub - empty by default
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docs
|
|
4
|
+
class Header < Phlex::HTML
|
|
5
|
+
def initialize(title:, description: nil)
|
|
6
|
+
@title = title
|
|
7
|
+
@description = description
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template
|
|
11
|
+
div do
|
|
12
|
+
h1 { @title }
|
|
13
|
+
p { @description } if @description
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Stub constants for sidebar documentation examples
|
|
4
|
+
# These are replaced with actual implementations in the web app
|
|
5
|
+
|
|
6
|
+
module Views
|
|
7
|
+
module Docs
|
|
8
|
+
class Sidebar < Views::Base
|
|
9
|
+
class Example
|
|
10
|
+
CODE = <<~RUBY
|
|
11
|
+
# Sidebar example code placeholder
|
|
12
|
+
RUBY
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class InsetExample
|
|
16
|
+
CODE = <<~RUBY
|
|
17
|
+
# Sidebar inset example code placeholder
|
|
18
|
+
RUBY
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docs
|
|
4
|
+
class VisualCodeExample < Phlex::HTML
|
|
5
|
+
def initialize(title:, context:, description: nil, src: nil)
|
|
6
|
+
@title = title
|
|
7
|
+
@context = context
|
|
8
|
+
@description = description
|
|
9
|
+
@src = src
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def view_template(&block)
|
|
13
|
+
code = block.call
|
|
14
|
+
div do
|
|
15
|
+
h3 { @title }
|
|
16
|
+
p { @description } if @description
|
|
17
|
+
pre { code }
|
|
18
|
+
@context.instance_eval(code)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Views::Docs::DropdownMenu < Views::Base
|
|
4
|
+
def view_template
|
|
5
|
+
component = "DropdownMenu"
|
|
6
|
+
div(class: "max-w-2xl mx-auto w-full py-10 space-y-10") do
|
|
7
|
+
render Docs::Header.new(title: "Dropdown Menu", description: "Displays a menu to the user — such as a set of actions or functions — triggered by a button.")
|
|
8
|
+
|
|
9
|
+
Heading(level: 2) { "Usage" }
|
|
10
|
+
|
|
11
|
+
render Docs::VisualCodeExample.new(title: "Example", context: self) do
|
|
12
|
+
<<~RUBY
|
|
13
|
+
DropdownMenu do
|
|
14
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
15
|
+
Button(variant: :outline) { "Open" }
|
|
16
|
+
end
|
|
17
|
+
DropdownMenuContent do
|
|
18
|
+
DropdownMenuLabel { "My Account" }
|
|
19
|
+
DropdownMenuSeparator
|
|
20
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
21
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
22
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
23
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
RUBY
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
render Docs::VisualCodeExample.new(title: "Placement", description: "If the DropdownMenu conflicts with edge, it will auto-adjust it's placement", context: self) do
|
|
30
|
+
<<~RUBY
|
|
31
|
+
div(class: 'grid grid-cols-1 sm:grid-cols-3 gap-4') do
|
|
32
|
+
# -- TOP --
|
|
33
|
+
DropdownMenu(options: { placement: 'top' }) do
|
|
34
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
35
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'top' }
|
|
36
|
+
end
|
|
37
|
+
DropdownMenuContent do
|
|
38
|
+
DropdownMenuLabel { "My Account" }
|
|
39
|
+
DropdownMenuSeparator
|
|
40
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
41
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
42
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
43
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
DropdownMenu(options: { placement: 'top-start' }) do
|
|
48
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
49
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'top-start' }
|
|
50
|
+
end
|
|
51
|
+
DropdownMenuContent do
|
|
52
|
+
DropdownMenuLabel { "My Account" }
|
|
53
|
+
DropdownMenuSeparator
|
|
54
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
55
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
56
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
57
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
DropdownMenu(options: { placement: 'top-end' }) do
|
|
62
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
63
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'top-end' }
|
|
64
|
+
end
|
|
65
|
+
DropdownMenuContent do
|
|
66
|
+
DropdownMenuLabel { "My Account" }
|
|
67
|
+
DropdownMenuSeparator
|
|
68
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
69
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
70
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
71
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# -- BOTTOM --
|
|
76
|
+
DropdownMenu(options: { placement: 'bottom' }) do
|
|
77
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
78
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'bottom' }
|
|
79
|
+
end
|
|
80
|
+
DropdownMenuContent do
|
|
81
|
+
DropdownMenuLabel { "My Account" }
|
|
82
|
+
DropdownMenuSeparator
|
|
83
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
84
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
85
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
86
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
DropdownMenu(options: { placement: 'bottom-start' }) do
|
|
91
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
92
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'bottom-start' }
|
|
93
|
+
end
|
|
94
|
+
DropdownMenuContent do
|
|
95
|
+
DropdownMenuLabel { "My Account" }
|
|
96
|
+
DropdownMenuSeparator
|
|
97
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
98
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
99
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
100
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
DropdownMenu(options: { placement: 'bottom-end' }) do
|
|
105
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
106
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'bottom-end' }
|
|
107
|
+
end
|
|
108
|
+
DropdownMenuContent do
|
|
109
|
+
DropdownMenuLabel { "My Account" }
|
|
110
|
+
DropdownMenuSeparator
|
|
111
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
112
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
113
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
114
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# -- LEFT --
|
|
119
|
+
DropdownMenu(options: { placement: 'left' }) do
|
|
120
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
121
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'left' }
|
|
122
|
+
end
|
|
123
|
+
DropdownMenuContent do
|
|
124
|
+
DropdownMenuLabel { "My Account" }
|
|
125
|
+
DropdownMenuSeparator
|
|
126
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
127
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
128
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
129
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
DropdownMenu(options: { placement: 'left-start' }) do
|
|
134
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
135
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'left-start' }
|
|
136
|
+
end
|
|
137
|
+
DropdownMenuContent do
|
|
138
|
+
DropdownMenuLabel { "My Account" }
|
|
139
|
+
DropdownMenuSeparator
|
|
140
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
141
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
142
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
143
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
DropdownMenu(options: { placement: 'left-end' }) do
|
|
148
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
149
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'left-end' }
|
|
150
|
+
end
|
|
151
|
+
DropdownMenuContent do
|
|
152
|
+
DropdownMenuLabel { "My Account" }
|
|
153
|
+
DropdownMenuSeparator
|
|
154
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
155
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
156
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
157
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# -- RIGHT --
|
|
162
|
+
DropdownMenu(options: { placement: 'right' }) do
|
|
163
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
164
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'right' }
|
|
165
|
+
end
|
|
166
|
+
DropdownMenuContent do
|
|
167
|
+
DropdownMenuLabel { "My Account" }
|
|
168
|
+
DropdownMenuSeparator
|
|
169
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
170
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
171
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
172
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
DropdownMenu(options: { placement: 'right-start' }) do
|
|
177
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
178
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'right-start' }
|
|
179
|
+
end
|
|
180
|
+
DropdownMenuContent do
|
|
181
|
+
DropdownMenuLabel { "My Account" }
|
|
182
|
+
DropdownMenuSeparator
|
|
183
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
184
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
185
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
186
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
DropdownMenu(options: { placement: 'right-end' }) do
|
|
191
|
+
DropdownMenuTrigger(class: 'w-full') do
|
|
192
|
+
Button(variant: :outline, class: 'w-full justify-center') { 'right-end' }
|
|
193
|
+
end
|
|
194
|
+
DropdownMenuContent do
|
|
195
|
+
DropdownMenuLabel { "My Account" }
|
|
196
|
+
DropdownMenuSeparator
|
|
197
|
+
DropdownMenuItem(href: '#') { "Profile" }
|
|
198
|
+
DropdownMenuItem(href: '#') { "Billing" }
|
|
199
|
+
DropdownMenuItem(href: '#') { "Team" }
|
|
200
|
+
DropdownMenuItem(href: '#') { "Subscription" }
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
RUBY
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
render Components::ComponentSetup::Tabs.new(component_name: component)
|
|
208
|
+
|
|
209
|
+
render Docs::ComponentsTable.new(component_files(component))
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Views::Docs::Form < Views::Base
|
|
4
|
+
def view_template
|
|
5
|
+
component = "Form"
|
|
6
|
+
div(class: "max-w-2xl mx-auto w-full py-10 space-y-10") do
|
|
7
|
+
render Docs::Header.new(title: "Form", description: "Building forms with built-in client-side validations.")
|
|
8
|
+
|
|
9
|
+
Heading(level: 2) { "Usage" }
|
|
10
|
+
|
|
11
|
+
render Docs::VisualCodeExample.new(title: "Example", context: self) do
|
|
12
|
+
<<~RUBY
|
|
13
|
+
Form(class: "w-2/3 space-y-6") do
|
|
14
|
+
FormField do
|
|
15
|
+
FormFieldLabel { "Default error" }
|
|
16
|
+
Input(placeholder: "Joel Drapper", required: true, minlength: "3") { "Joel Drapper" }
|
|
17
|
+
FormFieldHint()
|
|
18
|
+
FormFieldError()
|
|
19
|
+
end
|
|
20
|
+
Button(type: "submit") { "Save" }
|
|
21
|
+
end
|
|
22
|
+
RUBY
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
render Docs::VisualCodeExample.new(title: "Disabled", context: self) do
|
|
26
|
+
<<~RUBY
|
|
27
|
+
FormField do
|
|
28
|
+
FormFieldLabel { "Disabled" }
|
|
29
|
+
Input(disabled: true, placeholder: "Joel Drapper", required: true, minlength: "3") { "Joel Drapper" }
|
|
30
|
+
end
|
|
31
|
+
RUBY
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
render Docs::VisualCodeExample.new(title: "Aria Disabled", context: self) do
|
|
35
|
+
<<~RUBY
|
|
36
|
+
FormField do
|
|
37
|
+
FormFieldLabel { "Aria Disabled" }
|
|
38
|
+
Input(aria: {disabled: "true"}, placeholder: "Joel Drapper", required: true, minlength: "3") { "Joel Drapper" }
|
|
39
|
+
end
|
|
40
|
+
RUBY
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
render Docs::VisualCodeExample.new(title: "Custom error message", context: self) do
|
|
44
|
+
<<~RUBY
|
|
45
|
+
Form(class: "w-2/3 space-y-6") do
|
|
46
|
+
FormField do
|
|
47
|
+
FormFieldLabel { "Custom error message" }
|
|
48
|
+
Input(placeholder: "joel@drapper.me", required: true, data_value_missing: "Custom error message")
|
|
49
|
+
FormFieldError()
|
|
50
|
+
end
|
|
51
|
+
Button(type: "submit") { "Save" }
|
|
52
|
+
end
|
|
53
|
+
RUBY
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
render Docs::VisualCodeExample.new(title: "Backend error", context: self) do
|
|
57
|
+
<<~RUBY
|
|
58
|
+
Form(class: "w-2/3 space-y-6") do
|
|
59
|
+
FormField do
|
|
60
|
+
FormFieldLabel { "Backend error" }
|
|
61
|
+
Input(placeholder: "Joel Drapper", required: true)
|
|
62
|
+
FormFieldError { "Error from backend" }
|
|
63
|
+
end
|
|
64
|
+
Button(type: "submit") { "Save" }
|
|
65
|
+
end
|
|
66
|
+
RUBY
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
render Docs::VisualCodeExample.new(title: "Checkbox", context: self) do
|
|
70
|
+
<<~RUBY
|
|
71
|
+
Form(class: "w-2/3 space-y-6") do
|
|
72
|
+
FormField do
|
|
73
|
+
Checkbox(required: true)
|
|
74
|
+
label(
|
|
75
|
+
class:
|
|
76
|
+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
77
|
+
) { " Accept terms and conditions " }
|
|
78
|
+
FormFieldError()
|
|
79
|
+
end
|
|
80
|
+
Button(type: "submit") { "Save" }
|
|
81
|
+
end
|
|
82
|
+
RUBY
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
render Docs::VisualCodeExample.new(title: "Select", context: self) do
|
|
86
|
+
<<~RUBY
|
|
87
|
+
Form(class: "w-2/3 space-y-6") do
|
|
88
|
+
FormField do
|
|
89
|
+
FormFieldLabel { "Select" }
|
|
90
|
+
Select do
|
|
91
|
+
SelectInput(required: true)
|
|
92
|
+
SelectTrigger do
|
|
93
|
+
SelectValue(placeholder: "Select a fruit")
|
|
94
|
+
end
|
|
95
|
+
SelectContent() do
|
|
96
|
+
SelectGroup do
|
|
97
|
+
SelectLabel { "Fruits" }
|
|
98
|
+
SelectItem(value: "apple") { "Apple" }
|
|
99
|
+
SelectItem(value: "orange") { "Orange" }
|
|
100
|
+
SelectItem(value: "banana") { "Banana" }
|
|
101
|
+
SelectItem(value: "watermelon") { "Watermelon" }
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
FormFieldError()
|
|
106
|
+
end
|
|
107
|
+
Button(type: "submit") { "Save" }
|
|
108
|
+
end
|
|
109
|
+
RUBY
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
render Docs::VisualCodeExample.new(title: "Combobox", context: self) do
|
|
113
|
+
<<~RUBY
|
|
114
|
+
Form(class: "w-2/3 space-y-6") do
|
|
115
|
+
FormField do
|
|
116
|
+
FormFieldLabel { "Combobox" }
|
|
117
|
+
|
|
118
|
+
Combobox do
|
|
119
|
+
ComboboxTrigger placeholder: "Pick value"
|
|
120
|
+
|
|
121
|
+
ComboboxPopover do
|
|
122
|
+
ComboboxSearchInput(placeholder: "Pick value or type anything")
|
|
123
|
+
|
|
124
|
+
ComboboxList do
|
|
125
|
+
ComboboxEmptyState { "No result" }
|
|
126
|
+
|
|
127
|
+
ComboboxListGroup label: "Fruits" do
|
|
128
|
+
ComboboxItem do
|
|
129
|
+
ComboboxRadio(name: "food", value: "apple", required: true)
|
|
130
|
+
span { "Apple" }
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
ComboboxItem do
|
|
134
|
+
ComboboxRadio(name: "food", value: "banana", required: true)
|
|
135
|
+
span { "Banana" }
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
ComboboxListGroup label: "Vegetable" do
|
|
140
|
+
ComboboxItem do
|
|
141
|
+
ComboboxRadio(name: "food", value: "brocoli", required: true)
|
|
142
|
+
span { "Broccoli" }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
ComboboxItem do
|
|
146
|
+
ComboboxRadio(name: "food", value: "carrot", required: true)
|
|
147
|
+
span { "Carrot" }
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
ComboboxListGroup label: "Others" do
|
|
152
|
+
ComboboxItem do
|
|
153
|
+
ComboboxRadio(name: "food", value: "chocolate", required: true)
|
|
154
|
+
span { "Chocolate" }
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
ComboboxItem do
|
|
158
|
+
ComboboxRadio(name: "food", value: "milk", required: true)
|
|
159
|
+
span { "Milk" }
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
FormFieldError()
|
|
167
|
+
end
|
|
168
|
+
Button(type: "submit") { "Save" }
|
|
169
|
+
end
|
|
170
|
+
RUBY
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
render Components::ComponentSetup::Tabs.new(component_name: component)
|
|
174
|
+
|
|
175
|
+
render Docs::ComponentsTable.new(component_files(component))
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
@@ -11,7 +11,7 @@ module RubyUI
|
|
|
11
11
|
def default_attrs
|
|
12
12
|
{
|
|
13
13
|
class: [
|
|
14
|
-
"text-sm font-medium leading-none",
|
|
14
|
+
"empty:hidden text-sm font-medium leading-none",
|
|
15
15
|
"peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
16
16
|
"peer-aria-disabled:cursor-not-allowed peer-aria-disabled:opacity-70 peer-aria-disabled:pointer-events-none"
|
|
17
17
|
]
|