Skip to content

Commit 5f9f886

Browse files
committed
add sidebar component to the docs
1 parent b2d1f91 commit 5f9f886

40 files changed

+1877
-3
lines changed

app/components/docs/visual_code_example.rb

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ def self.reset_collected_code
1313
@@collected_code = []
1414
end
1515

16-
def initialize(title: nil, description: nil, context: nil)
16+
def initialize(title: nil, description: nil, src: nil, context: nil)
1717
@title = title
1818
@description = description
19+
@src = src
1920
@context = context
2021
end
2122

@@ -43,7 +44,7 @@ def view_template(&)
4344
def render_header
4445
div do
4546
if @title
46-
div(class: "flex items-center gap-x-2 mb-1") do
47+
div(class: "") do
4748
Components.Heading(level: 4) { @title.capitalize }
4849
end
4950
end
@@ -71,6 +72,20 @@ def render_tab_contents(&)
7172
end
7273

7374
def render_preview_tab(&block)
75+
return iframe_preview if @src
76+
77+
raw_preview
78+
end
79+
80+
def iframe_preview
81+
div(class: "relative aspect-[4/2.5] w-full overflow-hidden rounded-md border") do
82+
div(class: "absolute inset-0 hidden w-[1600px] bg-background md:block") do
83+
iframe(src: @src, class: "size-full")
84+
end
85+
end
86+
end
87+
88+
def raw_preview
7489
div(class: "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 relative rounded-md border") do
7590
div(class: "preview flex min-h-[350px] w-full justify-center p-10 items-center") do
7691
decoded_code = CGI.unescapeHTML(@display_code)

