shadcn-ui 0.0.4 → 0.0.8
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/README.md +13 -314
- data/Rakefile +90 -0
- data/app/assets/stylesheets/shadcn.css +9 -1
- data/app/controllers/components_controller.rb +1 -0
- data/app/controllers/users_controller.rb +19 -0
- data/app/form_builders/shadcn_form_builder.rb +43 -0
- data/app/helpers/application_helper.rb +5 -0
- data/app/helpers/components/alert_dialog_helper.rb +19 -3
- data/app/helpers/components/alert_helper.rb +7 -3
- data/app/helpers/components/badge_helper.rb +4 -1
- data/app/helpers/components/combobox_helper.rb +10 -0
- data/app/helpers/components/forms_helper.rb +13 -0
- data/app/helpers/components/input_helper.rb +14 -4
- data/app/helpers/components/{seperator_helper.rb → separator_helper.rb} +1 -1
- data/app/helpers/components/slider_helper.rb +1 -1
- data/app/helpers/components/switch_helper.rb +5 -0
- data/app/helpers/components/tabs_helper.rb +29 -0
- data/app/helpers/components/toast_helper.rb +4 -1
- data/app/helpers/components_helper.rb +11 -5
- data/app/javascript/controllers/ui/dialog_controller.js +1 -1
- data/app/javascript/controllers/ui/dropdown_controller.js +1 -1
- data/app/javascript/controllers/ui/hover-card_controller.js +2 -3
- data/app/javascript/controllers/ui/popover_controller.js +2 -2
- data/app/javascript/controllers/ui/sheet_controller.js +1 -1
- data/app/javascript/controllers/ui/switch_controller.js +25 -0
- data/app/javascript/controllers/{tabs_controller.js → ui/tabs_controller.js} +2 -2
- data/app/javascript/controllers/ui/toast_controller.js +50 -23
- data/app/javascript/controllers/ui/transition_controller.js +1 -1
- data/app/models/user.rb +9 -0
- data/app/views/application/index.html.erb +1 -1
- data/app/views/components/ui/_alert_dialog.html.erb +10 -6
- data/app/views/components/ui/_combobox.html.erb +11 -0
- data/app/views/components/ui/_dialog.html.erb +0 -26
- data/app/views/components/ui/_filter.html.erb +1 -1
- data/app/views/components/ui/_input.html.erb +3 -0
- data/app/views/components/ui/_label.html.erb +1 -1
- data/app/views/components/ui/_popover.html.erb +1 -1
- data/app/views/components/ui/_slider.html.erb +5 -1
- data/app/views/components/ui/_switch.html.erb +25 -0
- data/app/views/components/ui/_tabs.html.erb +13 -0
- data/app/views/components/ui/_toast.html.erb +8 -4
- data/app/views/components/ui/tabs/_panel.html.erb +8 -0
- data/app/views/components/ui/tabs/_tab.html.erb +10 -0
- data/app/views/documentation/installation.html.md +1 -1
- data/app/views/examples/components/accordion/code/_preview.erb +11 -3
- data/app/views/examples/components/accordion/code/_usage.erb +2 -2
- data/app/views/examples/components/alert/code/_no_icon.erb +1 -1
- data/app/views/examples/components/alert-dialog/_usage.html.erb +24 -0
- data/app/views/examples/components/alert-dialog/code/_preview.erb +22 -6
- data/app/views/examples/components/alert-dialog/code/_usage.erb +13 -0
- data/app/views/examples/components/alert-dialog.html.erb +7 -1
- data/app/views/examples/components/card/code/_usage.erb +1 -1
- data/app/views/examples/components/combobox/_usage.html.erb +11 -0
- data/app/views/examples/components/combobox/code/_preview.erb +7 -0
- data/app/views/examples/components/combobox/code/_usage.erb +4 -0
- data/app/views/examples/components/combobox.html.erb +27 -0
- data/app/views/examples/components/forms/_usage.html.erb +28 -0
- data/app/views/examples/components/forms/code/_preview.erb +13 -0
- data/app/views/examples/components/forms/code/_usage.erb +6 -0
- data/app/views/examples/components/forms.html.erb +23 -0
- data/app/views/examples/components/slider/code/_preview.erb +2 -1
- data/app/views/examples/components/switch/_usage.html.erb +11 -0
- data/app/views/examples/components/switch/code/_preview.erb +4 -0
- data/app/views/examples/components/switch/code/_usage.erb +1 -0
- data/app/views/examples/components/switch.html.erb +27 -0
- data/app/views/examples/components/tabs/_usage.html.erb +15 -0
- data/app/views/examples/components/tabs/code/_account.html.erb +32 -0
- data/app/views/examples/components/tabs/code/_password.html.erb +19 -0
- data/app/views/examples/components/tabs/code/_preview.erb +14 -0
- data/app/views/examples/components/tabs/code/_usage.erb +12 -0
- data/app/views/examples/components/tabs.html.erb +27 -0
- data/app/views/examples/components/toast/code/_destructive.erb +6 -0
- data/app/views/examples/components/toast/code/_preview.erb +4 -3
- data/app/views/examples/components/toast.html.erb +17 -2
- data/app/views/layouts/application.html.erb +26 -4
- data/app/views/layouts/documentation/_component_header.html.erb +5 -4
- data/app/views/layouts/documentation/_examples.html.erb +7 -9
- data/app/views/layouts/documentation/_preview.html.erb +5 -5
- data/app/views/layouts/shared/_components.html.erb +6 -6
- data/config/routes.rb +3 -0
- data/lib/components.json +28 -13
- data/lib/generators/shadcn-ui_generator.rb +1 -1
- data/lib/shadcn-ui/version.rb +1 -1
- metadata +53 -9
- data/.env +0 -1
- data/app/views/components/ui/_badge.html.erb +0 -1
- data/app/views/components/ui/_separator.html.erb +0 -4
@@ -0,0 +1,29 @@
|
|
1
|
+
module Components::TabsHelper
|
2
|
+
def render_tabs(&block)
|
3
|
+
@_tabs = []
|
4
|
+
capture(&block)
|
5
|
+
render "components/ui/tabs"
|
6
|
+
end
|
7
|
+
|
8
|
+
def tab_list(&block)
|
9
|
+
content_for :tab_list, capture(&block), flush: true
|
10
|
+
end
|
11
|
+
|
12
|
+
def tab(title, **options)
|
13
|
+
options[:id] ||= "tab_#{title.parameterize}"
|
14
|
+
options[:state] = options[:active] ? "active" : "inactive"
|
15
|
+
|
16
|
+
@_tabs << {title: title, id: options[:id]}
|
17
|
+
render("components/ui/tabs/tab", title:, options:)
|
18
|
+
end
|
19
|
+
|
20
|
+
def tab_panels(&block)
|
21
|
+
content_for :tab_panels, capture(&block), flush: true
|
22
|
+
end
|
23
|
+
|
24
|
+
def tab_panel(**options, &block)
|
25
|
+
options[:state] = options[:active] ? "active" : "inactive"
|
26
|
+
content_for :panel, capture(&block), flush: true
|
27
|
+
render("components/ui/tabs/panel", options:)
|
28
|
+
end
|
29
|
+
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module Components::ToastHelper
|
2
|
-
def render_toast(header: nil, description: nil, action: nil, class: nil, data:
|
2
|
+
def render_toast(header: nil, description: nil, action: nil, class: nil, data: {}, variant: :default, **options, &block)
|
3
|
+
options[:class] ||= ""
|
4
|
+
options[:class] << " destructive group border-destructive bg-destructive text-destructive-foreground " if variant == :destructive
|
5
|
+
|
3
6
|
render "components/ui/toast", header:, description:, action:, class:, data:, options: options
|
4
7
|
end
|
5
8
|
end
|
@@ -1,4 +1,10 @@
|
|
1
|
+
require "tailwind_merge"
|
2
|
+
|
1
3
|
module ComponentsHelper
|
4
|
+
def tw(classes)
|
5
|
+
TailwindMerge::Merger.new.merge(classes)
|
6
|
+
end
|
7
|
+
|
2
8
|
PRIMARY_CLASSES = " bg-primary text-primary-foreground hover:bg-primary/80 "
|
3
9
|
SECONDARY_CLASSES = " bg-secondary text-secondary-foreground hover:bg-secondary/80 "
|
4
10
|
OUTLINE_CLASSES = " border border-input bg-background hover:bg-accent hover:text-accent-foreground "
|
@@ -6,11 +12,11 @@ module ComponentsHelper
|
|
6
12
|
DESTRUCTIVE_CLASSES = " bg-destructive text-destructive-foreground hover:bg-destructive/90 "
|
7
13
|
|
8
14
|
module Button
|
9
|
-
PRIMARY =
|
10
|
-
SECONDARY =
|
11
|
-
OUTLINE =
|
12
|
-
GHOST =
|
13
|
-
DESTRUCTIVE =
|
15
|
+
PRIMARY = ComponentsHelper::PRIMARY_CLASSES
|
16
|
+
SECONDARY = ComponentsHelper::SECONDARY_CLASSES
|
17
|
+
OUTLINE = ComponentsHelper::OUTLINE_CLASSES
|
18
|
+
GHOST = ComponentsHelper::GHOST_CLASSES
|
19
|
+
DESTRUCTIVE = ComponentsHelper::DESTRUCTIVE_CLASSES
|
14
20
|
end
|
15
21
|
|
16
22
|
module Alert
|
@@ -1,6 +1,6 @@
|
|
1
1
|
// Inspired by https://github.com/kanety/stimulus-dialog
|
2
2
|
import { Controller } from "@hotwired/stimulus";
|
3
|
-
import "
|
3
|
+
import "https://ga.jspm.io/npm:@kanety/stimulus-static-actions@1.0.1/dist/index.modern.js";
|
4
4
|
|
5
5
|
export default class UIDialog extends Controller {
|
6
6
|
static targets = ["dialog", "modal", "focus", "drag", "backdrop", "closeButton"];
|
@@ -1,5 +1,5 @@
|
|
1
1
|
// Inspired By: https://github.com/stimulus-components/stimulus-dropdown/blob/master/src/index.ts
|
2
2
|
import UIPopover from "controllers/ui/popover_controller";
|
3
|
-
import { useTransition } from "stimulus-use";
|
3
|
+
import { useTransition } from "https://ga.jspm.io/npm:stimulus-use@0.51.3/dist/index.js";
|
4
4
|
|
5
5
|
export default class extends UIPopover {}
|
@@ -1,9 +1,8 @@
|
|
1
1
|
// Inspired by: https://github.com/excid3/tailwindcss-stimulus-components/blob/master/src/popover.js
|
2
2
|
|
3
3
|
import { Controller } from "@hotwired/stimulus";
|
4
|
-
import { createPopper } from "
|
5
|
-
import { useDebounce } from "stimulus-use";
|
6
|
-
import { useHover } from "stimulus-use";
|
4
|
+
import { createPopper } from "https://ga.jspm.io/npm:@popperjs/core@2.11.8/lib/index.js";
|
5
|
+
import { useDebounce, useHover } from "https://ga.jspm.io/npm:stimulus-use@0.51.3/dist/index.js";
|
7
6
|
|
8
7
|
export default class UIHoverCardController extends Controller {
|
9
8
|
static debounces = ["mouseEnter", "mouseLeave"];
|
@@ -1,8 +1,8 @@
|
|
1
1
|
// Inspired by: https://github.com/excid3/tailwindcss-stimulus-components/blob/master/src/popover.js
|
2
2
|
|
3
3
|
import { Controller } from "@hotwired/stimulus";
|
4
|
-
import { createPopper } from "
|
5
|
-
import { useClickOutside } from "stimulus-use";
|
4
|
+
import { createPopper } from "https://ga.jspm.io/npm:@popperjs/core@2.11.8/lib/index.js";
|
5
|
+
import { useClickOutside } from "https://ga.jspm.io/npm:stimulus-use@0.51.3/dist/index.js";
|
6
6
|
|
7
7
|
export default class UIPopover extends Controller {
|
8
8
|
static values = {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import UIDialog from "controllers/ui/dialog_controller";
|
2
|
-
import "
|
2
|
+
import "https://ga.jspm.io/npm:@kanety/stimulus-static-actions@1.0.1/dist/index.modern.js";
|
3
3
|
|
4
4
|
export default class extends UIDialog {
|
5
5
|
// Handles a button triggering the sheet in a different
|
@@ -0,0 +1,25 @@
|
|
1
|
+
// Inspired by: https://github.com/excid3/tailwindcss-stimulus-components/blob/master/src/popover.js
|
2
|
+
|
3
|
+
import { Controller } from "@hotwired/stimulus";
|
4
|
+
|
5
|
+
export default class UIToggleController extends Controller {
|
6
|
+
connect() {}
|
7
|
+
|
8
|
+
toggle() {
|
9
|
+
const button = this.element.querySelector("button");
|
10
|
+
const span = this.element.querySelector("span");
|
11
|
+
const input = this.element.querySelector("input[type='hidden']");
|
12
|
+
|
13
|
+
if (this.element.dataset.state == "checked") {
|
14
|
+
input.value = "unchecked";
|
15
|
+
button.dataset.state = "unchecked";
|
16
|
+
span.dataset.state = "unchecked";
|
17
|
+
this.element.dataset.state = "unchecked";
|
18
|
+
} else {
|
19
|
+
input.value = "checked";
|
20
|
+
button.dataset.state = "checked";
|
21
|
+
span.dataset.state = "checked";
|
22
|
+
this.element.dataset.state = "checked";
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
// https://github.com/excid3/tailwindcss-stimulus-components/blob/master/src/tabs.js
|
2
2
|
import { Controller } from "@hotwired/stimulus";
|
3
|
-
import "
|
3
|
+
import "https://ga.jspm.io/npm:@kanety/stimulus-static-actions@1.0.1/dist/index.modern.js";
|
4
4
|
|
5
5
|
export default class extends Controller {
|
6
6
|
static targets = ["tab", "panel"];
|
@@ -10,7 +10,7 @@ export default class extends Controller {
|
|
10
10
|
this.activeTabClasses = (this.data.get("activeTab") || "active").split(" ");
|
11
11
|
this.inactiveTabClasses = (this.data.get("inactiveTab") || "inactive").split(" ");
|
12
12
|
if (this.anchor) this.index = this.tabTargets.findIndex((tab) => tab.id === this.anchor);
|
13
|
-
this.showTab();
|
13
|
+
// this.showTab();
|
14
14
|
}
|
15
15
|
|
16
16
|
change(event) {
|
@@ -4,40 +4,67 @@ export default class UIToastController extends Controller {
|
|
4
4
|
static targets = ["item"];
|
5
5
|
|
6
6
|
connect() {
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
if (this.element.role == "region" && this.element.dataset.auto != "false") {
|
8
|
+
setTimeout(() => {
|
9
|
+
this.open();
|
10
|
+
}, 1000);
|
11
|
+
this.close();
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
open() {
|
16
|
+
const toastElement = this.element.querySelector("[data-ui--toast-target='item']");
|
17
|
+
this.element.dataset.state = "open";
|
18
|
+
this.element.classList.remove("hidden");
|
19
|
+
this.showToast(toastElement);
|
20
|
+
}
|
21
|
+
|
22
|
+
close() {
|
23
|
+
const toastElement = this.element.querySelector("[data-ui--toast-target='item']");
|
24
|
+
this.element.dataset.state = "closed";
|
25
|
+
this.element.classList.add("hidden");
|
26
|
+
this.closeToast(toastElement);
|
27
|
+
}
|
28
|
+
|
29
|
+
showToast(el) {
|
30
|
+
if (el) {
|
31
|
+
el.dataset.state = "open";
|
32
|
+
el.classList.remove("hidden");
|
33
|
+
}
|
34
|
+
}
|
10
35
|
|
11
|
-
|
36
|
+
closeToast(el) {
|
37
|
+
if (el) {
|
38
|
+
setTimeout(() => {
|
39
|
+
el.dataset.state = "closed";
|
40
|
+
el.classList.add("hidden");
|
41
|
+
}, el.dataset.duration || 3000);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
trigger() {
|
46
|
+
const idTarget = this.element.dataset.target;
|
47
|
+
const toastContainer = document.querySelector(`${idTarget}`);
|
48
|
+
toastContainer.dataset.state = "open";
|
49
|
+
toastContainer.classList.remove("hidden");
|
50
|
+
const toastElement = toastContainer.querySelector("[data-ui--toast-target='item']");
|
51
|
+
this.showToast(toastElement);
|
52
|
+
this.closeToast(toastElement);
|
12
53
|
}
|
13
54
|
|
14
55
|
openAll() {
|
15
|
-
const toastElements = document.querySelectorAll(
|
56
|
+
const toastElements = document.querySelectorAll(
|
57
|
+
"[data-ui--toast-target='item']:not([data-visible='false'])",
|
58
|
+
);
|
16
59
|
toastElements.forEach((toastElement) => {
|
17
|
-
toastElement
|
18
|
-
toastElement.classList.remove("hidden");
|
60
|
+
this.showToast(toastElement);
|
19
61
|
});
|
20
62
|
}
|
21
63
|
|
22
64
|
closeAll() {
|
23
65
|
const toastElements = document.querySelectorAll("[data-ui--toast-target='item']");
|
24
66
|
toastElements.forEach((toastElement) => {
|
25
|
-
|
26
|
-
toastElement.dataset.state = "closed";
|
27
|
-
toastElement.classList.add("hidden");
|
28
|
-
}, toastElement.dataset.duration);
|
67
|
+
this.closeToast(toastElement);
|
29
68
|
});
|
30
69
|
}
|
31
|
-
|
32
|
-
test() {
|
33
|
-
const $this = this;
|
34
|
-
this.closeAll();
|
35
|
-
setTimeout(() => {
|
36
|
-
$this.openAll();
|
37
|
-
setTimeout(() => {
|
38
|
-
$this.closeAll();
|
39
|
-
}, 3000);
|
40
|
-
}, 1000);
|
41
|
-
}
|
42
|
-
close() {}
|
43
70
|
}
|
data/app/models/user.rb
ADDED
@@ -8,7 +8,7 @@
|
|
8
8
|
data-orientation="vertical"
|
9
9
|
role="none"
|
10
10
|
class="shrink-0 bg-border w-[1px] mx-2 h-4"></div>
|
11
|
-
<span class="sm:hidden">
|
11
|
+
<span class="sm:hidden">Introducing shadcn/ui on Rails!</span>
|
12
12
|
<span class="hidden sm:inline">Introducing shadcn/ui on Rails!</span>
|
13
13
|
<svg
|
14
14
|
width="15"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<div data-controller="ui--dialog">
|
2
|
+
<div data-action="click->ui--dialog#open"><%= content_for(:alert_dialog_trigger) %></div>
|
2
3
|
<%= render "components/ui/shared/backdrop", as: "backdrop" %>
|
3
4
|
|
4
|
-
<%= trigger %>
|
5
5
|
<div
|
6
6
|
role="alertdialog"
|
7
7
|
data-state="closed"
|
@@ -9,12 +9,16 @@
|
|
9
9
|
tabindex="-1"
|
10
10
|
style="pointer-events: auto"
|
11
11
|
data-ui--dialog-target="dialog">
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
</div>
|
12
|
+
<div>
|
13
|
+
<%= content_for(:alert_dialog_content) %>
|
14
|
+
</div>
|
16
15
|
<div class="flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2">
|
17
|
-
|
16
|
+
<div data-action="click->ui--dialog#close">
|
17
|
+
<%= content_for(:alert_dialog_cancel) %>
|
18
|
+
</div>
|
19
|
+
<div data-action="click->ui--dialog#close">
|
20
|
+
<%= content_for(:alert_dialog_continue) %>
|
21
|
+
</div>
|
18
22
|
</div>
|
19
23
|
</div>
|
20
24
|
</div>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%= render_popover do %>
|
2
|
+
<%= popover_trigger do %>
|
3
|
+
<button class="inline-flex items-center rounded-md 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 border border-input bg-background hover:bg-accent hover:text-accent-foreground h-10 px-4 py-2 w-[200px] justify-between" role="combobox" aria-expanded="false" type="button" aria-haspopup="dialog" data-state="closed">
|
4
|
+
<%= content_for :trigger %>
|
5
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="ml-2 h-4 w-4 shrink-0 opacity-50"><path d="m7 15 5 5 5-5"></path><path d="m7 9 5-5 5 5"></path></svg>
|
6
|
+
</button>
|
7
|
+
<% end %>
|
8
|
+
<%= popover_content class: "border-none p-0" do %>
|
9
|
+
<%= render_filter items %>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
@@ -41,29 +41,3 @@
|
|
41
41
|
</button>
|
42
42
|
</div>
|
43
43
|
</div>
|
44
|
-
<!-- <div data-controller="ui--dialog">
|
45
|
-
<div
|
46
|
-
data-ui--dialog-target="modal"
|
47
|
-
data-state="closed"
|
48
|
-
class="hidden fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
49
|
-
style="pointer-events: auto"
|
50
|
-
data-aria-hidden="true"
|
51
|
-
aria-hidden="true"></div>
|
52
|
-
|
53
|
-
<%#= trigger %>
|
54
|
-
<div
|
55
|
-
role="alertdialog"
|
56
|
-
data-state="closed"
|
57
|
-
class="hidden fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full"
|
58
|
-
tabindex="-1"
|
59
|
-
style="pointer-events: auto"
|
60
|
-
data-ui--dialog-target="dialog">
|
61
|
-
<div class="flex flex-col space-y-2 text-center sm:text-left">
|
62
|
-
<h2 class="text-lg font-semibold"><%#= label %></h2>
|
63
|
-
<p class="text-sm text-muted-foreground"><%#= description %></p>
|
64
|
-
</div>
|
65
|
-
<div class="flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2">
|
66
|
-
<%#= cancel %> <%#= continue %>
|
67
|
-
</div>
|
68
|
-
</div>
|
69
|
-
</div> -->
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<%= render_card do %>
|
3
3
|
<div class="flex items-center">
|
4
4
|
<%= content_for :filter_icon %>
|
5
|
-
<%= render_input name: "filter", placeholder: "Filter items...",
|
5
|
+
<%= render_input name: "filter", placeholder: "Filter items...", variant: :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] %>">
|
8
8
|
<%= content_tag :div, role: "group" do
|
@@ -2,6 +2,9 @@
|
|
2
2
|
<%= text_field_tag name, value, type: type, id: id,
|
3
3
|
class: options[:class],
|
4
4
|
placeholder: options[:placeholder],
|
5
|
+
autocomplete: options[:autocomplete],
|
6
|
+
autocapitalize: options[:autocapitalize],
|
7
|
+
autocorrect: options[:autocorrect],
|
5
8
|
disabled: options[:disabled],
|
6
9
|
required: options[:required],
|
7
10
|
readonly: options[:readonly],
|
@@ -1,3 +1,3 @@
|
|
1
1
|
<%= label_tag name, label,
|
2
2
|
data: options[:data],
|
3
|
-
class: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 #{options[:class]}" %>
|
3
|
+
class: tw("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 #{options[:class]}") %>
|
@@ -11,7 +11,7 @@
|
|
11
11
|
data-align="center"
|
12
12
|
data-state="closed"
|
13
13
|
role="dialog"
|
14
|
-
class="hidden z-50
|
14
|
+
class="<%= tw("hidden z-50 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none #{content_for(:popover_content_class)}") %>"
|
15
15
|
tabindex=" -1 ">
|
16
16
|
<%= content_for(:popover_content) %>
|
17
17
|
</div>
|
@@ -1,2 +1,6 @@
|
|
1
1
|
|
2
|
-
<input type="range" min="1" max="100"
|
2
|
+
<input type="range" min="1" max="100"
|
3
|
+
value="<%= value %>" id="<%= id %>" name="<%= name %>"
|
4
|
+
style="background-size: <%= value %>% 100%"
|
5
|
+
data-controller="ui--slider" data-action="input->ui--slider#updateRange"
|
6
|
+
class="<%= options[:class] %>">
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<div
|
2
|
+
data-controller="ui--switch"
|
3
|
+
class="flex items-center space-x-2 cursor-pointer"
|
4
|
+
data-action="click->ui--switch#toggle"
|
5
|
+
data-state="<%= state %>">
|
6
|
+
<input type="hidden" value="<%= state %>" name="<%= name %>">
|
7
|
+
<button
|
8
|
+
type="button"
|
9
|
+
role="switch"
|
10
|
+
aria-checked="false"
|
11
|
+
data-state="<%= state %>"
|
12
|
+
class="peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input"
|
13
|
+
id="<%= id %>">
|
14
|
+
<span
|
15
|
+
data-state="<%= state %>"
|
16
|
+
class="pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0">
|
17
|
+
</span>
|
18
|
+
</button>
|
19
|
+
<label
|
20
|
+
data-action="click->ui--switch#toggle"
|
21
|
+
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer"
|
22
|
+
for="<%= id %>">
|
23
|
+
<%= text %>
|
24
|
+
</label>
|
25
|
+
</div>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<div class="group" data-controller="ui--tabs">
|
2
|
+
<div
|
3
|
+
role="tablist"
|
4
|
+
aria-orientation="horizontal"
|
5
|
+
class="h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground grid w-full grid-cols-2"
|
6
|
+
tabindex="0"
|
7
|
+
data-orientation="horizontal"
|
8
|
+
style="outline: none">
|
9
|
+
<%= content_for :tab_list %>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<%= content_for :tab_panels %>
|
13
|
+
</div>
|
@@ -1,4 +1,8 @@
|
|
1
|
-
<div role="region" aria-label="Notifications (F8)" tabindex="-1" style=""
|
1
|
+
<div role="region" aria-label="Notifications (F8)" tabindex="-1" style=""
|
2
|
+
id="<%= options[:id] %>"
|
3
|
+
data-controller="ui--toast <%= data[:controller] %>"
|
4
|
+
data-auto="<%= options[:auto] %>"
|
5
|
+
class="hidden">
|
2
6
|
<span aria-hidden="true" tabindex="0" style="position: fixed; border: 0px; width: 1px; height: 1px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; overflow-wrap: normal;"></span>
|
3
7
|
<ol tabindex="-1" class="fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]">
|
4
8
|
<li role="status"
|
@@ -9,7 +13,7 @@
|
|
9
13
|
data-ui--toast-target="item"
|
10
14
|
data-swipe-direction="right"
|
11
15
|
data-duration="5000"
|
12
|
-
class="toast-item hidden group pointer-events-auto relative flex w-full items-center
|
16
|
+
class="<%= tw("toast-item hidden group pointer-events-auto relative flex w-full items-center
|
13
17
|
justify-between space-x-4 overflow-hidden rounded-md p-6 pr-8 shadow-lg
|
14
18
|
transition-all
|
15
19
|
data-[swipe=cancel]:translate-x-0
|
@@ -20,14 +24,14 @@
|
|
20
24
|
data-[state=closed]:fade-out-80
|
21
25
|
data-[state=open]:slide-in-from-top-full
|
22
26
|
data-[state=open]:sm:slide-in-from-bottom-full
|
23
|
-
border bg-background"
|
27
|
+
border bg-background #{options[:class]}") %>"
|
24
28
|
style="user-select: none; touch-action: none;">
|
25
29
|
<div class="grid gap-1">
|
26
30
|
<div class="text-sm font-semibold"><%= header %></div>
|
27
31
|
<div class="text-sm opacity-90"><%= description %></div>
|
28
32
|
</div>
|
29
33
|
<%= action %>
|
30
|
-
<button data-action="ui--toast#
|
34
|
+
<button data-action="ui--toast#close" type="button" class="absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600" toast-close="" data-radix-toast-announce-exclude=""><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4"><line x1="18" x2="6" y1="6" y2="18"></line><line x1="6" x2="18" y1="6" y2="18"></line></svg></button>
|
31
35
|
</li>
|
32
36
|
</ol>
|
33
37
|
<span aria-hidden="true" tabindex="0" style="position: fixed; border: 0px; width: 1px; height: 1px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; overflow-wrap: normal;"></span>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<button
|
2
|
+
type="button"
|
3
|
+
role="tab"
|
4
|
+
data-ui--tabs-target="tab"
|
5
|
+
data-state="<%= options[:state] %>"
|
6
|
+
class="inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm"
|
7
|
+
tabindex="0"
|
8
|
+
data-orientation="horizontal">
|
9
|
+
<%= title %>
|
10
|
+
</button>
|
@@ -32,7 +32,7 @@ The components need a few things in order to render and function properly
|
|
32
32
|
package.json if you need via `echo '{}' >> package.json`.
|
33
33
|
|
34
34
|
```
|
35
|
-
npm install -D
|
35
|
+
npm install -D tailwindcss-animate
|
36
36
|
```
|
37
37
|
|
38
38
|
These are the requirements if you want to add them individually:
|
@@ -1,3 +1,11 @@
|
|
1
|
-
<%= render_accordion title: "Did you know?",
|
2
|
-
component library you want!" %>
|
3
|
-
|
1
|
+
<%= render_accordion title: "Did you know?",
|
2
|
+
description: "You can wrap shadcn helpers in any component library you want!" %>
|
3
|
+
|
4
|
+
<%= render_accordion do %>
|
5
|
+
<%= accordion_title do %>
|
6
|
+
Use the generators
|
7
|
+
<% end %>
|
8
|
+
<%= accordion_description do %>
|
9
|
+
Add components with <%= code("rails g shadcn_ui add accordion") %>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">The Alert Dialog 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_dialog_helper.rb") %></li>
|
5
|
+
<li><%= code("app/views/components/ui/_alert_dialog.html.erb") %></li>
|
6
|
+
</ul>
|
7
|
+
|
8
|
+
And relies on <%= code("app/javascript/controllers/ui/dialog_controller.js") %>.
|
9
|
+
|
10
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
11
|
+
The method <%= code("render_alert_dialog") %> defined in <%= code("app/helpers/components/alert_dialog_helper.rb") %>
|
12
|
+
accepts a block for the inner components of the dialog. It renders the partial
|
13
|
+
<%= code("app/views/components/ui/_alert_dialog.html.erb") %> which contains the model structure and
|
14
|
+
and the 2 actions buttons of continue and cancel.
|
15
|
+
</p>
|
16
|
+
|
17
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
18
|
+
The modal is composed of 4 components with corresponding helper methods, <%= code("alert_dialog_trigger") %>,
|
19
|
+
which accepts a block for the element that will trigger the modal, and <%= code("alert_dialog_content") %>,
|
20
|
+
which accepts a block for the body of the modal and the two actions for the modal, <%= code("alert_dialog_cancel") %> for the element that you would like to cancel the dialog interaction, for example a button, and <%= code("alert_dialog_continue") %> for the element you would like to use to continue to interaction. Note, you should feel free to bind your own data actions to these buttons as they are enclosed in an element that will handle closing the modal on click.
|
21
|
+
</p>
|
22
|
+
|
23
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
24
|
+
See <a href="/docs/components/dialog">Dialog</a> for more context as this component inherits functionality from that one.</p>
|
@@ -1,6 +1,22 @@
|
|
1
|
-
<%= render_alert_dialog
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
<%= render_alert_dialog do %>
|
2
|
+
<%= alert_dialog_trigger do %>
|
3
|
+
<%= render_button("Open Dialog", variant: :outline) %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<%= alert_dialog_content do %>
|
7
|
+
<div class="flex flex-col space-y-2 text-center sm:text-left">
|
8
|
+
<h2 class="text-lg font-semibold">Are you absolutely sure?</h2>
|
9
|
+
<p class="text-sm text-muted-foreground">
|
10
|
+
This action cannot be undone. This will permanently delete your account and remove your data from our servers.
|
11
|
+
</p>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<%= alert_dialog_cancel do %>
|
16
|
+
<%= render_button("Cancel", variant: :outline) %>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<%= alert_dialog_continue do %>
|
20
|
+
<%= render_button("Continue") %>
|
21
|
+
<% end %>
|
22
|
+
<% end %>
|