Skip to content

Commit f9d703f

Browse files
authored
[Improvement] Add docs generator and button documentation (#335)
* Add docs generator and button documentation Introduce a new generator (`ruby_ui:install:docs`) that copies component documentation files from the gem to Rails applications. Documentation files follow the naming convention `{component}_docs.rb` and are copied to `app/views/docs/` with the `_docs` suffix removed. Usage: bin/rails g ruby_ui:install:docs bin/rails g ruby_ui:install:docs --force Include stub classes for docs dependencies (Views::Base, Docs::Header, Docs::VisualCodeExample, etc.) so docs files can be loaded without errors. Rails apps can override these with full implementations. Includes button component documentation as the first example. * Add documentation for batch 1 components (#336) Add docs files for: - accordion - alert - alert_dialog - aspect_ratio - avatar - badge - breadcrumb - calendar - card
1 parent 71a17c2 commit f9d703f

File tree

18 files changed

+996
-1
lines changed

18 files changed

+996
-1
lines changed

CONTRIBUTING.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,22 @@ While we don't have specific test coverage requirements, all contributions shoul
4141

4242
If your changes include new components, modify how components should be used, or add new behaviors, it is highly recommended to also open a PR on the [ruby-ui/web](https://github.com/ruby-ui/web) repository. This ensures the documentation website stays up-to-date with the latest component changes.
4343

44+
### Installing Documentation Files
45+
46+
RubyUI includes documentation files for each component that can be installed into your Rails application. These files are located at `lib/ruby_ui/{component}/{component}_docs.rb` and provide usage examples for each component.
47+
48+
To install the documentation files:
49+
50+
```bash
51+
bin/rails g ruby_ui:install:docs
52+
```
53+
54+
To overwrite existing documentation files:
55+
56+
```bash
57+
bin/rails g ruby_ui:install:docs --force
58+
```
59+
60+
This will copy the documentation files to `app/views/docs/` in your Rails application.
61+
4462
Thank you for contributing to make RubyUI better!
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# frozen_string_literal: true
2+
3+
require "rails/generators"
4+
5+
module RubyUI
6+
module Generators
7+
module Install
8+
class DocsGenerator < Rails::Generators::Base
9+
namespace "ruby_ui:install:docs"
10+
source_root File.expand_path("../../../ruby_ui", __dir__)
11+
class_option :force, type: :boolean, default: false
12+
13+
def copy_docs_files
14+
say "Installing RubyUI documentation files..."
15+
16+
docs_file_paths.each do |source_path|
17+
dest_filename = File.basename(source_path).sub("_docs", "")
18+
copy_file source_path, Rails.root.join("app/views/docs", dest_filename), force: options["force"]
19+
end
20+
21+
say ""
22+
say "Documentation installed to app/views/docs/", :green
23+
end
24+
25+
private
26+
27+
def docs_file_paths
28+
Dir.glob(File.join(self.class.source_root, "*", "*_docs.rb"))
29+
end
30+
end
31+
end
32+
end
33+
end
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# frozen_string_literal: true
2+
3+
class Views::Docs::Accordion < Views::Base
4+
def view_template
5+
div(class: "max-w-2xl mx-auto w-full py-10 space-y-10") do
6+
component = "Accordion"
7+
render Docs::Header.new(title: component,
8+
description: "A vertically stacked set of interactive headings that each reveal a section of content.")
9+
10+
Heading(level: 2) { "Usage" }
11+
12+
render Docs::VisualCodeExample.new(title: "Example", context: self) do
13+
@@code = <<~RUBY
14+
div(class: "w-full") do
15+
Accordion do
16+
AccordionItem do
17+
AccordionTrigger do
18+
p(class: "font-medium") { "What is PhlexUI?" }
19+
AccordionIcon()
20+
end
21+
22+
AccordionContent do
23+
p(class: "text-sm pb-4") do
24+
"PhlexUI is a UI component library for Ruby devs who want to build better, faster."
25+
end
26+
end
27+
end
28+
end
29+
30+
Accordion do
31+
AccordionItem do
32+
AccordionTrigger do
33+
p(class: "font-medium") { "Can I use it with Rails?" }
34+
AccordionIcon()
35+
end
36+
37+
AccordionContent do
38+
p(class: "text-sm pb-4") do
39+
"Yes, PhlexUI is pure Ruby and works great with Rails. It's a Ruby gem that you can install into your Rails app."
40+
end
41+
end
42+
end
43+
end
44+
end
45+
RUBY
46+
end
47+
48+
render Components::ComponentSetup::Tabs.new(component_name: component)
49+
50+
render Docs::ComponentsTable.new(component_files(component))
51+
end
52+
end
53+
end

lib/ruby_ui/alert/alert_docs.rb

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# frozen_string_literal: true
2+
3+
class Views::Docs::Alert < Views::Base
4+
def view_template
5+
component = "Alert"
6+
div(class: "max-w-2xl mx-auto w-full py-10 space-y-10") do
7+
render Docs::Header.new(title: "Alert", description: "Displays a callout for user attention.")
8+
9+
Heading(level: 2) { "Usage" }
10+
11+
render Docs::VisualCodeExample.new(title: "Example", context: self) do
12+
<<~RUBY
13+
Alert do
14+
rocket_icon
15+
AlertTitle { "Pro tip" }
16+
AlertDescription { "With RubyUI you'll ship faster." }
17+
end
18+
RUBY
19+
end
20+
21+
render Docs::VisualCodeExample.new(title: "Without Icon", context: self) do
22+
<<~RUBY
23+
Alert do
24+
AlertTitle { "Pro tip" }
25+
AlertDescription { "Simply, don't include an icon and your alert will look like this." }
26+
end
27+
RUBY
28+
end
29+
30+
render Docs::VisualCodeExample.new(title: "Warning", context: self) do
31+
<<~RUBY
32+
Alert(variant: :warning) do
33+
info_icon
34+
AlertTitle { "Ship often" }
35+
AlertDescription { "Shipping is good, your users will thank you for it." }
36+
end
37+
RUBY
38+
end
39+
40+
render Docs::VisualCodeExample.new(title: "Destructive", context: self) do
41+
<<~RUBY
42+
Alert(variant: :destructive) do
43+
alert_icon
44+
AlertTitle { "Oopsie daisy!" }
45+
AlertDescription { "Your design system is non-existent." }
46+
end
47+
RUBY
48+
end
49+
50+
render Docs::VisualCodeExample.new(title: "Success", context: self) do
51+
<<~RUBY
52+
Alert(variant: :success) do
53+
check_icon
54+
AlertTitle { "Installation successful" }
55+
AlertDescription { "You're all set to start using RubyUI in your application." }
56+
end
57+
RUBY
58+
end
59+
60+
render Components::ComponentSetup::Tabs.new(component_name: component)
61+
62+
render Docs::ComponentsTable.new(component_files(component))
63+
end
64+
end
65+
66+
private
67+
68+
def rocket_icon
69+
svg(
70+
xmlns: "http://www.w3.org/2000/svg",
71+
viewbox: "0 0 24 24",
72+
fill: "currentColor",
73+
class: "w-5 h-5"
74+
) do |s|
75+
s.path(
76+
fill_rule: "evenodd",
77+
d:
78+
"M9.315 7.584C12.195 3.883 16.695 1.5 21.75 1.5a.75.75 0 01.75.75c0 5.056-2.383 9.555-6.084 12.436A6.75 6.75 0 019.75 22.5a.75.75 0 01-.75-.75v-4.131A15.838 15.838 0 016.382 15H2.25a.75.75 0 01-.75-.75 6.75 6.75 0 017.815-6.666zM15 6.75a2.25 2.25 0 100 4.5 2.25 2.25 0 000-4.5z",
79+
clip_rule: "evenodd"
80+
)
81+
s.path(
82+
d:
83+
"M5.26 17.242a.75.75 0 10-.897-1.203 5.243 5.243 0 00-2.05 5.022.75.75 0 00.625.627 5.243 5.243 0 005.022-2.051.75.75 0 10-1.202-.897 3.744 3.744 0 01-3.008 1.51c0-1.23.592-2.323 1.51-3.008z"
84+
)
85+
end
86+
end
87+
88+
def alert_icon
89+
svg(
90+
xmlns: "http://www.w3.org/2000/svg",
91+
viewbox: "0 0 24 24",
92+
fill: "currentColor",
93+
class: "w-5 h-5"
94+
) do |s|
95+
s.path(
96+
fill_rule: "evenodd",
97+
d:
98+
"M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z",
99+
clip_rule: "evenodd"
100+
)
101+
end
102+
end
103+
104+
def info_icon
105+
svg(
106+
xmlns: "http://www.w3.org/2000/svg",
107+
viewbox: "0 0 24 24",
108+
fill: "currentColor",
109+
class: "w-5 h-5"
110+
) do |s|
111+
s.path(
112+
fill_rule: "evenodd",
113+
d:
114+
"M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 01.67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 11-.671-1.34l.041-.022zM12 9a.75.75 0 100-1.5.75.75 0 000 1.5z",
115+
clip_rule: "evenodd"
116+
)
117+
end
118+
end
119+
120+
def check_icon
121+
svg(
122+
xmlns: "http://www.w3.org/2000/svg",
123+
viewbox: "0 0 24 24",
124+
fill: "currentColor",
125+
class: "w-5 h-5"
126+
) do |s|
127+
s.path(
128+
fill_rule: "evenodd",
129+
d:
130+
"M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm13.36-1.814a.75.75 0 10-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 00-1.06 1.06l2.25 2.25a.75.75 0 001.14-.094l3.75-5.25z",
131+
clip_rule: "evenodd"
132+
)
133+
end
134+
end
135+
end
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# frozen_string_literal: true
2+
3+
class Views::Docs::AlertDialog < Views::Base
4+
def view_template
5+
component = "AlertDialog"
6+
div(class: "max-w-2xl mx-auto w-full py-10 space-y-10") do
7+
render Docs::Header.new(title: "Alert Dialog", description: "A modal dialog that interrupts the user with important content and expects a response.")
8+
9+
Heading(level: 2) { "Usage" }
10+
render Docs::VisualCodeExample.new(title: "Example", context: self) do
11+
<<~RUBY
12+
AlertDialog do
13+
AlertDialogTrigger do
14+
Button { "Show dialog" }
15+
end
16+
AlertDialogContent do
17+
AlertDialogHeader do
18+
AlertDialogTitle { "Are you absolutely sure?" }
19+
AlertDialogDescription { "This action cannot be undone. This will permanently delete your account and remove your data from our servers." }
20+
end
21+
AlertDialogFooter do
22+
AlertDialogCancel { "Cancel" }
23+
AlertDialogAction { "Continue" } # Will probably be a link to a controller action (e.g. delete account)
24+
end
25+
end
26+
end
27+
RUBY
28+
end
29+
30+
render Components::ComponentSetup::Tabs.new(component_name: component)
31+
32+
render Docs::ComponentsTable.new(component_files(component))
33+
end
34+
end
35+
end
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# frozen_string_literal: true
2+
3+
class Views::Docs::AspectRatio < Views::Base
4+
def view_template
5+
component = "AspectRatio"
6+
div(class: "max-w-2xl mx-auto w-full py-10 space-y-10") do
7+
render Docs::Header.new(title: "Aspect Ratio", description: "Displays content within a desired ratio.")
8+
9+
Heading(level: 2) { "Usage" }
10+
11+
render Docs::VisualCodeExample.new(title: "16/9", context: self) do
12+
<<~RUBY
13+
AspectRatio(aspect_ratio: "16/9", class: "rounded-md overflow-hidden border shadow-sm") do
14+
img(
15+
alt: "Placeholder",
16+
loading: "lazy",
17+
src: image_path('pattern.jpg')
18+
)
19+
end
20+
RUBY
21+
end
22+
23+
render Docs::VisualCodeExample.new(title: "4/3", context: self) do
24+
<<~RUBY
25+
AspectRatio(aspect_ratio: "4/3", class: "rounded-md overflow-hidden border shadow-sm") do
26+
img(
27+
alt: "Placeholder",
28+
loading: "lazy",
29+
src: image_path('pattern.jpg')
30+
)
31+
end
32+
RUBY
33+
end
34+
35+
render Docs::VisualCodeExample.new(title: "1/1", context: self) do
36+
<<~RUBY
37+
AspectRatio(aspect_ratio: "1/1", class: "rounded-md overflow-hidden border shadow-sm") do
38+
img(
39+
alt: "Placeholder",
40+
loading: "lazy",
41+
src: image_path('pattern.jpg')
42+
)
43+
end
44+
RUBY
45+
end
46+
47+
render Docs::VisualCodeExample.new(title: "21/9", context: self) do
48+
<<~RUBY
49+
AspectRatio(aspect_ratio: "21/9", class: "rounded-md overflow-hidden border shadow-sm") do
50+
img(
51+
alt: "Placeholder",
52+
loading: "lazy",
53+
src: image_path('pattern.jpg')
54+
)
55+
end
56+
RUBY
57+
end
58+
59+
render Components::ComponentSetup::Tabs.new(component_name: component)
60+
61+
render Docs::ComponentsTable.new(component_files(component))
62+
end
63+
end
64+
end

0 commit comments

Comments
 (0)