app/components/ruby_ui/dropdown_menu/dropdown_menu_content.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module RubyUI
44
class DropdownMenuContent < Base
55
def view_template(&block)
6-
div(data: {ruby_ui__dropdown_menu_target: "content"}, class: "hidden", style: "width: max-content; position: absolute; top: 0; left: 0;") do
6+
div(data: {ruby_ui__dropdown_menu_target: "content"}, class: "hidden", style: "width: max-content; position: absolute; top: 0; left: 0; z-index: 50;") do
77
div(**attrs, &block)
88
end
99
end
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# frozen_string_literal: true
2+
3+
module RubyUI
4+
class CollapsiableSidebar < Base
5+
def initialize(side: :left, variant: :sidebar, collapsible: :offcanvas, open: true, **attrs)
6+
@side = side
7+
@variant = variant
8+
@collapsible = collapsible
9+
@open = open
10+
super(**attrs)
11+
end
12+
13+
def view_template(&)
14+
MobileSidebar(side: @side, **attrs, &)
15+
div(**mix(sidebar_attrs, attrs)) do
16+
div(**gap_element_attrs)
17+
div(**content_wrapper_attrs) do
18+
div(**content_attrs, &)
19+
end
20+
end
21+
end
22+
23+
private
24+
25+
def sidebar_attrs
26+
{
27+
class: "group peer hidden text-sidebar-foreground md:block",
28+
data: {
29+
state: @open ? "expanded" : "collapsed",
30+
collapsible: @open ? "" : @collapsible,
31+
variant: @variant,
32+
side: @side,
33+
collapsible_kind: @collapsible,
34+
ruby_ui__sidebar_target: "sidebar"
35+
}
36+
}
37+
end
38+
39+
def gap_element_attrs
40+
{
41+
class: [
42+
"relative w-[var(--sidebar-width)] bg-transparent transition-[width]",
43+
"duration-200 ease-linear",
44+
"group-data-[collapsible=offcanvas]:w-0",
45+
"group-data-[side=right]:rotate-180",
46+
variant_classes
47+
]
48+
}
49+
end
50+
51+
def content_wrapper_attrs
52+
{
53+
class: [
54+
"fixed inset-y-0 z-10 hidden h-svh w-[var(--sidebar-width)]",
55+
"transition-[left,right,width] duration-200 ease-linear md:flex",
56+
content_wrapper_side_classes,
57+
content_wrapper_variant_classes
58+
]
59+
}
60+
end
61+
62+
def content_attrs
63+
{
64+
class: [
65+
"flex h-full w-full flex-col bg-sidebar",
66+
"group-data-[variant=floating]:rounded-lg",
67+
"group-data-[variant=floating]:border",
68+
"group-data-[variant=floating]:border-sidebar-border",
69+
"group-data-[variant=floating]:shadow"
70+
],
71+
data: {
72+
sidebar: "sidebar"
73+
}
74+
}
75+
end
76+
77+
def variant_classes
78+
if %i[floating inset].include?(@variant)
79+
"group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]"
80+
else
81+
"group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)]"
82+
end
83+
end
84+
85+
def content_wrapper_side_classes
86+
return "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" if @side == :left
87+
88+
"right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]"
89+
end
90+
91+
def content_wrapper_variant_classes
92+
if %i[floating inset].include?(@variant)
93+
"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]"
94+
else
95+
"group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)] group-data-[side=left]:border-r group-data-[side=right]:border-l"
96+
end
97+
end
98+
end
99+
end
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# frozen_string_literal: true
2+
3+
module RubyUI
4+
class CollapsibleSidebar < Base
5+
def initialize(side: :left, variant: :sidebar, collapsible: :offcanvas, open: true, **attrs)
6+
@side = side
7+
@variant = variant
8+
@collapsible = collapsible
9+
@open = open
10+
super(**attrs)
11+
end
12+
13+
def view_template(&)
14+
MobileSidebar(side: @side, **attrs, &)
15+
div(**mix(sidebar_attrs, attrs)) do
16+
div(**gap_element_attrs)
17+
div(**content_wrapper_attrs) do
18+
div(**content_attrs, &)
19+
end
20+
end
21+
end
22+
23+
private
24+
25+
def sidebar_attrs
26+
{
27+
class: "group peer hidden text-sidebar-foreground md:block",
28+
data: {
29+
state: @open ? "expanded" : "collapsed",
30+
collapsible: @open ? "" : @collapsible,
31+
variant: @variant,
32+
side: @side,
33+
collapsible_kind: @collapsible,
34+
ruby_ui__sidebar_target: "sidebar"
35+
}
36+
}
37+
end
38+
39+
def gap_element_attrs
40+
{
41+
class: [
42+
"relative w-[var(--sidebar-width)] bg-transparent transition-[width]",
43+
"duration-200 ease-linear",
44+
"group-data-[collapsible=offcanvas]:w-0",
45+
"group-data-[side=right]:rotate-180",
46+
variant_classes
47+
]
48+
}
49+
end
50+
51+
def content_wrapper_attrs
52+
{
53+
class: [
54+
"fixed inset-y-0 z-10 hidden h-svh w-[var(--sidebar-width)]",
55+
"transition-[left,right,width] duration-200 ease-linear md:flex",
56+
content_wrapper_side_classes,
57+
content_wrapper_variant_classes
58+
]
59+
}
60+
end
61+
62+
def content_attrs
63+
{
64+
class: [
65+
"flex h-full w-full flex-col bg-sidebar",
66+
"group-data-[variant=floating]:rounded-lg",
67+
"group-data-[variant=floating]:border",
68+
"group-data-[variant=floating]:border-sidebar-border",
69+
"group-data-[variant=floating]:shadow"
70+
],
71+
data: {
72+
sidebar: "sidebar"
73+
}
74+
}
75+
end
76+
77+
def variant_classes
78+
if %i[floating inset].include?(@variant)
79+
"group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]"
80+
else
81+
"group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)]"
82+
end
83+
end
84+
85+
def content_wrapper_side_classes
86+
return "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" if @side == :left
87+
88+
"right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]"
89+
end
90+
91+
def content_wrapper_variant_classes
92+
if %i[floating inset].include?(@variant)
93+
"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]"
94+
else
95+
"group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)] group-data-[side=left]:border-r group-data-[side=right]:border-l"
96+
end
97+
end
98+
end
99+
end
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# frozen_string_literal: true
2+
3+
module RubyUI
4+
class MobileSidebar < Base
5+
SIDEBAR_WIDTH_MOBILE = "18rem"
6+
7+
def initialize(side: :left, **attrs)
8+
@side = side
9+
super(**attrs)
10+
end
11+
12+
def view_template(&)
13+
Sheet(**attrs) do
14+
SheetContent(
15+
side: @side,
16+
class: "w-[var(--sidebar-width)] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden",
17+
style: {
18+
"--sidebar-width": SIDEBAR_WIDTH_MOBILE
19+
},
20+
data: {
21+
sidebar: "sidebar",
22+
mobile: "true"
23+
}
24+
) do
25+
SheetHeader(class: "sr-only") do
26+
SheetTitle { "Sidebar" }
27+
SheetDescription { "Displays the mobile sidebar." }
28+
end
29+
div(class: "flex h-full w-full flex-col", &)
30+
end
31+
end
32+
end
33+
34+
private
35+
36+
def default_attrs
37+
{
38+
data: {
39+
ruby_ui__sidebar_target: "mobileSidebar",
40+
action: "ruby--ui-sidebar:open->ruby-ui--sheet#open:self"
41+
}
42+
}
43+
end
44+
end
45+
end
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
module RubyUI
4+
class NonCollapsibleSidebar < Base
5+
def view_template(&)
6+
div(**attrs, &)
7+
end
8+
9+
private
10+
11+
def default_attrs
12+
{
13+
class: "flex h-full w-[var(--sidebar-width)] flex-col bg-sidebar text-sidebar-foreground"
14+
}
15+
end
16+
end
17+
end
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# frozen_string_literal: true
2+
3+
module RubyUI
4+
class Sidebar < Base
5+
SIDES = %i[left right].freeze
6+
VARIANTS = %i[sidebar floating inset].freeze
7+
COLLAPSIBLES = %i[offcanvas icon none].freeze
8+
9+
def initialize(side: :left, variant: :sidebar, collapsible: :offcanvas, open: true, **attrs)
10+
raise ArgumentError, "Invalid side: #{side}." unless SIDES.include?(side.to_sym)
11+
raise ArgumentError "Invalid variant: #{variant}." unless VARIANTS.include?(variant.to_sym)
12+
raise ArgumentError, "Invalid collapsible: #{collapsible}." unless COLLAPSIBLES.include?(collapsible.to_sym)
13+
14+
@side = side.to_sym
15+
@variant = variant.to_sym
16+
@collapsible = collapsible.to_sym
17+
@open = open
18+
super(**attrs)
19+
end
20+
21+
def view_template(&)
22+
if @collapsible == :none
23+
NonCollapsibleSidebar(**attrs, &)
24+
else
25+
CollapsibleSidebar(side: @side, variant: @variant, collapsible: @collapsible, open: @open, **attrs, &)
26+
end
27+
end
28+
end
29+
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
module RubyUI
4+
class SidebarContent < Base
5+
def view_template(&)
6+
div(**attrs, &)
7+
end
8+
9+
private
10+
11+
def default_attrs
12+
{
13+
class: "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
14+
data: {
15+
sidebar: "content"
16+
}
17+
}
18+
end
19+
end
20+
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
module RubyUI
4+
class SidebarFooter < Base
5+
def view_template(&)
6+
div(**attrs, &)
7+
end
8+
9+
private
10+
11+
def default_attrs
12+
{
13+
class: "flex flex-col gap-2 p-2",
14+
data: {
15+
sidebar: "footer"
16+
}
17+
}
18+
end
19+
end
20+
end

0 commit comments

Comments
 (0)