ariadne_view_components 0.0.95.5 → 0.0.96
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/CHANGELOG.md +14 -0
- data/app/assets/javascripts/ariadne_view_components.js +13 -13
- data/app/assets/javascripts/ariadne_view_components.js.br +0 -0
- data/app/assets/javascripts/ariadne_view_components.js.gz +0 -0
- data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
- data/app/assets/stylesheets/ariadne_view_components.css +1 -1
- data/app/assets/stylesheets/ariadne_view_components.css.br +0 -0
- data/app/assets/stylesheets/ariadne_view_components.css.gz +0 -0
- data/app/components/ariadne/form/base_component.rb +2 -0
- data/app/components/ariadne/form/base_input_component.rb +15 -0
- data/app/components/ariadne/form/label_helper.rb +35 -0
- data/app/components/ariadne/form/radio_button/component.rb +0 -7
- data/app/components/ariadne/form/select/component.html.erb +6 -10
- data/app/components/ariadne/form/select/component.rb +8 -14
- data/app/components/ariadne/form/text_field/component.html.erb +8 -8
- data/app/components/ariadne/form/text_field/component.rb +37 -51
- data/app/components/ariadne/layout/sidebar/component.html.erb +10 -0
- data/app/components/ariadne/layout/sidebar/component.rb +45 -0
- data/app/components/ariadne/ui/avatar/component.rb +1 -1
- data/app/components/ariadne/ui/badge/component.rb +0 -2
- data/app/components/ariadne/ui/clipboard_copy/component.ts +7 -0
- data/app/components/ariadne/ui/dialog/component.html.erb +4 -8
- data/app/components/ariadne/ui/dialog/component.rb +4 -6
- data/app/components/ariadne/ui/dialog/component.ts +4 -8
- data/app/components/ariadne/ui/popover/component.html.erb +1 -1
- data/app/components/ariadne/ui/popover/component.rb +6 -8
- data/app/components/ariadne/ui/popover/component.ts +5 -1
- data/app/components/ariadne/ui/sidebar/component.html.erb +24 -0
- data/app/components/ariadne/ui/sidebar/component.rb +82 -0
- data/app/components/ariadne/ui/sidebar/content/component.html.erb +14 -0
- data/app/components/ariadne/ui/sidebar/content/component.rb +47 -0
- data/app/components/ariadne/ui/sidebar/footer/component.html.erb +13 -0
- data/app/components/ariadne/ui/sidebar/footer/component.rb +54 -0
- data/app/components/ariadne/ui/sidebar/group/component.html.erb +36 -0
- data/app/components/ariadne/ui/sidebar/group/component.rb +84 -0
- data/app/components/ariadne/ui/sidebar/group/component.ts +72 -0
- data/app/components/ariadne/ui/sidebar/header/component.html.erb +13 -0
- data/app/components/ariadne/ui/sidebar/header/component.rb +54 -0
- data/app/components/ariadne/ui/sidebar/item/component.html.erb +24 -0
- data/app/components/ariadne/ui/sidebar/item/component.rb +78 -0
- data/app/frontend/stylesheets/ariadne_view_components.css +8 -1
- data/app/helpers/ariadne/form_helper.rb +4 -1
- data/lib/ariadne/view_components/version.rb +1 -1
- metadata +18 -4
- data/app/components/ariadne/ui/dialog/body/component.html.erb +0 -3
- data/app/components/ariadne/ui/dialog/body/component.rb +0 -28
@@ -1,15 +1,11 @@
|
|
1
|
-
<div>
|
2
|
-
|
3
|
-
class="<%= label_styles %>"
|
4
|
-
for="<%= @name %>"><%= @label %></label>
|
5
|
-
<% if required? %>
|
6
|
-
<span aria-hidden="true">*</span>
|
7
|
-
<% end %>
|
1
|
+
<div class="ariadne:space-y-2">
|
2
|
+
<%= render_label %>
|
8
3
|
<div class="ariadne:relative">
|
9
4
|
<div class="ariadne:pointer-events-none ariadne:absolute ariadne:inset-y-0 ariadne:left-0 ariadne:flex ariadne:items-center ariadne:px-3">
|
10
5
|
<%= leading_visual if leading_visual? %>
|
11
6
|
</div>
|
12
|
-
|
7
|
+
<div class="ariadne:flex">
|
8
|
+
<%= content_tag(
|
13
9
|
input? ? :input : :textarea,
|
14
10
|
input? ? nil : html_attrs[:value],
|
15
11
|
name: @name,
|
@@ -17,6 +13,10 @@
|
|
17
13
|
type: @type,
|
18
14
|
**html_attrs.except(:class)
|
19
15
|
) %>
|
16
|
+
<% if copyable? %>
|
17
|
+
<%= render Ariadne::UI::ClipboardCopy::Component.new(for: html_attrs[:id], html_attrs: { aria: { label: @label }} ) %>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
20
20
|
<% if @validation_message %>
|
21
21
|
<%= render(Primer::BaseComponent.new(tag: :div, **@validation_arguments)) do %>
|
22
22
|
<span class="FormControl-inlineValidation--visual"><%= render(Primer::Beta::Octicon.new(icon: :"alert-fill", size: :xsmall, aria: { hidden: true })) %></span>
|
@@ -40,11 +40,8 @@ module Ariadne
|
|
40
40
|
option :size, default: -> { :base }
|
41
41
|
option :width, default: -> { :narrow }
|
42
42
|
|
43
|
-
option :label_classes, default: -> { "" }
|
44
|
-
option :label_arguments, default: -> { {} }
|
45
|
-
|
46
43
|
accepts_html_attributes do |html_attrs|
|
47
|
-
html_attrs[:class] = merge_tailwind_classes([style(theme:, size:, width:, type:
|
44
|
+
html_attrs[:class] = merge_tailwind_classes([style(theme:, size:, width:, type:), html_attrs[:class]].join(" "))
|
48
45
|
|
49
46
|
html_attrs
|
50
47
|
end
|
@@ -57,10 +54,6 @@ module Ariadne
|
|
57
54
|
true
|
58
55
|
end
|
59
56
|
|
60
|
-
def label_styles
|
61
|
-
merge_tailwind_classes([style(:label), label_classes].join(" "))
|
62
|
-
end
|
63
|
-
|
64
57
|
style do
|
65
58
|
base do
|
66
59
|
[
|
@@ -140,41 +133,41 @@ module Ariadne
|
|
140
133
|
end
|
141
134
|
|
142
135
|
type do
|
143
|
-
text {
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
136
|
+
text {}
|
137
|
+
text_area do
|
138
|
+
[
|
139
|
+
"ariadne:relative",
|
140
|
+
"ariadne:px-[calc(--spacing(3.5)-1px)]",
|
141
|
+
"ariadne:py-[calc(--spacing(2.5)-1px)]",
|
142
|
+
"ariadne:sm:px-[calc(--spacing(3)-1px)]",
|
143
|
+
"ariadne:sm:py-[calc(--spacing(1.5)-1px)]",
|
144
|
+
"ariadne:block",
|
145
|
+
"ariadne:h-full",
|
146
|
+
"ariadne:w-full",
|
147
|
+
"ariadne:appearance-none",
|
148
|
+
"ariadne:rounded-lg",
|
149
|
+
"ariadne:text-base/6",
|
150
|
+
"ariadne:text-zinc-950",
|
151
|
+
"ariadne:placeholder:text-zinc-500",
|
152
|
+
"ariadne:sm:text-sm/6",
|
153
|
+
"ariadne:dark:text-white",
|
154
|
+
"ariadne:border",
|
155
|
+
"ariadne:border-zinc-950/10",
|
156
|
+
"ariadne:data-hover:border-zinc-950/20",
|
157
|
+
"ariadne:dark:border-white/10",
|
158
|
+
"ariadne:dark:data-hover:border-white/20",
|
159
|
+
"ariadne:bg-transparent",
|
160
|
+
"ariadne:dark:bg-white/5",
|
161
|
+
"ariadne:focus:outline-hidden",
|
162
|
+
"ariadne:data-invalid:border-red-500",
|
163
|
+
"ariadne:data-invalid:data-hover:border-red-500",
|
164
|
+
"ariadne:dark:data-invalid:border-red-600",
|
165
|
+
"ariadne:dark:data-invalid:data-hover:border-red-600",
|
166
|
+
"ariadne:disabled:border-zinc-950/20",
|
167
|
+
"ariadne:dark:disabled:border-white/15",
|
168
|
+
"ariadne:dark:data-hover:disabled:border-white/15",
|
169
|
+
"ariadne:resize-y",
|
170
|
+
]
|
178
171
|
end
|
179
172
|
end
|
180
173
|
end
|
@@ -182,14 +175,7 @@ module Ariadne
|
|
182
175
|
|
183
176
|
style(:label) do
|
184
177
|
base do
|
185
|
-
|
186
|
-
"ariadne:text-content",
|
187
|
-
"ariadne:dark:text-content-dark",
|
188
|
-
"ariadne:peer-disabled:cursor-not-allowed",
|
189
|
-
"ariadne:peer-disabled:opacity-70",
|
190
|
-
"ariadne:leading-none",
|
191
|
-
"ariadne:font-medium",
|
192
|
-
]
|
178
|
+
Ariadne::Form::BaseComponent::BASE_LABEL_STYLES
|
193
179
|
end
|
194
180
|
|
195
181
|
variants do
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Ariadne
|
5
|
+
module Layout
|
6
|
+
module Sidebar
|
7
|
+
# Renders a layout with a sidebar on the left and main content on the right.
|
8
|
+
# The sidebar is always positioned on the left side of the layout.
|
9
|
+
class Component < Ariadne::BaseComponent
|
10
|
+
# @param [Ariadne::UI::Sidebar::Component, nil] sidebar_component The sidebar component to render.
|
11
|
+
# If nil, you must provide sidebar content using with_sidebar_content.
|
12
|
+
option :sidebar_component, optional: true
|
13
|
+
|
14
|
+
# Sidebar content to be rendered if no sidebar_component is provided
|
15
|
+
# Only used when sidebar_component option is nil
|
16
|
+
renders_one :sidebar_content, Ariadne::BaseComponent::ACCEPT_ANYTHING
|
17
|
+
|
18
|
+
# Main content area to be rendered alongside the sidebar
|
19
|
+
renders_one :main_content, Ariadne::BaseComponent::ACCEPT_ANYTHING
|
20
|
+
|
21
|
+
# Style definitions for the layout container
|
22
|
+
style do
|
23
|
+
base do
|
24
|
+
[
|
25
|
+
"ariadne:flex",
|
26
|
+
"ariadne:h-full",
|
27
|
+
"ariadne:min-h-screen",
|
28
|
+
"ariadne:overflow-hidden"
|
29
|
+
]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Main content area styles
|
34
|
+
style(:main_content) do
|
35
|
+
base do
|
36
|
+
[
|
37
|
+
"ariadne:flex-1",
|
38
|
+
"ariadne:overflow-auto"
|
39
|
+
]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -17,7 +17,7 @@ module Ariadne
|
|
17
17
|
option :text, optional: true
|
18
18
|
# @param [String] src The avatar's URL.
|
19
19
|
option :src, optional: true
|
20
|
-
# @param [String]
|
20
|
+
# @param [String] alt The avatar's alt text.
|
21
21
|
option :alt, optional: true
|
22
22
|
# @param [String] size (Ariadne::UI::Badge::DEFAULT_SIZE) The avatar's size. <%= one_of(Ariadne::SizeHelper::VALID_SIZES) %>
|
23
23
|
option :size, default: proc { :md }
|
@@ -50,6 +50,7 @@ export default class ClipboardCopyController extends controllerFactory<HTMLDetai
|
|
50
50
|
target,
|
51
51
|
window.setTimeout(() => {
|
52
52
|
this.showInitial()
|
53
|
+
this.hideConfirm()
|
53
54
|
this.clipboardCopyElementTimers.delete(target)
|
54
55
|
}, CLIPBOARD_COPY_TIMER_DURATION),
|
55
56
|
)
|
@@ -70,4 +71,10 @@ export default class ClipboardCopyController extends controllerFactory<HTMLDetai
|
|
70
71
|
this.confirmedTarget.classList.add(this.hiddenClassValue)
|
71
72
|
}
|
72
73
|
}
|
74
|
+
|
75
|
+
hideConfirm() {
|
76
|
+
if (this.hasConfirmedTarget) {
|
77
|
+
this.confirmedTarget.classList.remove(this.showClassValue)
|
78
|
+
}
|
79
|
+
}
|
73
80
|
}
|
@@ -12,13 +12,9 @@
|
|
12
12
|
<%= html_attributes %>>
|
13
13
|
<div class="ariadne:flex ariadne:flex-col ariadne:space-y-2 ariadne:text-center ariadne:sm:text-left">
|
14
14
|
<span id="<%= dialog_id %>-title" class="ariadne:text-lg ariadne:font-semibold"><%= title %></span>
|
15
|
-
|
16
|
-
<%=
|
17
|
-
|
18
|
-
<div data-labelled-by="<%= labelledby %>">
|
19
|
-
<%= body %>
|
20
|
-
</div>
|
21
|
-
<% end %>
|
15
|
+
<div data-labelled-by="<%= labelledby %>">
|
16
|
+
<%= body %>
|
17
|
+
</div>
|
22
18
|
<% if footer? %>
|
23
19
|
<%= footer %>
|
24
20
|
<% end %>
|
@@ -27,7 +23,7 @@
|
|
27
23
|
<%= render Ariadne::UI::Button::Component.new(
|
28
24
|
scheme: :nude,
|
29
25
|
size: :xs,
|
30
|
-
html_attrs: { "data-action": "click->#{stimulus_name}#
|
26
|
+
html_attrs: { "data-action": "click->#{stimulus_name}#close", aria: { label: dialog_close_label } }).as_icon(icon: "x-mark", variant: :outline) %>
|
31
27
|
</div>
|
32
28
|
</div>
|
33
29
|
</dialog>
|
@@ -37,7 +37,7 @@ module Ariadne
|
|
37
37
|
# @param options [Hash] Same arguments as <%= link_to_component(Ariadne::UI::Button::Component) %>.
|
38
38
|
renders_one :reveal_button, lambda { |**options|
|
39
39
|
component_data_attrs = {
|
40
|
-
action: "#{Ariadne::UI::Dialog::Component.stimulus_name}#
|
40
|
+
action: "#{Ariadne::UI::Dialog::Component.stimulus_name}#open",
|
41
41
|
}
|
42
42
|
|
43
43
|
options[:html_attrs] ||= {}
|
@@ -50,7 +50,7 @@ module Ariadne
|
|
50
50
|
# @param options [Hash] Same arguments as <%= link_to_component(Ariadne::UI::Link::Component) %>.
|
51
51
|
renders_one :reveal_link, lambda { |**options|
|
52
52
|
component_data_attrs = {
|
53
|
-
action: "#{Ariadne::UI::Dialog::Component.stimulus_name}#
|
53
|
+
action: "#{Ariadne::UI::Dialog::Component.stimulus_name}#open",
|
54
54
|
}
|
55
55
|
|
56
56
|
options[:html_attrs] ||= {}
|
@@ -58,10 +58,8 @@ module Ariadne
|
|
58
58
|
Ariadne::UI::Link::Component.new(**options)
|
59
59
|
}
|
60
60
|
|
61
|
-
# The content.
|
62
|
-
|
63
|
-
# @param system_arguments [Hash] Same arguments as <%= link_to_component(Ariadne::UI::Dialog::Body::Component) %>.
|
64
|
-
renders_one :body, Ariadne::UI::Dialog::Body::Component
|
61
|
+
# The main content within the dialog.
|
62
|
+
renders_one :body, BaseComponent::ACCEPT_ANYTHING
|
65
63
|
|
66
64
|
# Optional footer content to the dialog; usually form buttons for submit or cancel.
|
67
65
|
#
|
@@ -4,7 +4,8 @@ import {disableBodyScroll, enableBodyScroll} from 'body-scroll-lock'
|
|
4
4
|
export default class DialogController extends controllerFactory()({
|
5
5
|
targets: {dialog: HTMLDialogElement},
|
6
6
|
}) {
|
7
|
-
close() {
|
7
|
+
close(e?:MouseEvent) {
|
8
|
+
if (e) e.preventDefault()
|
8
9
|
if (!this.dialogTarget.open) return
|
9
10
|
this.dialogTarget.close()
|
10
11
|
enableBodyScroll(this.dialogTarget)
|
@@ -14,17 +15,12 @@ export default class DialogController extends controllerFactory()({
|
|
14
15
|
this.close()
|
15
16
|
}
|
16
17
|
|
17
|
-
open() {
|
18
|
+
open(e: MouseEvent) {
|
19
|
+
e.preventDefault();
|
18
20
|
this.dialogTarget.showModal()
|
19
21
|
disableBodyScroll(this.dialogTarget, {reserveScrollBarGap: true})
|
20
22
|
}
|
21
23
|
|
22
|
-
swapVisibility(e: MouseEvent) {
|
23
|
-
e.preventDefault()
|
24
|
-
if (this.dialogTarget.open) this.close()
|
25
|
-
else this.open()
|
26
|
-
}
|
27
|
-
|
28
24
|
windowClick(e: MouseEvent) {
|
29
25
|
if (e.target === this.dialogTarget) {
|
30
26
|
this.close()
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div data-controller="<%= @stimulus_controllers %>">
|
1
|
+
<div data-controller="<%= @stimulus_controllers %>" data-<%= stimulus_name %>-placement-value="<%= popover_placement %>">
|
2
2
|
<%= reveal_button %>
|
3
3
|
<div class="<%= html_attrs[:class] %>" <%= html_attributes %>>
|
4
4
|
<%= content %>
|
@@ -59,18 +59,16 @@ module Ariadne
|
|
59
59
|
html_attrs[:data] ||= {}
|
60
60
|
html_attrs[:data] = {
|
61
61
|
"#{stimulus_name}-target" => ["popover", html_attrs.fetch(:data, {}).fetch(:target, nil)].compact.join(" "),
|
62
|
-
"#{stimulus_name}-placement-value" => popover_placement,
|
63
62
|
}.merge(html_attrs[:data])
|
64
63
|
end
|
65
64
|
|
66
65
|
def popover_placement
|
67
|
-
placement =
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
66
|
+
placement = case @position
|
67
|
+
when :above then "top"
|
68
|
+
when :below then "bottom"
|
69
|
+
else
|
70
|
+
"bottom"
|
71
|
+
end
|
74
72
|
placement += "-start" if @alignment == :left
|
75
73
|
placement += "-end" if @alignment == :right
|
76
74
|
placement
|
@@ -18,13 +18,17 @@ export default class PopoverController extends controllerFactory()({
|
|
18
18
|
})
|
19
19
|
}
|
20
20
|
|
21
|
+
toggle() {
|
22
|
+
dispatchEvent(new CustomEvent('toggle', {detail: {newState: this.popoverTarget.open ? 'closed' : 'open'}}))
|
23
|
+
}
|
24
|
+
|
21
25
|
updatePosition() {
|
22
26
|
autoUpdate(this.buttonTarget, this.popoverTarget, () => {
|
23
27
|
computePosition(this.buttonTarget, this.popoverTarget, {
|
24
28
|
placement: this.placementValue,
|
25
29
|
middleware: [offset(5), flip(), shift({padding: 5})],
|
26
30
|
}).then(({x, y}) => {
|
27
|
-
Object.assign(this.
|
31
|
+
Object.assign(this.popoverTarget.style, {
|
28
32
|
left: `${x}px`,
|
29
33
|
top: `${y}px`,
|
30
34
|
})
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<%# Sidebar container with data attributes for JavaScript interactions %>
|
2
|
+
<%= tag.aside(
|
3
|
+
id: "sidebar-#{object_id}",
|
4
|
+
class: style,
|
5
|
+
data: {
|
6
|
+
controller: "ariadne--ui--sidebar",
|
7
|
+
ariadne__ui__sidebar_target: "sidebar",
|
8
|
+
collapsed: !default_open,
|
9
|
+
collapsible: collapsible,
|
10
|
+
}
|
11
|
+
) do %>
|
12
|
+
<%# Render the header if provided %>
|
13
|
+
<% if header_component %>
|
14
|
+
<%= header_component %>
|
15
|
+
<% end %>
|
16
|
+
<%# Render the content if provided %>
|
17
|
+
<% if content_component %>
|
18
|
+
<%= content_component %>
|
19
|
+
<% end %>
|
20
|
+
<%# Render the footer if provided %>
|
21
|
+
<% if footer_component %>
|
22
|
+
<%= footer_component %>
|
23
|
+
<% end %>
|
24
|
+
<% end %>
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Ariadne
|
5
|
+
module UI
|
6
|
+
module Sidebar
|
7
|
+
# A sidebar component for navigation and application structure.
|
8
|
+
#
|
9
|
+
# The sidebar can be collapsible, with configurable breakpoints for responsive behavior.
|
10
|
+
# It supports header, footer, and content sections with nested groups and items.
|
11
|
+
class Component < Ariadne::BaseComponent
|
12
|
+
# @param [Symbol] collapsible (:icon) Indicates how the sidebar collapses. Can be `:icon` (collapses to icons), `:hidden` (hides completely), or `:none` (doesn't collapse).
|
13
|
+
option :collapsible, default: -> { :icon }
|
14
|
+
|
15
|
+
# @param [Boolean] default_open (true) Whether the sidebar is open by default.
|
16
|
+
option :default_open, default: -> { true }
|
17
|
+
|
18
|
+
# @param [Symbol] variant (:default) The visual variant of the sidebar.
|
19
|
+
option :variant, default: -> { :default }
|
20
|
+
|
21
|
+
# @param [Symbol] size (:md) Size of the sidebar. Can be :sm, :md, or :lg.
|
22
|
+
option :size, default: -> { :md }
|
23
|
+
|
24
|
+
# @param [String] width (null) The width of the sidebar. If provided, overrides the size option.
|
25
|
+
option :width, default: -> { nil }
|
26
|
+
|
27
|
+
# @param [String] collapsed_width (null) The width of the collapsed sidebar. If provided, overrides the default.
|
28
|
+
option :collapsed_width, default: -> { nil }
|
29
|
+
|
30
|
+
# Header component for the sidebar
|
31
|
+
renders_one :header_component, Ariadne::UI::Sidebar::Header::Component
|
32
|
+
|
33
|
+
# Footer component for the sidebar
|
34
|
+
renders_one :footer_component, Ariadne::UI::Sidebar::Footer::Component
|
35
|
+
|
36
|
+
# Content component for the sidebar
|
37
|
+
renders_one :content_component, Ariadne::UI::Sidebar::Content::Component
|
38
|
+
# Define style variants for the sidebar
|
39
|
+
style do
|
40
|
+
base do
|
41
|
+
[
|
42
|
+
"ariadne:flex",
|
43
|
+
"ariadne:flex-col",
|
44
|
+
"ariadne:h-screen",
|
45
|
+
"ariadne:overflow-hidden",
|
46
|
+
"ariadne:border-r",
|
47
|
+
"ariadne:bg-white", # Add background color matching Figma
|
48
|
+
"ariadne:border-zinc-100",
|
49
|
+
"ariadne:dark:border-zinc-800", # Updated dark border color
|
50
|
+
"ariadne:transition-all",
|
51
|
+
"ariadne:duration-300",
|
52
|
+
"ariadne:ease-in-out",
|
53
|
+
"ariadne:z-20"
|
54
|
+
]
|
55
|
+
end
|
56
|
+
|
57
|
+
variants do
|
58
|
+
variant do
|
59
|
+
default do
|
60
|
+
[]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
size do
|
65
|
+
sm do
|
66
|
+
["ariadne:w-64 ariadne:data-[collapsed=true]:w-16"]
|
67
|
+
end
|
68
|
+
|
69
|
+
md do
|
70
|
+
["ariadne:w-72 ariadne:data-[collapsed=true]:w-20"]
|
71
|
+
end
|
72
|
+
|
73
|
+
lg do
|
74
|
+
["ariadne:w-80 ariadne:data-[collapsed=true]:w-24"]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<div class="<%= style %>">
|
2
|
+
<% if search %>
|
3
|
+
<div class="ariadne:mb-4">
|
4
|
+
<%= search %>
|
5
|
+
</div>
|
6
|
+
<% end %>
|
7
|
+
<% if groups.any? %>
|
8
|
+
<% groups.each do |group| %>
|
9
|
+
<%= group %>
|
10
|
+
<% end %>
|
11
|
+
<% elsif custom_content %>
|
12
|
+
<%= custom_content %>
|
13
|
+
<% end %>
|
14
|
+
</div>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Ariadne
|
5
|
+
module UI
|
6
|
+
module Sidebar
|
7
|
+
module Content
|
8
|
+
# Content component for the sidebar.
|
9
|
+
# Container for sidebar groups and items.
|
10
|
+
class Component < Ariadne::BaseComponent
|
11
|
+
# Accepts any content for the sidebar
|
12
|
+
renders_many :groups, Ariadne::UI::Sidebar::Group::Component
|
13
|
+
|
14
|
+
# If no groups are used, any content can be passed directly
|
15
|
+
renders_one :custom_content, BaseComponent::ACCEPT_ANYTHING
|
16
|
+
|
17
|
+
# Search box for the sidebar
|
18
|
+
renders_one :search
|
19
|
+
|
20
|
+
# Whether to render direct content with padding
|
21
|
+
option :padded, default: -> { true }
|
22
|
+
|
23
|
+
style do
|
24
|
+
base do
|
25
|
+
[
|
26
|
+
"ariadne:flex",
|
27
|
+
"ariadne:flex-col",
|
28
|
+
"ariadne:gap-3",
|
29
|
+
"ariadne:flex-1",
|
30
|
+
"ariadne:overflow-y-auto",
|
31
|
+
"ariadne:py-2",
|
32
|
+
"ariadne:bg-white", # Match Figma background
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
variants do
|
37
|
+
padded do
|
38
|
+
yes { "ariadne:px-4" }
|
39
|
+
no { "" }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<div class="<%= style %>">
|
2
|
+
<% if primary %>
|
3
|
+
<div class="ariadne:flex ariadne:items-center ariadne:gap-2">
|
4
|
+
<%= primary %>
|
5
|
+
</div>
|
6
|
+
<% end %>
|
7
|
+
<% if secondary %>
|
8
|
+
<div class="ariadne:flex ariadne:items-center ariadne:gap-2">
|
9
|
+
<%= secondary %>
|
10
|
+
</div>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Ariadne
|
5
|
+
module UI
|
6
|
+
module Sidebar
|
7
|
+
module Footer
|
8
|
+
# Footer component for the sidebar.
|
9
|
+
# Often used for user profile, settings, or other actions at the bottom of the sidebar.
|
10
|
+
class Component < Ariadne::BaseComponent
|
11
|
+
# @param [Boolean] sticky (true) Whether the footer sticks to the bottom of the sidebar.
|
12
|
+
option :sticky, default: -> { true }
|
13
|
+
|
14
|
+
# Primary content slot for the footer
|
15
|
+
renders_one :primary
|
16
|
+
|
17
|
+
# Secondary content slot for the footer, often used for actions
|
18
|
+
renders_one :secondary
|
19
|
+
|
20
|
+
style do
|
21
|
+
base do
|
22
|
+
[
|
23
|
+
"ariadne:flex",
|
24
|
+
"ariadne:items-center",
|
25
|
+
"ariadne:justify-between",
|
26
|
+
"ariadne:p-4",
|
27
|
+
"ariadne:border-t",
|
28
|
+
"ariadne:border-zinc-100",
|
29
|
+
"ariadne:dark:border-zinc-800",
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
variants do
|
34
|
+
sticky do
|
35
|
+
no do
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
|
39
|
+
yes do
|
40
|
+
[
|
41
|
+
"ariadne:sticky",
|
42
|
+
"ariadne:bottom-0",
|
43
|
+
"ariadne:z-10",
|
44
|
+
"ariadne:mt-auto",
|
45
|
+
]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<div class="<%= style %>"
|
2
|
+
id="<%= component_id %>"
|
3
|
+
data-controller="<%= collapsible ? 'ariadne-ui-sidebar-group' : nil %>"
|
4
|
+
data-ariadne-ui-sidebar-group-open-value="<%= default_open %>">
|
5
|
+
<% if label.present? %>
|
6
|
+
<div class="<%= style(:label) %>" <%= "data-action='click->ariadne-ui-sidebar-group#toggle'" if collapsible %>>
|
7
|
+
<%= label %>
|
8
|
+
<% if collapsible %>
|
9
|
+
<button type="button"
|
10
|
+
data-action="ariadne-ui-sidebar-group#toggle"
|
11
|
+
class="ariadne:cursor-pointer ariadne:ml-auto ariadne:flex ariadne:items-center ariadne:text-current ariadne:bg-transparent ariadne:border-0 ariadne:p-0">
|
12
|
+
<%= render Ariadne::UI::Heroicon::Component.new(
|
13
|
+
icon: "chevron-right",
|
14
|
+
size: :xs,
|
15
|
+
variant: :solid,
|
16
|
+
class: "ariadne:ml-auto ariadne:duration-200 ariadne:ease-in-out ariadne:mr-0.5",
|
17
|
+
html_attrs: {
|
18
|
+
data: { "ariadne-ui-sidebar-group-target": "chevron" },
|
19
|
+
class: "ariadne:transition-transform #{default_open ? 'ariadne:rotate-90' : ''}"
|
20
|
+
}
|
21
|
+
) %>
|
22
|
+
</button>
|
23
|
+
<% end %>
|
24
|
+
</div>
|
25
|
+
<% end %>
|
26
|
+
<div class="<%= style(:items_container, collapsible: collapsible) %> ariadne:overflow-hidden"
|
27
|
+
data-ariadne-ui-sidebar-group-target="content">
|
28
|
+
<% if items.any? %>
|
29
|
+
<% items.each do |item| %>
|
30
|
+
<%= item %>
|
31
|
+
<% end %>
|
32
|
+
<% elsif custom_content %>
|
33
|
+
<%= custom_content %>
|
34
|
+
<% end %>
|
35
|
+
</div>
|
36
|
+
</div>
|