|
| 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 |
0 commit comments