shadcn-ui 0.0.2 → 0.0.4
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/.env +1 -0
- data/Rakefile +6 -3
- data/app/assets/stylesheets/{application.scss → application.css} +0 -27
- data/app/assets/stylesheets/application.tailwind.css +32 -160
- data/app/assets/stylesheets/shadcn.css +216 -0
- data/app/helpers/components/accordion_helper.rb +14 -1
- data/app/helpers/components/alert_helper.rb +4 -2
- data/app/helpers/components/button_helper.rb +2 -1
- data/app/helpers/components/card_helper.rb +1 -1
- data/app/helpers/components/checkbox_helper.rb +2 -2
- data/app/helpers/components/collapsible_helper.rb +8 -0
- data/app/helpers/components/input_helper.rb +1 -1
- data/app/helpers/components/sheet_helper.rb +9 -0
- data/app/helpers/components/slider_helper.rb +1 -1
- data/app/helpers/components_helper.rb +11 -0
- data/app/helpers/examples_helper.rb +7 -3
- data/app/javascript/controllers/highlight_controller.js +0 -1
- data/app/javascript/controllers/ui/popover_controller.js +6 -2
- data/app/views/application/index.html.erb +625 -17
- data/app/views/components/ui/_accordion.html.erb +2 -2
- data/app/views/components/ui/_alert.html.erb +15 -3
- data/app/views/components/ui/_card.html.erb +7 -1
- data/app/views/components/ui/_checkbox.html.erb +2 -1
- data/app/views/components/ui/_collapsible.html.erb +2 -6
- data/app/views/components/ui/_filter.html.erb +2 -1
- data/app/views/components/ui/_sheet.html.erb +1 -1
- data/app/views/documentation/generators.html.md +21 -0
- data/app/views/documentation/helpers.html.md +54 -0
- data/app/views/documentation/index.html.md +22 -0
- data/app/views/documentation/installation.html.md +130 -2
- data/app/views/documentation/javascript.html.md +8 -0
- data/app/views/examples/components/accordion/_usage.html.erb +15 -0
- data/app/views/examples/components/accordion/code/_block.html.erb +8 -0
- data/app/views/examples/components/accordion/code/_description.html.erb +7 -0
- data/app/views/examples/components/accordion/code/_preview.erb +3 -0
- data/app/views/examples/components/accordion/code/_usage.erb +16 -0
- data/app/views/examples/components/accordion.html.erb +37 -3
- data/app/views/examples/components/alert/_usage.html.erb +10 -0
- data/app/views/examples/components/alert/code/_attention.erb +3 -0
- data/app/views/examples/components/alert/code/_destructive.erb +2 -0
- data/app/views/examples/components/alert/code/_info.erb +3 -0
- data/app/views/examples/components/alert/code/_no_icon.erb +3 -0
- data/app/views/examples/components/alert/code/_preview.erb +2 -0
- data/app/views/examples/components/alert/code/_success.erb +3 -0
- data/app/views/examples/components/alert/code/_usage.erb +1 -0
- data/app/views/examples/components/alert-dialog/code/_preview.erb +6 -0
- data/app/views/examples/components/alert-dialog/code/_usage.erb +0 -0
- data/app/views/examples/components/alert-dialog.html.erb +8 -11
- data/app/views/examples/components/alert.html.erb +90 -8
- data/app/views/examples/components/badge/_usage.html.erb +10 -0
- data/app/views/examples/components/badge/code/_preview.erb +5 -0
- data/app/views/examples/components/badge/code/_usage.erb +1 -0
- data/app/views/examples/components/badge.html.erb +12 -17
- data/app/views/examples/components/button/_usage.html.erb +19 -0
- data/app/views/examples/components/button/code/_preview.erb +13 -0
- data/app/views/examples/components/button/code/_usage.erb +6 -0
- data/app/views/examples/components/button.html.erb +12 -20
- data/app/views/examples/components/card/_usage.html.erb +21 -0
- data/app/views/examples/components/card/code/_form.erb +72 -0
- data/app/views/examples/components/card/code/_notifications.erb +61 -0
- data/app/views/examples/components/card/code/_preview.erb +6 -0
- data/app/views/examples/components/card/code/_usage.erb +3 -0
- data/app/views/examples/components/card.html.erb +31 -143
- data/app/views/examples/components/checkbox/_usage.html.erb +9 -0
- data/app/views/examples/components/checkbox/code/_preview.erb +2 -0
- data/app/views/examples/components/checkbox/code/_usage.erb +1 -0
- data/app/views/examples/components/checkbox.html.erb +15 -1
- data/app/views/examples/components/collapsible/_usage.html.erb +16 -0
- data/app/views/examples/components/collapsible/code/_preview.erb +9 -0
- data/app/views/examples/components/collapsible/code/_usage.erb +7 -0
- data/app/views/examples/components/collapsible.html.erb +12 -10
- data/app/views/examples/components/dialog.html.erb +6 -15
- data/app/views/examples/components/dropdown-menu/_usage.html.erb +19 -0
- data/app/views/examples/components/dropdown-menu/code/_preview.erb +19 -0
- data/app/views/examples/components/dropdown-menu/code/_usage.erb +13 -0
- data/app/views/examples/components/dropdown-menu.html.erb +29 -15
- data/app/views/examples/components/filter/_usage.html.erb +14 -0
- data/app/views/examples/components/filter/code/_icon.html.erb +7 -0
- data/app/views/examples/components/filter/code/_preview.erb +3 -0
- data/app/views/examples/components/filter/code/_usage.erb +5 -0
- data/app/views/examples/components/filter.html.erb +27 -7
- data/app/views/examples/components/hover-card/_usage.html.erb +15 -0
- data/app/views/examples/components/hover-card/code/_preview.erb +13 -0
- data/app/views/examples/components/hover-card/code/_usage.erb +6 -0
- data/app/views/examples/components/hover-card.html.erb +12 -14
- data/app/views/examples/components/input/_usage.html.erb +10 -0
- data/app/views/examples/components/input/code/_borderless.erb +3 -0
- data/app/views/examples/components/input/code/_preview.erb +1 -0
- data/app/views/examples/components/input/code/_usage.erb +1 -0
- data/app/views/examples/components/input.html.erb +17 -3
- data/app/views/examples/components/label/_usage.html.erb +9 -0
- data/app/views/examples/components/label/code/_preview.erb +5 -0
- data/app/views/examples/components/label/code/_usage.erb +1 -0
- data/app/views/examples/components/label.html.erb +14 -5
- data/app/views/examples/components/popover/_usage.html.erb +12 -0
- data/app/views/examples/components/popover/code/_form.erb +23 -0
- data/app/views/examples/components/popover/code/_preview.erb +13 -0
- data/app/views/examples/components/popover/code/_usage.erb +7 -0
- data/app/views/examples/components/popover.html.erb +28 -24
- data/app/views/examples/components/progress/_usage.erb +9 -0
- data/app/views/examples/components/progress/code/_preview.erb +1 -0
- data/app/views/examples/components/progress/code/_usage.erb +1 -0
- data/app/views/examples/components/progress.html.erb +12 -2
- data/app/views/examples/components/separator/_usage.html.erb +10 -0
- data/app/views/examples/components/separator/code/_fancy.erb +21 -0
- data/app/views/examples/components/separator/code/_preview.erb +1 -0
- data/app/views/examples/components/separator/code/_usage.erb +1 -0
- data/app/views/examples/components/separator.html.erb +26 -19
- data/app/views/examples/components/sheet/_usage.html.erb +38 -0
- data/app/views/examples/components/sheet/code/_mobile_menu.erb +17 -0
- data/app/views/examples/components/sheet/code/_preview.erb +22 -0
- data/app/views/examples/components/sheet/code/_usage.erb +7 -0
- data/app/views/examples/components/sheet.html.erb +17 -10
- data/app/views/examples/components/skeleton/_usage.html.erb +9 -0
- data/app/views/examples/components/skeleton/code/_preview.erb +1 -0
- data/app/views/examples/components/skeleton/code/_usage.erb +1 -0
- data/app/views/examples/components/skeleton.html.erb +16 -2
- data/app/views/examples/components/slider/_usage.html.erb +11 -0
- data/app/views/examples/components/slider/code/_preview.erb +3 -0
- data/app/views/examples/components/slider/code/_usage.erb +1 -0
- data/app/views/examples/components/slider.html.erb +16 -2
- data/app/views/examples/components/textarea/_usage.html.erb +9 -0
- data/app/views/examples/components/textarea/code/_preview.erb +1 -0
- data/app/views/examples/components/textarea/code/_usage.erb +1 -0
- data/app/views/examples/components/textarea.html.erb +16 -2
- data/app/views/examples/components/toast/_usage.html.erb +11 -0
- data/app/views/examples/components/toast/code/_preview.erb +3 -0
- data/app/views/examples/components/toast/code/_usage.erb +2 -0
- data/app/views/examples/components/toast.html.erb +12 -4
- data/app/views/examples/components/toggle/_usage.html.erb +10 -0
- data/app/views/examples/components/toggle/code/_preview.erb +1 -0
- data/app/views/examples/components/toggle/code/_usage.erb +1 -0
- data/app/views/examples/components/toggle.html.erb +16 -2
- data/app/views/examples/components/tooltip/_usage.html.erb +11 -0
- data/app/views/examples/components/tooltip/code/_preview.erb +12 -0
- data/app/views/examples/components/tooltip/code/_usage.erb +7 -0
- data/app/views/examples/components/tooltip.html.erb +16 -13
- data/app/views/layouts/shared/_components.html.erb +44 -41
- data/config/environments/production.rb +4 -4
- data/config/shadcn.tailwind.js +98 -0
- data/config/tailwind.config.js +13 -74
- data/lib/components.json +7 -3
- data/lib/generators/shadcn-ui_generator.rb +201 -0
- data/lib/shadcn-ui/version.rb +1 -1
- data/package-lock.json +90 -3
- data/package.json +4 -0
- metadata +97 -9
- data/lib/generators/shadcn_ui_generator.rb +0 -81
- /data/app/assets/stylesheets/{lambda.light.scss → lambda.light.css} +0 -0
- /data/app/views/examples/components/dialog/code/{form.erb → _form.erb} +0 -0
- /data/app/views/examples/components/dialog/code/{notifications.erb → _notifications.erb} +0 -0
- /data/app/views/examples/components/dialog/code/{preview.erb → _preview.erb} +0 -0
- /data/app/views/examples/components/dialog/code/{usage.erb → _usage.erb} +0 -0
@@ -14,7 +14,7 @@
|
|
14
14
|
aria-expanded="true"
|
15
15
|
data-orientation="vertical"
|
16
16
|
class="flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180">
|
17
|
-
<%= title %><svg
|
17
|
+
<%= title || content_for(:title) %><svg
|
18
18
|
xmlns="http://www.w3.org/2000/svg"
|
19
19
|
width="24"
|
20
20
|
height="24"
|
@@ -34,7 +34,7 @@
|
|
34
34
|
role="region"
|
35
35
|
data-orientation="vertical"
|
36
36
|
class="st-accordion__content overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down">
|
37
|
-
<div class="pb-4 pt-0"><%= description %></div>
|
37
|
+
<div class="pb-4 pt-0"><%= description || content_for(:description) %></div>
|
38
38
|
</div>
|
39
39
|
</div>
|
40
40
|
</div>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
role="alert"
|
3
3
|
class="<%= alert_classes %> relative w-full rounded-lg border p-4 [&:has(svg)]:pl-11 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4">
|
4
4
|
<!--prettier-ignore-->
|
5
|
-
<% case variant %>
|
5
|
+
<% case variant.to_sym %>
|
6
6
|
<% when :default %>
|
7
7
|
<svg
|
8
8
|
xmlns="http://www.w3.org/2000/svg"
|
@@ -22,7 +22,19 @@
|
|
22
22
|
y1="19"
|
23
23
|
y2="19"></line>
|
24
24
|
</svg>
|
25
|
-
<% when :
|
25
|
+
<% when :info %>
|
26
|
+
<svg class="h-4 w-4 text-info" viewBox="0 0 20 20" fill="none" stroke="currentColor" aria-hidden="true">
|
27
|
+
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd"></path>
|
28
|
+
</svg>
|
29
|
+
<% when :success %>
|
30
|
+
<svg class="h-4 w-4 text-success" viewBox="0 0 20 20" fill="none" stroke="currentColor" aria-hidden="true">
|
31
|
+
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd"></path>
|
32
|
+
</svg>
|
33
|
+
<% when :attention %>
|
34
|
+
<svg class="h-4 w-4 text-yellow-400" viewBox="0 0 20 20" fill="none" stroke="currentColor" aria-hidden="true">
|
35
|
+
<path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"></path>
|
36
|
+
</svg>
|
37
|
+
<% when :error, :destructive, :danger, :alert %>
|
26
38
|
<svg
|
27
39
|
xmlns="http://www.w3.org/2000/svg"
|
28
40
|
width="24"
|
@@ -49,7 +61,7 @@
|
|
49
61
|
y1="16"
|
50
62
|
y2="16"></line>
|
51
63
|
</svg>
|
52
|
-
<% end %>
|
64
|
+
<% end if icon %>
|
53
65
|
<h5 class="mb-1 font-medium leading-none tracking-tight"><%= title %></h5>
|
54
66
|
<div class="text-sm [&_p]:leading-relaxed"><%= description %></div>
|
55
67
|
</div>
|
@@ -8,6 +8,12 @@
|
|
8
8
|
<% end %>
|
9
9
|
</div>
|
10
10
|
<% end %>
|
11
|
-
|
11
|
+
<% if !block && !title %>
|
12
|
+
<%= content_tag( :div, class: "p-6" ){ body } %>
|
13
|
+
<% elsif !block %>
|
14
|
+
<%= content_tag( :div, class: "px-6" ){ body } %>
|
15
|
+
<% else %>
|
16
|
+
<%= body %>
|
17
|
+
<% end %>
|
12
18
|
<% if footer %><footer class="mx-6 mb-6"><%= footer %></footer><% end %>
|
13
19
|
</div>
|
@@ -8,7 +8,8 @@
|
|
8
8
|
value="on"
|
9
9
|
class="peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground"
|
10
10
|
for="<%= name %>"
|
11
|
-
data-action="click->ui--checkbox#toggle"
|
11
|
+
data-action="click->ui--checkbox#toggle"
|
12
|
+
id="<%= options[:id] %>">
|
12
13
|
<span
|
13
14
|
class="flex items-center justify-center text-current hidden"
|
14
15
|
style="pointer-events: none">
|
@@ -6,11 +6,7 @@
|
|
6
6
|
class="flex items-center justify-between space-x-4 px-4"
|
7
7
|
data-action="click->ui--collapsible#toggle">
|
8
8
|
<h4 class="text-sm font-semibold"><%= trigger %></h4>
|
9
|
-
|
10
|
-
class="inline-flex items-center justify-center text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 hover:bg-accent hover:text-accent-foreground h-9 rounded-md w-9 p-0"
|
11
|
-
type="button"
|
12
|
-
aria-expanded="false"
|
13
|
-
data-state="closed">
|
9
|
+
<%= render_button variant: :ghost, data: {state: "closed"}, aria: {expanded: false}, class: "px-[0.75em] " do %>
|
14
10
|
<svg
|
15
11
|
xmlns="http://www.w3.org/2000/svg"
|
16
12
|
width="24"
|
@@ -26,7 +22,7 @@
|
|
26
22
|
<path d="m7 9 5-5 5 5"></path>
|
27
23
|
</svg>
|
28
24
|
<span class="sr-only">Toggle</span>
|
29
|
-
|
25
|
+
<% end %>
|
30
26
|
</div>
|
31
27
|
<%= yield :preview %>
|
32
28
|
<div
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<div data-controller="ui--filter">
|
2
2
|
<%= render_card do %>
|
3
3
|
<div class="flex items-center">
|
4
|
-
|
4
|
+
<%= content_for :filter_icon %>
|
5
5
|
<%= render_input name: "filter", placeholder: "Filter items...", style: :borderless, class: input_class, data: {"ui--filter-target": "source", action: "input->ui--filter#filter"} %></div>
|
6
6
|
<%= render_separator %>
|
7
7
|
<div class="<%= options[:class] %>">
|
@@ -12,3 +12,4 @@
|
|
12
12
|
end %>
|
13
13
|
</div>
|
14
14
|
<% end %>
|
15
|
+
</div>
|
@@ -9,7 +9,7 @@
|
|
9
9
|
data-ui--sheet-target="dialog"
|
10
10
|
class="data-[state=closed]:hidden data-[state=open]:block fixed z-50 gap-4 bg-background p-6 shadow-lg
|
11
11
|
transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500
|
12
|
-
inset-y-0 <%= options[:direction]
|
12
|
+
inset-y-0 <%= direction_class(options[:direction]) %> h-full <%= options[:width] %> border-l data-[state=closed]:slide-out-to-<%= options[:direction] %> data-[state=open]:slide-in-from-<%= options[:direction] %> sm:max-w-sm" tabindex="-1"
|
13
13
|
style="pointer-events: auto">
|
14
14
|
<div data-ui--sheet-target="content"><%= content_for(:sheet_content) %></div>
|
15
15
|
<button
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Component Generators
|
2
|
+
|
3
|
+
The gem adds generators to your application to help you copy the code from this application into
|
4
|
+
yours.
|
5
|
+
|
6
|
+
Each time you run the generator it will check to make sure you have the prerequisites, like Tailwind
|
7
|
+
and the shadcn stylesheet, and if not, do its best to reconcile that for you.
|
8
|
+
|
9
|
+
After that it will copy the component files into your application. If you edit the component,
|
10
|
+
re-running the generator for it will remove your edits. **Re-running a component generator is
|
11
|
+
basically reinstalling it and overwriting any changes you might have made.**
|
12
|
+
|
13
|
+
The generator will show up in `rails g` and it is called `shadcn-ui`
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
```
|
18
|
+
rails generate shadcn-ui <component_name>
|
19
|
+
```
|
20
|
+
|
21
|
+
You can list out the available components from `rails g shadcn-ui`.
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Component Helpers
|
2
|
+
|
3
|
+
The main entry point to using the component is always a `render_<component>` method defined in the
|
4
|
+
helper located in `app/helpers/components/<component>_helper.rb`.
|
5
|
+
|
6
|
+
The main responsibility of the component's render method is to ultimatelly render the component's
|
7
|
+
partial, located in `app/views/components/ui/_<component>.html.erb`.
|
8
|
+
|
9
|
+
The component partial generally will integrate all the content passed to the component helper,
|
10
|
+
whether through arguments or blocks.
|
11
|
+
|
12
|
+
The render helper generally takes a hash of arguments, and a block. The arguments are used for
|
13
|
+
required values for the HTML or for the content. Blocks generally correspond to inner content or
|
14
|
+
sections for the component.
|
15
|
+
|
16
|
+
<%= code_partial("dialog/usage", :erb) %>
|
17
|
+
|
18
|
+
Here the `render_dialog` helper takes a block, and the block is used to render the `dialog_trigger`
|
19
|
+
within the corresponding DOM along with the `dialog_content` as a sibling.
|
20
|
+
|
21
|
+
Inner content is generally rendered with a `content_for` call, and the component render method will
|
22
|
+
yield to the block, capture the content, and pass it along to the main partial.
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
module Components::DialogHelper
|
26
|
+
def render_dialog(**options, &block)
|
27
|
+
content = capture(&block) if block
|
28
|
+
render "components/ui/dialog", content: content, **options
|
29
|
+
end
|
30
|
+
|
31
|
+
def dialog_trigger(&block)
|
32
|
+
content_for :dialog_trigger, capture(&block), flush: true
|
33
|
+
end
|
34
|
+
|
35
|
+
def dialog_content(&block)
|
36
|
+
content_for :dialog_content, capture(&block), flush: true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
That is a pretty standard example of how the components work. The component partial is responsible
|
42
|
+
for the end result HTML.
|
43
|
+
|
44
|
+
## Options
|
45
|
+
|
46
|
+
Most of the components accept a variaty of DOM/HTML/Data related options. Sometimes these are
|
47
|
+
explcitly defined in the render method, and sometimes they are globed as an `**options` argument.
|
48
|
+
This should be standardized. As much as possible, I've tried to ensure that these are correctly
|
49
|
+
accounted for and passed along to the final html/dom elements, but I imagine that is not the case
|
50
|
+
everywhere. **Would love it if you raised an issue when you find this.**
|
51
|
+
|
52
|
+
## Standardiziation
|
53
|
+
|
54
|
+
As I add more components and see edge cases, I will move to standardizing the API.
|
@@ -13,3 +13,25 @@ Pick the components you need. Copy and paste the code into your project and cust
|
|
13
13
|
The code is yours.
|
14
14
|
|
15
15
|
_Use this as a reference to build your own component libraries._
|
16
|
+
|
17
|
+
## What?
|
18
|
+
|
19
|
+
### The Application
|
20
|
+
|
21
|
+
The [repository for this library](https://github.com/aviflombaum/shadcn-rails) is both a gem and an
|
22
|
+
example repository containing this documentation. AFAIK there is no consequence in terms of bloat to
|
23
|
+
packaging and entire functional rails app within a gem, especially given the app has very few
|
24
|
+
dependencies, no database, and is generally very small. The benefit is that you can run the app
|
25
|
+
locally and see the components in action by booting up the application with `./bin/dev/` and going
|
26
|
+
to localhost. In fact, this website is running the application within the gem right now.
|
27
|
+
|
28
|
+
The benefit of this is that it gives you a working application from which to modify and copy the raw
|
29
|
+
files for each component. The end goal of the gem is to simply copy working code from this
|
30
|
+
application into your app so that you take ownership over the component and can customize it to your
|
31
|
+
needs without any unnecessary abstraction.
|
32
|
+
|
33
|
+
### The Gem
|
34
|
+
|
35
|
+
The gem provides a generator for you to use in your application to facilitate copying the code from
|
36
|
+
this application to yours. It also enforces some setup for you as the component files alone in
|
37
|
+
isolation won't always work. [Learn more about the generator](/documentation/generators).
|
@@ -1,4 +1,126 @@
|
|
1
|
-
#
|
1
|
+
# Installation
|
2
|
+
|
3
|
+
The more automated way to install the components into your application is via the gem packaged
|
4
|
+
within this application. The gem provides generators that will setup your applications as best as
|
5
|
+
possible without potentially overwriting any existing code as well as copy components and their
|
6
|
+
dependencies to your application.
|
7
|
+
|
8
|
+
## Add the Gem
|
9
|
+
|
10
|
+
First step is adding the gem to your gemfile.
|
11
|
+
|
12
|
+
```sh
|
13
|
+
bundle add shadcn-ui
|
14
|
+
bundle install
|
15
|
+
```
|
16
|
+
|
17
|
+
## Install and Setup Dependencies
|
18
|
+
|
19
|
+
### TailwindCSS
|
20
|
+
|
21
|
+
The components need a few things in order to render and function properly
|
22
|
+
|
23
|
+
1. Tailwindcss must be installed in your application. If it's not already, I recommend just using
|
24
|
+
the `tailwindcss-rails` gem and running its installer to bootstrap your application with
|
25
|
+
TailwindCSS.
|
26
|
+
|
27
|
+
2. A few tailwindcss npm packages are required by the theme and the best way to get them is to add
|
28
|
+
them to your package.json or even if you're application doesn't use node packages because you use
|
29
|
+
importmaps or something else, having a package.json will still work only to allow the tailwind
|
30
|
+
cli to compile the themes. The easiest way I've found to include everything you need is by
|
31
|
+
including only one package that will include the rest of them, `tailwind-animate`. Create a
|
32
|
+
package.json if you need via `echo '{}' >> package.json`.
|
33
|
+
|
34
|
+
```
|
35
|
+
npm install -D tailwind-animate
|
36
|
+
```
|
37
|
+
|
38
|
+
These are the requirements if you want to add them individually:
|
39
|
+
|
40
|
+
```
|
41
|
+
@tailwindcss/forms
|
42
|
+
@tailwindcss/aspect-ratio
|
43
|
+
@tailwindcss/typography
|
44
|
+
@tailwindcss/container-queries
|
45
|
+
tailwindcss-animate
|
46
|
+
```
|
47
|
+
|
48
|
+
### shadcn CSS - Required
|
49
|
+
|
50
|
+
#### shadcn.css
|
51
|
+
|
52
|
+
These steps were not automated and are required to be done manually.
|
53
|
+
|
54
|
+
The components also require a few CSS variables to be set in order to render properly. It's a two
|
55
|
+
step process, first, the gem installation should have added `app/assets/stylesheets/shadcn.css` to
|
56
|
+
your application. You need to make sure this is included within `application.tailwind.css`, which
|
57
|
+
should have happened automatically, but double check.
|
58
|
+
|
59
|
+
```
|
60
|
+
@import "shadcn.css";
|
61
|
+
@tailwind base;
|
62
|
+
@tailwind components;
|
63
|
+
@tailwind utilities;
|
64
|
+
```
|
65
|
+
|
66
|
+
#### shadcn.tailwind.js
|
67
|
+
|
68
|
+
The installation also should have added a `config/shadcn.tailwind.js` file to your application. This
|
69
|
+
file is required to be included in your `tailwind.config.js` file. The best way to include it is to
|
70
|
+
`require` it in your `tailwind.config.js` file and expand the configuration settings. This is what a
|
71
|
+
newly setup `tailwind.config.js` file should look like after the inclusion of the
|
72
|
+
`shadcn.tailwind.js` settings.
|
73
|
+
|
74
|
+
```js
|
75
|
+
const defaultTheme = require("tailwindcss/defaultTheme");
|
76
|
+
const shadcnConfig = require("./shadcn.tailwind.js");
|
77
|
+
|
78
|
+
module.exports = {
|
79
|
+
content: [
|
80
|
+
"./public/*.html",
|
81
|
+
"./app/helpers/**/*.rb",
|
82
|
+
"./app/javascript/**/*.js",
|
83
|
+
"./app/views/**/*.{erb,haml,html,slim}",
|
84
|
+
],
|
85
|
+
theme: {
|
86
|
+
extend: {
|
87
|
+
fontFamily: {
|
88
|
+
sans: ["Inter var", ...defaultTheme.fontFamily.sans],
|
89
|
+
},
|
90
|
+
},
|
91
|
+
},
|
92
|
+
plugins: [
|
93
|
+
require("@tailwindcss/forms"),
|
94
|
+
require("@tailwindcss/aspect-ratio"),
|
95
|
+
require("@tailwindcss/typography"),
|
96
|
+
require("@tailwindcss/container-queries"),
|
97
|
+
],
|
98
|
+
...shadcnConfig,
|
99
|
+
};
|
100
|
+
```
|
101
|
+
|
102
|
+
You could also just use the shadcnConfig as the default Tailwind settings needed are also defined
|
103
|
+
there..
|
104
|
+
|
105
|
+
```js
|
106
|
+
const shadcnConfig = require("./shadcn.tailwind.js");
|
107
|
+
|
108
|
+
module.exports = {
|
109
|
+
...shadcnConfig,
|
110
|
+
};
|
111
|
+
```
|
112
|
+
|
113
|
+
After that feel free to add further customizatios to your tailwind config. For an existing tailwind
|
114
|
+
config, just add shadcnConfig to the end of the config object. It will override any settings needed
|
115
|
+
by being at the end. And obviously feel free to inspect shadcnConfig and keep only what's reui
|
116
|
+
|
117
|
+
## End
|
118
|
+
|
119
|
+
That's it! You are now set to start
|
120
|
+
[installing components via the generator]("/documentation/generators") and rendering them into your
|
121
|
+
views.
|
122
|
+
|
123
|
+
# Manual Installation
|
2
124
|
|
3
125
|
Prior to the initial gem release, you can use this as an alpha by cloning this repository and
|
4
126
|
starting up the app as you would a standard rails app.
|
@@ -220,7 +342,7 @@ Add the following to your app/assets/stylesheets/application.tailwind.css file.
|
|
220
342
|
}
|
221
343
|
```
|
222
344
|
|
223
|
-
### Copy
|
345
|
+
### Copy Component Files
|
224
346
|
|
225
347
|
For example, if you want to use the Accordion component, you would copy the following files to your
|
226
348
|
application:
|
@@ -247,3 +369,9 @@ See the component's demo page in `app/views/examples/components/accordion.html.e
|
|
247
369
|
examples.
|
248
370
|
|
249
371
|
This will be similar for each component.
|
372
|
+
|
373
|
+
# Conclusion
|
374
|
+
|
375
|
+
You can freely mix and match both styles as your application evolves. The end goal of each of them
|
376
|
+
is to get the component code into your application so you can further customize and take ownership
|
377
|
+
of your design system.
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Stimulus Controllers
|
2
|
+
|
3
|
+
Many components are paired with a stimulus controller that lives in
|
4
|
+
`app/javascript/controllers/ui/<component>_controller.js`. As much as possible I try to avoid adding
|
5
|
+
depedencies and currently this application is managing them with importmaps and I'm pretty sure if
|
6
|
+
you're not using importmaps, this breaks.
|
7
|
+
|
8
|
+
The Stimulus controllers frankly need a lot of work.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">The Accordion component introduces:</p>
|
2
|
+
|
3
|
+
<ul class="my-6 ml-6 list-disc [&>li]:mt-2 text-sm">
|
4
|
+
<li><%= code("app/helpers/components/accordion_helper.rb") %></li>
|
5
|
+
<li><%= code("app/views/components/ui/_accordion.html.erb") %></li>
|
6
|
+
<li><%= code("app/javascript/controllers/ui/accordion_controller.js") %></li>
|
7
|
+
</ul>
|
8
|
+
|
9
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
10
|
+
The method <%= code("render_accordion") %> defined in <%= code("app/helpers/components/accordion_helper.rb") %>
|
11
|
+
accepts a <%= code("title:") %> and <%= code("description:") %> keyword arguments in the inline usage.</p>
|
12
|
+
|
13
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">When passed only a <%= code("title") %> argument, the helper will accept a block to be rendered as the content for the description.</p>
|
14
|
+
|
15
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">When passed no arguments, the block passed to the accordion helper must call <%= code("accordion_title") %> and <%= code("accordion_description") %> both of which accept blocks for the content for those portals within the component.</p>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<%= render_accordion title: "Embed components in the description of an accordion" do %>
|
2
|
+
<%= accordion_description do %>
|
3
|
+
<%= render_card title: "A Simple Card", class: "w-full" do %>
|
4
|
+
<p class="p-6">But it could be anything really, give it a try.</p>
|
5
|
+
<% end %>
|
6
|
+
<% end %>
|
7
|
+
<% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Inline
|
2
|
+
<%= render_accordion(title:, :description) %>
|
3
|
+
|
4
|
+
# Description Block
|
5
|
+
<%= render_accordion(title:) do %>
|
6
|
+
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
# Title and Description Block
|
10
|
+
<% render_accordion do %>
|
11
|
+
<%= content_for :title do e%>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<%= content_for :description do e%>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
@@ -4,14 +4,48 @@
|
|
4
4
|
|
5
5
|
<% content_for :preview, flush: true do %>
|
6
6
|
<div class="w-full">
|
7
|
-
<%=
|
8
|
-
component library you want!" %>
|
9
|
-
<%= render_accordion title: "Use the generators.", description: "Add components with #{code("rails g shadcn_ui add accordion")}".html_safe %>
|
7
|
+
<%= render_code_preview('accordion') %>
|
10
8
|
</div>
|
11
9
|
<% end %>
|
12
10
|
|
11
|
+
<% content_for :code, flush: true do %>
|
12
|
+
<%= code_partial("accordion/preview", :erb) %>
|
13
|
+
<% end %>
|
14
|
+
|
13
15
|
<%= render_preview %>
|
14
16
|
|
15
17
|
<h2 class="font-heading scroll-m-20 border-b pb-2 text-2xl font-semibold tracking-tight first:mt-0" id="installation">Installation</h2>
|
16
18
|
|
19
|
+
<%= code_sample(language: "sh") do %>
|
20
|
+
rails generate shadcn-ui accodordion
|
21
|
+
<% end %>
|
22
|
+
|
17
23
|
<h2 class="font-heading mt-12 scroll-m-20 border-b pb-2 mb-2 text-2xl font-semibold tracking-tight first:mt-0" id="usage"><a href="/docs/components/dialog#usage">Usage</a></h2>
|
24
|
+
|
25
|
+
<%= code_partial("accordion/usage", :erb) %>
|
26
|
+
|
27
|
+
<%= render_usage("accordion") %>
|
28
|
+
|
29
|
+
<% content_for :examples, flush: true do %>
|
30
|
+
<div class="w-full flex justify-center">
|
31
|
+
<%= render "examples/components/accordion/code/description" %>
|
32
|
+
</div>
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
<% content_for :code, flush: true do %>
|
36
|
+
<%= code_partial("accordion/description.html", :erb) %>
|
37
|
+
<% end %>
|
38
|
+
|
39
|
+
<%= render_example %>
|
40
|
+
|
41
|
+
<% content_for :examples, flush: true do %>
|
42
|
+
<div class="w-full flex justify-center">
|
43
|
+
<%= render "examples/components/accordion/code/block" %>
|
44
|
+
</div>
|
45
|
+
<% end %>
|
46
|
+
|
47
|
+
<% content_for :code, flush: true do %>
|
48
|
+
<%= code_partial("accordion/block.html", :erb) %>
|
49
|
+
<% end %>
|
50
|
+
|
51
|
+
<%= render_example %>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">The Alert component introduces:</p>
|
2
|
+
|
3
|
+
<ul class="my-6 ml-6 list-disc [&>li]:mt-2 text-sm">
|
4
|
+
<li><%= code("app/helpers/components/alert_helper.rb") %></li>
|
5
|
+
<li><%= code("app/views/components/ui/_alert.html.erb") %></li>
|
6
|
+
</ul>
|
7
|
+
|
8
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
9
|
+
The method <%= code("render_alert") %> defined in <%= code("app/helpers/components/alert_helper.rb") %>
|
10
|
+
accepts a <%= code("title:") %> and <%= code("description:") %> required keyword arguments along with an optional <%= code("variant:") %> argument for the kind of alert to render. Skip the icon by setting the optional argument <%= code("icon:") %> to <%= code("false") %>.</p>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render_alert title:, description:, variant: %>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<%= render_alert_dialog(
|
2
|
+
trigger: render_button("Open Dialog", variant: :outline, data: {action: "ui--dialog#open" }),
|
3
|
+
continue: render_button("Continue"),
|
4
|
+
label: "Are you absolutely sure?",
|
5
|
+
description: "This action cannot be undone. This will permanently delete your account and remove your data from our servers.",
|
6
|
+
) %>
|
File without changes
|
@@ -3,22 +3,19 @@
|
|
3
3
|
title: "Alert Dialog",
|
4
4
|
description: "A modal dialog that interrupts the user with important content and expects a response." %>
|
5
5
|
|
6
|
-
|
7
|
-
<div class="w-full flex justify-center">
|
8
|
-
|
6
|
+
<% content_for :preview, flush: true do %>
|
7
|
+
<div class="w-full flex justify-center">
|
8
|
+
<%= render_code_preview('alert-dialog') %>
|
9
|
+
</div>
|
10
|
+
<% end %>
|
9
11
|
|
10
|
-
|
11
|
-
<%=
|
12
|
-
trigger: render_button("Open Dialog", variant: :outline, data: {action: "ui--dialog#open" }),
|
13
|
-
continue: render_button("Continue"),
|
14
|
-
label: "Are you absolutely sure?",
|
15
|
-
description: "This action cannot be undone. This will permanently delete your account and remove your data from our servers.",
|
16
|
-
) %>
|
17
|
-
</div>
|
12
|
+
<% content_for :code, flush: true do %>
|
13
|
+
<%= code_partial("alert-dialog/preview", :erb) %>
|
18
14
|
<% end %>
|
19
15
|
|
20
16
|
<%= render_preview %>
|
21
17
|
|
18
|
+
|
22
19
|
<h2 class="font-heading scroll-m-20 border-b pb-2 text-2xl font-semibold tracking-tight first:mt-0" id="installation">Installation</h2>
|
23
20
|
|
24
21
|
<h2 class="font-heading mt-12 scroll-m-20 border-b pb-2 mb-2 text-2xl font-semibold tracking-tight first:mt-0" id="usage"><a href="/docs/components/dialog#usage">Usage</a></h2>
|