better_ui 0.3.0 → 0.4.0
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.
Potentially problematic release.
This version of better_ui might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +174 -216
- data/app/assets/javascripts/better_ui/controllers/navbar_controller.js +138 -0
- data/app/assets/javascripts/better_ui/controllers/sidebar_controller.js +211 -0
- data/app/assets/javascripts/better_ui/controllers/toast_controller.js +161 -0
- data/app/assets/javascripts/better_ui/index.js +159 -0
- data/app/assets/javascripts/better_ui/toast_manager.js +77 -0
- data/app/assets/stylesheets/better_ui/application.css +30 -0
- data/app/components/better_ui/application/alert_component.html.erb +27 -0
- data/app/components/better_ui/application/alert_component.rb +196 -0
- data/app/components/better_ui/application/header_component.html.erb +88 -0
- data/app/components/better_ui/application/header_component.rb +188 -0
- data/app/components/better_ui/application/navbar_component.html.erb +294 -0
- data/app/components/better_ui/application/navbar_component.rb +249 -0
- data/app/components/better_ui/application/sidebar_component.html.erb +207 -0
- data/app/components/better_ui/application/sidebar_component.rb +318 -0
- data/app/components/better_ui/application/toast_component.html.erb +35 -0
- data/app/components/better_ui/application/toast_component.rb +188 -0
- data/app/components/better_ui/general/breadcrumb_component.html.erb +39 -0
- data/app/components/better_ui/general/breadcrumb_component.rb +132 -0
- data/app/components/better_ui/general/{button/component.html.erb → button_component.html.erb} +7 -7
- data/app/components/better_ui/general/button_component.rb +193 -0
- data/app/components/better_ui/general/heading_component.html.erb +25 -0
- data/app/components/better_ui/general/heading_component.rb +142 -0
- data/app/components/better_ui/general/icon_component.html.erb +2 -0
- data/app/components/better_ui/general/icon_component.rb +101 -0
- data/app/components/better_ui/general/panel_component.html.erb +27 -0
- data/app/components/better_ui/general/panel_component.rb +97 -0
- data/app/components/better_ui/general/table_component.html.erb +37 -0
- data/app/components/better_ui/general/table_component.rb +141 -0
- data/app/components/better_ui/theme_helper.rb +169 -0
- data/app/controllers/better_ui/application_controller.rb +1 -0
- data/app/controllers/better_ui/docs_controller.rb +34 -0
- data/app/helpers/better_ui_application_helper.rb +99 -0
- data/app/views/layouts/component_preview.html.erb +32 -0
- data/config/initializers/lookbook.rb +12 -12
- data/config/routes.rb +13 -0
- data/lib/better_ui/engine.rb +42 -5
- data/lib/better_ui/version.rb +1 -1
- data/lib/better_ui.rb +20 -4
- metadata +117 -157
- data/app/components/better_ui/application/card/component.html.erb +0 -20
- data/app/components/better_ui/application/card/component.rb +0 -214
- data/app/components/better_ui/application/main/component.html.erb +0 -9
- data/app/components/better_ui/application/main/component.rb +0 -123
- data/app/components/better_ui/application/navbar/component.html.erb +0 -92
- data/app/components/better_ui/application/navbar/component.rb +0 -136
- data/app/components/better_ui/application/sidebar/component.html.erb +0 -227
- data/app/components/better_ui/application/sidebar/component.rb +0 -130
- data/app/components/better_ui/general/accordion/component.html.erb +0 -5
- data/app/components/better_ui/general/accordion/component.rb +0 -92
- data/app/components/better_ui/general/accordion/item_component.html.erb +0 -12
- data/app/components/better_ui/general/accordion/item_component.rb +0 -176
- data/app/components/better_ui/general/alert/component.html.erb +0 -32
- data/app/components/better_ui/general/alert/component.rb +0 -242
- data/app/components/better_ui/general/avatar/component.html.erb +0 -20
- data/app/components/better_ui/general/avatar/component.rb +0 -301
- data/app/components/better_ui/general/badge/component.html.erb +0 -23
- data/app/components/better_ui/general/badge/component.rb +0 -248
- data/app/components/better_ui/general/breadcrumb/component.html.erb +0 -15
- data/app/components/better_ui/general/breadcrumb/component.rb +0 -187
- data/app/components/better_ui/general/button/component.rb +0 -214
- data/app/components/better_ui/general/divider/component.html.erb +0 -10
- data/app/components/better_ui/general/divider/component.rb +0 -226
- data/app/components/better_ui/general/dropdown/component.html.erb +0 -25
- data/app/components/better_ui/general/dropdown/component.rb +0 -170
- data/app/components/better_ui/general/dropdown/divider_component.html.erb +0 -1
- data/app/components/better_ui/general/dropdown/divider_component.rb +0 -41
- data/app/components/better_ui/general/dropdown/item_component.html.erb +0 -6
- data/app/components/better_ui/general/dropdown/item_component.rb +0 -119
- data/app/components/better_ui/general/field/component.html.erb +0 -27
- data/app/components/better_ui/general/field/component.rb +0 -37
- data/app/components/better_ui/general/heading/component.html.erb +0 -22
- data/app/components/better_ui/general/heading/component.rb +0 -257
- data/app/components/better_ui/general/icon/component.html.erb +0 -7
- data/app/components/better_ui/general/icon/component.rb +0 -239
- data/app/components/better_ui/general/input/checkbox/component.html.erb +0 -5
- data/app/components/better_ui/general/input/checkbox/component.rb +0 -238
- data/app/components/better_ui/general/input/datetime/component.html.erb +0 -5
- data/app/components/better_ui/general/input/datetime/component.rb +0 -223
- data/app/components/better_ui/general/input/radio/component.html.erb +0 -5
- data/app/components/better_ui/general/input/radio/component.rb +0 -230
- data/app/components/better_ui/general/input/select/component.html.erb +0 -16
- data/app/components/better_ui/general/input/select/component.rb +0 -184
- data/app/components/better_ui/general/input/select/select_component.html.erb +0 -5
- data/app/components/better_ui/general/input/select/select_component.rb +0 -37
- data/app/components/better_ui/general/input/text/component.html.erb +0 -5
- data/app/components/better_ui/general/input/text/component.rb +0 -171
- data/app/components/better_ui/general/input/textarea/component.html.erb +0 -5
- data/app/components/better_ui/general/input/textarea/component.rb +0 -166
- data/app/components/better_ui/general/link/component.html.erb +0 -18
- data/app/components/better_ui/general/link/component.rb +0 -258
- data/app/components/better_ui/general/modal/component.html.erb +0 -5
- data/app/components/better_ui/general/modal/component.rb +0 -47
- data/app/components/better_ui/general/modal/modal_component.html.erb +0 -52
- data/app/components/better_ui/general/modal/modal_component.rb +0 -160
- data/app/components/better_ui/general/pagination/component.html.erb +0 -85
- data/app/components/better_ui/general/pagination/component.rb +0 -216
- data/app/components/better_ui/general/panel/component.html.erb +0 -28
- data/app/components/better_ui/general/panel/component.rb +0 -249
- data/app/components/better_ui/general/progress/component.html.erb +0 -11
- data/app/components/better_ui/general/progress/component.rb +0 -160
- data/app/components/better_ui/general/spinner/component.html.erb +0 -35
- data/app/components/better_ui/general/spinner/component.rb +0 -93
- data/app/components/better_ui/general/table/component.html.erb +0 -5
- data/app/components/better_ui/general/table/component.rb +0 -217
- data/app/components/better_ui/general/table/tbody_component.html.erb +0 -3
- data/app/components/better_ui/general/table/tbody_component.rb +0 -30
- data/app/components/better_ui/general/table/td_component.html.erb +0 -3
- data/app/components/better_ui/general/table/td_component.rb +0 -44
- data/app/components/better_ui/general/table/tfoot_component.html.erb +0 -3
- data/app/components/better_ui/general/table/tfoot_component.rb +0 -28
- data/app/components/better_ui/general/table/th_component.html.erb +0 -6
- data/app/components/better_ui/general/table/th_component.rb +0 -51
- data/app/components/better_ui/general/table/thead_component.html.erb +0 -3
- data/app/components/better_ui/general/table/thead_component.rb +0 -28
- data/app/components/better_ui/general/table/tr_component.html.erb +0 -3
- data/app/components/better_ui/general/table/tr_component.rb +0 -30
- data/app/components/better_ui/general/tabs/component.html.erb +0 -11
- data/app/components/better_ui/general/tabs/component.rb +0 -120
- data/app/components/better_ui/general/tabs/panel_component.html.erb +0 -3
- data/app/components/better_ui/general/tabs/panel_component.rb +0 -37
- data/app/components/better_ui/general/tabs/tab_component.html.erb +0 -13
- data/app/components/better_ui/general/tabs/tab_component.rb +0 -111
- data/app/components/better_ui/general/tag/component.html.erb +0 -3
- data/app/components/better_ui/general/tag/component.rb +0 -104
- data/app/components/better_ui/general/tooltip/component.html.erb +0 -7
- data/app/components/better_ui/general/tooltip/component.rb +0 -239
- data/app/helpers/better_ui/application/components/card/card_helper.rb +0 -96
- data/app/helpers/better_ui/application/components/card.rb +0 -11
- data/app/helpers/better_ui/application/components/main/main_helper.rb +0 -64
- data/app/helpers/better_ui/application/components/navbar/navbar_helper.rb +0 -77
- data/app/helpers/better_ui/application/components/sidebar/sidebar_helper.rb +0 -51
- data/app/helpers/better_ui/application_helper.rb +0 -55
- data/app/helpers/better_ui/general/components/accordion/accordion_helper.rb +0 -73
- data/app/helpers/better_ui/general/components/accordion.rb +0 -11
- data/app/helpers/better_ui/general/components/alert/alert_helper.rb +0 -57
- data/app/helpers/better_ui/general/components/avatar/avatar_helper.rb +0 -29
- data/app/helpers/better_ui/general/components/badge/badge_helper.rb +0 -53
- data/app/helpers/better_ui/general/components/breadcrumb/breadcrumb_helper.rb +0 -37
- data/app/helpers/better_ui/general/components/button/button_helper.rb +0 -65
- data/app/helpers/better_ui/general/components/container/container_helper.rb +0 -60
- data/app/helpers/better_ui/general/components/divider/divider_helper.rb +0 -63
- data/app/helpers/better_ui/general/components/dropdown/divider_helper.rb +0 -32
- data/app/helpers/better_ui/general/components/dropdown/dropdown_helper.rb +0 -79
- data/app/helpers/better_ui/general/components/dropdown/item_helper.rb +0 -62
- data/app/helpers/better_ui/general/components/field/field_helper.rb +0 -26
- data/app/helpers/better_ui/general/components/heading/heading_helper.rb +0 -72
- data/app/helpers/better_ui/general/components/icon/icon_helper.rb +0 -16
- data/app/helpers/better_ui/general/components/input/checkbox/checkbox_helper.rb +0 -81
- data/app/helpers/better_ui/general/components/input/datetime/datetime_helper.rb +0 -91
- data/app/helpers/better_ui/general/components/input/radio/radio_helper.rb +0 -79
- data/app/helpers/better_ui/general/components/input/radio_group/radio_group_helper.rb +0 -124
- data/app/helpers/better_ui/general/components/input/select/select_helper.rb +0 -70
- data/app/helpers/better_ui/general/components/input/text/text_helper.rb +0 -138
- data/app/helpers/better_ui/general/components/input/textarea/textarea_helper.rb +0 -73
- data/app/helpers/better_ui/general/components/link/link_helper.rb +0 -89
- data/app/helpers/better_ui/general/components/modal/modal_helper.rb +0 -85
- data/app/helpers/better_ui/general/components/modal.rb +0 -11
- data/app/helpers/better_ui/general/components/pagination/pagination_helper.rb +0 -82
- data/app/helpers/better_ui/general/components/panel/panel_helper.rb +0 -83
- data/app/helpers/better_ui/general/components/progress/progress_helper.rb +0 -53
- data/app/helpers/better_ui/general/components/spinner/spinner_helper.rb +0 -19
- data/app/helpers/better_ui/general/components/table/table_helper.rb +0 -53
- data/app/helpers/better_ui/general/components/table/tbody_helper.rb +0 -13
- data/app/helpers/better_ui/general/components/table/td_helper.rb +0 -19
- data/app/helpers/better_ui/general/components/table/tfoot_helper.rb +0 -13
- data/app/helpers/better_ui/general/components/table/th_helper.rb +0 -19
- data/app/helpers/better_ui/general/components/table/thead_helper.rb +0 -13
- data/app/helpers/better_ui/general/components/table/tr_helper.rb +0 -13
- data/app/helpers/better_ui/general/components/tabs/panel_helper.rb +0 -62
- data/app/helpers/better_ui/general/components/tabs/tab_helper.rb +0 -55
- data/app/helpers/better_ui/general/components/tabs/tabs_helper.rb +0 -95
- data/app/helpers/better_ui/general/components/tag/tag_helper.rb +0 -26
- data/app/helpers/better_ui/general/components/tooltip/tooltip_helper.rb +0 -60
- data/app/views/layouts/better_ui/application.html.erb +0 -17
- data/lib/better_ui/railtie.rb +0 -20
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module BetterUi
|
|
4
|
-
module Application
|
|
5
|
-
module Main
|
|
6
|
-
class Component < ViewComponent::Base
|
|
7
|
-
attr_reader :padding, :inner_padding, :rounded, :shadow, :with_sidebar, :sidebar_width, :classes
|
|
8
|
-
|
|
9
|
-
# Arrotondamento bordi con classi Tailwind dirette
|
|
10
|
-
MAIN_ROUNDED = {
|
|
11
|
-
none: "",
|
|
12
|
-
small: "rounded-lg",
|
|
13
|
-
medium: "rounded-xl",
|
|
14
|
-
large: "rounded-2xl",
|
|
15
|
-
full: "rounded-full"
|
|
16
|
-
}.freeze
|
|
17
|
-
|
|
18
|
-
# Ombre con classi Tailwind dirette
|
|
19
|
-
MAIN_SHADOW = {
|
|
20
|
-
none: "",
|
|
21
|
-
small: "shadow-sm",
|
|
22
|
-
medium: "shadow-md",
|
|
23
|
-
large: "shadow-lg"
|
|
24
|
-
}.freeze
|
|
25
|
-
|
|
26
|
-
# Padding con classi Tailwind dirette
|
|
27
|
-
MAIN_PADDING = {
|
|
28
|
-
true: "p-6",
|
|
29
|
-
false: "p-0"
|
|
30
|
-
}.freeze
|
|
31
|
-
|
|
32
|
-
# Classi layout per sidebar
|
|
33
|
-
MAIN_LAYOUT = {
|
|
34
|
-
sidebar: { sm: "pl-48", md: "pl-64", lg: "pl-72", xl: "pl-80" }, # Con Sidebar
|
|
35
|
-
none: "" # Senza sidebar
|
|
36
|
-
}.freeze
|
|
37
|
-
|
|
38
|
-
# Larghezza sidebar (deve corrispondere a SIDEBAR_WIDTHS del componente Sidebar)
|
|
39
|
-
MAIN_SIDEBAR_WIDTH = {
|
|
40
|
-
sm: 48,
|
|
41
|
-
md: 64,
|
|
42
|
-
lg: 72,
|
|
43
|
-
xl: 80
|
|
44
|
-
}.freeze
|
|
45
|
-
|
|
46
|
-
# @param padding [Boolean] Se applicare il padding al contenitore principale
|
|
47
|
-
# @param inner_padding [Boolean] Se applicare il padding al contenitore interno
|
|
48
|
-
# @param rounded [Symbol] Tipo di border-radius del contenitore interno (:none, :small, :medium, :large, :full), default :small
|
|
49
|
-
# @param shadow [Symbol] Tipo di ombra del contenitore interno (:none, :small, :medium, :large), default :medium
|
|
50
|
-
# @param with_sidebar [Boolean] Se lasciare lo spazio per la sidebar
|
|
51
|
-
# @param sidebar_width [Symbol] Larghezza della sidebar (:sm, :md, :lg, :xl), default :md
|
|
52
|
-
# @param classes [String] Classi CSS aggiuntive per il contenitore principale
|
|
53
|
-
def initialize(
|
|
54
|
-
padding: true,
|
|
55
|
-
inner_padding: true,
|
|
56
|
-
rounded: :small,
|
|
57
|
-
shadow: :medium,
|
|
58
|
-
with_sidebar: true,
|
|
59
|
-
sidebar_width: :md,
|
|
60
|
-
classes: nil
|
|
61
|
-
)
|
|
62
|
-
@padding = padding
|
|
63
|
-
@inner_padding = inner_padding
|
|
64
|
-
@rounded = rounded.to_sym
|
|
65
|
-
@shadow = shadow.to_sym
|
|
66
|
-
@with_sidebar = with_sidebar
|
|
67
|
-
@sidebar_width = sidebar_width.to_sym
|
|
68
|
-
@classes = classes
|
|
69
|
-
|
|
70
|
-
validate_params
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
private
|
|
76
|
-
|
|
77
|
-
def get_layout_class
|
|
78
|
-
if with_sidebar
|
|
79
|
-
MAIN_LAYOUT[:sidebar][@sidebar_width] || MAIN_LAYOUT[:sidebar][:md]
|
|
80
|
-
else
|
|
81
|
-
MAIN_LAYOUT[:none]
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def get_padding_class(enabled)
|
|
86
|
-
MAIN_PADDING[enabled] || MAIN_PADDING[false]
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def get_rounded_class
|
|
90
|
-
MAIN_ROUNDED[@rounded] || MAIN_ROUNDED[:small]
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def get_shadow_class
|
|
94
|
-
MAIN_SHADOW[@shadow] || MAIN_SHADOW[:medium]
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def validate_params
|
|
98
|
-
validate_rounded
|
|
99
|
-
validate_shadow
|
|
100
|
-
validate_sidebar_width if with_sidebar
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def validate_rounded
|
|
104
|
-
unless MAIN_ROUNDED.keys.include?(@rounded)
|
|
105
|
-
raise ArgumentError, "L'arrotondamento deve essere uno tra: #{MAIN_ROUNDED.keys.join(', ')}"
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def validate_shadow
|
|
110
|
-
unless MAIN_SHADOW.keys.include?(@shadow)
|
|
111
|
-
raise ArgumentError, "L'ombra deve essere una tra: #{MAIN_SHADOW.keys.join(', ')}"
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def validate_sidebar_width
|
|
116
|
-
unless MAIN_SIDEBAR_WIDTH.keys.include?(@sidebar_width)
|
|
117
|
-
raise ArgumentError, "La larghezza della sidebar deve essere una tra: #{MAIN_SIDEBAR_WIDTH.keys.join(', ')}"
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
end
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
<header class="<%= container_classes %>">
|
|
2
|
-
<div class="flex items-center justify-between">
|
|
3
|
-
<!-- Left side - custom content-->
|
|
4
|
-
<div class="flex items-center">
|
|
5
|
-
<%= content %>
|
|
6
|
-
</div>
|
|
7
|
-
|
|
8
|
-
<!-- User actions -->
|
|
9
|
-
<div class="flex items-center space-x-4">
|
|
10
|
-
<% if has_actions? %>
|
|
11
|
-
<% actions.each do |action| %>
|
|
12
|
-
<div class="flex-shrink-0">
|
|
13
|
-
<% if action[:type] == :button %>
|
|
14
|
-
<% if action[:href].present? %>
|
|
15
|
-
<a
|
|
16
|
-
href="<%= action[:href] %>"
|
|
17
|
-
class="inline-flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 <%= action[:theme] == :primary ? 'bg-gray-900 text-white hover:bg-gray-700' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' %>"
|
|
18
|
-
>
|
|
19
|
-
<% if action[:icon].present? %>
|
|
20
|
-
<%= bui_icon(action[:icon], size: :small) %>
|
|
21
|
-
<% if action[:label].present? %>
|
|
22
|
-
<span class="ml-2"><%= action[:label] %></span>
|
|
23
|
-
<% end %>
|
|
24
|
-
<% else %>
|
|
25
|
-
<%= action[:label] %>
|
|
26
|
-
<% end %>
|
|
27
|
-
</a>
|
|
28
|
-
<% else %>
|
|
29
|
-
<button
|
|
30
|
-
type="button"
|
|
31
|
-
class="inline-flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 <%= action[:theme] == :primary ? 'bg-gray-900 text-white hover:bg-gray-700' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' %>"
|
|
32
|
-
<% if action[:data].present? %>
|
|
33
|
-
<% action[:data].each do |key, value| %>
|
|
34
|
-
data-<%= key %>="<%= value %>"
|
|
35
|
-
<% end %>
|
|
36
|
-
<% end %>
|
|
37
|
-
>
|
|
38
|
-
<% if action[:icon].present? %>
|
|
39
|
-
<%= bui_icon(action[:icon], size: :small) %>
|
|
40
|
-
<% if action[:label].present? %>
|
|
41
|
-
<span class="ml-2"><%= action[:label] %></span>
|
|
42
|
-
<% end %>
|
|
43
|
-
<% else %>
|
|
44
|
-
<%= action[:label] %>
|
|
45
|
-
<% end %>
|
|
46
|
-
</button>
|
|
47
|
-
<% end %>
|
|
48
|
-
<% elsif action[:type] == :avatar %>
|
|
49
|
-
<% if action[:href].present? %>
|
|
50
|
-
<a href="<%= action[:href] %>" class="flex-shrink-0 hover:opacity-75 transition-opacity duration-150">
|
|
51
|
-
<% end %>
|
|
52
|
-
|
|
53
|
-
<% if action[:avatar].is_a?(Hash) %>
|
|
54
|
-
<%= bui_avatar(**action[:avatar]) %>
|
|
55
|
-
<% else %>
|
|
56
|
-
<%= action[:avatar].html_safe %>
|
|
57
|
-
<% end %>
|
|
58
|
-
|
|
59
|
-
<% if action[:href].present? %>
|
|
60
|
-
</a>
|
|
61
|
-
<% end %>
|
|
62
|
-
<% elsif action[:type] == :icon %>
|
|
63
|
-
<% if action[:href].present? %>
|
|
64
|
-
<a
|
|
65
|
-
href="<%= action[:href] %>"
|
|
66
|
-
class="p-2 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-md transition-colors duration-150"
|
|
67
|
-
>
|
|
68
|
-
<%= bui_icon(action[:icon], size: :medium) %>
|
|
69
|
-
</a>
|
|
70
|
-
<% else %>
|
|
71
|
-
<button
|
|
72
|
-
type="button"
|
|
73
|
-
class="p-2 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-md transition-colors duration-150"
|
|
74
|
-
<% if action[:data].present? %>
|
|
75
|
-
<% action[:data].each do |key, value| %>
|
|
76
|
-
data-<%= key %>="<%= value %>"
|
|
77
|
-
<% end %>
|
|
78
|
-
<% end %>
|
|
79
|
-
>
|
|
80
|
-
<%= bui_icon(action[:icon], size: :medium) %>
|
|
81
|
-
</button>
|
|
82
|
-
<% end %>
|
|
83
|
-
<% else %>
|
|
84
|
-
<!-- Custom content -->
|
|
85
|
-
<%= action[:content].html_safe if action[:content].present? %>
|
|
86
|
-
<% end %>
|
|
87
|
-
</div>
|
|
88
|
-
<% end %>
|
|
89
|
-
<% end %>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
</header>
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module BetterUi
|
|
4
|
-
module Application
|
|
5
|
-
module Navbar
|
|
6
|
-
class Component < ViewComponent::Base
|
|
7
|
-
# Include degli helper per utilizzare bui_icon e bui_avatar
|
|
8
|
-
include BetterUi::General::Components::Icon::IconHelper
|
|
9
|
-
include BetterUi::General::Components::Avatar::AvatarHelper
|
|
10
|
-
|
|
11
|
-
attr_reader :theme, :shadow, :border, :actions, :classes, :with_sidebar, :sidebar_width
|
|
12
|
-
|
|
13
|
-
# Temi navbar con classi Tailwind dirette
|
|
14
|
-
NAVBAR_THEME = {
|
|
15
|
-
default: "bg-white text-gray-900 border-gray-200",
|
|
16
|
-
white: "bg-white text-gray-900 border-gray-200",
|
|
17
|
-
red: "bg-red-50 text-red-900 border-red-200",
|
|
18
|
-
rose: "bg-rose-50 text-rose-900 border-rose-200",
|
|
19
|
-
orange: "bg-orange-50 text-orange-900 border-orange-200",
|
|
20
|
-
green: "bg-green-50 text-green-900 border-green-200",
|
|
21
|
-
blue: "bg-blue-50 text-blue-900 border-blue-200",
|
|
22
|
-
yellow: "bg-yellow-50 text-yellow-900 border-yellow-200",
|
|
23
|
-
violet: "bg-violet-50 text-violet-900 border-violet-200"
|
|
24
|
-
}.freeze
|
|
25
|
-
|
|
26
|
-
# Ombre navbar con classi Tailwind dirette
|
|
27
|
-
NAVBAR_SHADOW = {
|
|
28
|
-
none: "",
|
|
29
|
-
small: "shadow-sm",
|
|
30
|
-
medium: "shadow-md",
|
|
31
|
-
large: "shadow-lg"
|
|
32
|
-
}.freeze
|
|
33
|
-
|
|
34
|
-
# Larghezze sidebar con valori numerici per utilizzo in classi custom
|
|
35
|
-
NAVBAR_SIDEBAR_WIDTH = {
|
|
36
|
-
sm: 48,
|
|
37
|
-
md: 64,
|
|
38
|
-
lg: 72,
|
|
39
|
-
xl: 80
|
|
40
|
-
}.freeze
|
|
41
|
-
|
|
42
|
-
# @param theme [Symbol] Tema colori (default, white, red, rose, orange, green, blue, yellow, violet), default :default
|
|
43
|
-
# @param shadow [Symbol] Tipo di ombra (none, small, medium, large), default :small
|
|
44
|
-
# @param border [Boolean] Se mostrare il bordo inferiore, default true
|
|
45
|
-
# @param actions [Array] Array di azioni/pulsanti a destra
|
|
46
|
-
# @param classes [String] Classi CSS aggiuntive
|
|
47
|
-
# @param with_sidebar [Boolean] Se la navbar è affiancata a una sidebar, default false
|
|
48
|
-
# @param sidebar_width [Symbol] Larghezza della sidebar affiancata (:sm, :md, :lg, :xl), default :md
|
|
49
|
-
def initialize(
|
|
50
|
-
theme: :default,
|
|
51
|
-
shadow: :small,
|
|
52
|
-
border: false,
|
|
53
|
-
actions: [],
|
|
54
|
-
classes: nil,
|
|
55
|
-
with_sidebar: false,
|
|
56
|
-
sidebar_width: :md
|
|
57
|
-
)
|
|
58
|
-
@theme = theme.to_sym
|
|
59
|
-
@shadow = shadow.to_sym
|
|
60
|
-
@border = border
|
|
61
|
-
@actions = actions || []
|
|
62
|
-
@classes = classes
|
|
63
|
-
@with_sidebar = with_sidebar
|
|
64
|
-
@sidebar_width = sidebar_width.to_sym
|
|
65
|
-
|
|
66
|
-
validate_params
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def container_classes
|
|
70
|
-
base_classes = %w[h-[81px] px-6 py-4]
|
|
71
|
-
|
|
72
|
-
# Width
|
|
73
|
-
if with_sidebar
|
|
74
|
-
sidebar_width_value = NAVBAR_SIDEBAR_WIDTH[@sidebar_width] || NAVBAR_SIDEBAR_WIDTH[:md]
|
|
75
|
-
base_classes << "pl-#{sidebar_width_value}"
|
|
76
|
-
base_classes << "ml-auto"
|
|
77
|
-
else
|
|
78
|
-
base_classes << "w-full"
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# Tema
|
|
82
|
-
base_classes.concat(theme_classes.split)
|
|
83
|
-
|
|
84
|
-
# Shadow
|
|
85
|
-
base_classes << shadow_class if shadow != :none
|
|
86
|
-
|
|
87
|
-
# Border
|
|
88
|
-
base_classes << "border-b" if border
|
|
89
|
-
|
|
90
|
-
# Classi aggiuntive
|
|
91
|
-
base_classes << classes if classes.present?
|
|
92
|
-
|
|
93
|
-
base_classes.compact.join(" ")
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def has_actions?
|
|
97
|
-
actions.present? && actions.any?
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
private
|
|
101
|
-
|
|
102
|
-
def theme_classes
|
|
103
|
-
NAVBAR_THEME[@theme] || NAVBAR_THEME[:default]
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def shadow_class
|
|
107
|
-
NAVBAR_SHADOW[@shadow] || NAVBAR_SHADOW[:small]
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def validate_params
|
|
111
|
-
validate_theme
|
|
112
|
-
validate_shadow
|
|
113
|
-
validate_sidebar_width if with_sidebar
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def validate_theme
|
|
117
|
-
unless NAVBAR_THEME.keys.include?(@theme)
|
|
118
|
-
raise ArgumentError, "Il tema deve essere uno tra: #{NAVBAR_THEME.keys.join(', ')}"
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def validate_shadow
|
|
123
|
-
unless NAVBAR_SHADOW.keys.include?(@shadow)
|
|
124
|
-
raise ArgumentError, "L'ombra deve essere una tra: #{NAVBAR_SHADOW.keys.join(', ')}"
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def validate_sidebar_width
|
|
129
|
-
unless NAVBAR_SIDEBAR_WIDTH.keys.include?(@sidebar_width)
|
|
130
|
-
raise ArgumentError, "La larghezza della sidebar deve essere una tra: #{NAVBAR_SIDEBAR_WIDTH.keys.join(', ')}"
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
end
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
<div data-controller="bui-sidebar"
|
|
2
|
-
data-bui-sidebar-width-value="<%= @width == :md ? 256 : 320 %>"
|
|
3
|
-
data-bui-sidebar-min-width-value="200"
|
|
4
|
-
data-bui-sidebar-max-width-value="400"
|
|
5
|
-
data-bui-sidebar-pinned-value="true">
|
|
6
|
-
|
|
7
|
-
<!-- Mobile Overlay -->
|
|
8
|
-
<div data-bui-sidebar-target="overlay" class="fixed inset-0 bg-black bg-opacity-50 z-40 hidden md:hidden"></div>
|
|
9
|
-
|
|
10
|
-
<!-- Sidebar Container -->
|
|
11
|
-
<aside data-bui-sidebar-target="container" class="<%= container_classes %>">
|
|
12
|
-
<!-- Header Section -->
|
|
13
|
-
<% if has_header? %>
|
|
14
|
-
<div class="px-6 py-4 border-b border-gray-200">
|
|
15
|
-
<div class="flex items-center justify-between">
|
|
16
|
-
<% if header[:logo].present? %>
|
|
17
|
-
<div class="flex items-center">
|
|
18
|
-
<div class="flex-shrink-0">
|
|
19
|
-
<% if header[:logo].is_a?(Hash) %>
|
|
20
|
-
<%= bui_avatar(**header[:logo]) %>
|
|
21
|
-
<% else %>
|
|
22
|
-
<%= header[:logo].html_safe %>
|
|
23
|
-
<% end %>
|
|
24
|
-
</div>
|
|
25
|
-
<% if header[:title].present? %>
|
|
26
|
-
<div class="ml-3">
|
|
27
|
-
<h2 class="text-lg font-semibold text-gray-900"><%= header[:title] %></h2>
|
|
28
|
-
<% if header[:subtitle].present? %>
|
|
29
|
-
<p class="text-sm text-gray-500"><%= header[:subtitle] %></p>
|
|
30
|
-
<% end %>
|
|
31
|
-
</div>
|
|
32
|
-
<% end %>
|
|
33
|
-
</div>
|
|
34
|
-
<% elsif header[:title].present? %>
|
|
35
|
-
<div>
|
|
36
|
-
<h2 class="text-lg font-semibold text-gray-900"><%= header[:title] %></h2>
|
|
37
|
-
<% if header[:subtitle].present? %>
|
|
38
|
-
<p class="text-sm text-gray-500"><%= header[:subtitle] %></p>
|
|
39
|
-
<% end %>
|
|
40
|
-
</div>
|
|
41
|
-
<% end %>
|
|
42
|
-
|
|
43
|
-
<!-- Collapse Button (solo se collapsible) -->
|
|
44
|
-
<% if collapsible %>
|
|
45
|
-
<%= bui_button(
|
|
46
|
-
icon: "arrow-left",
|
|
47
|
-
type: :white,
|
|
48
|
-
size: :small,
|
|
49
|
-
title: "Comprimi sidebar"
|
|
50
|
-
) %>
|
|
51
|
-
<% end %>
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
<% end %>
|
|
55
|
-
|
|
56
|
-
<!-- Navigation Section -->
|
|
57
|
-
<nav class="flex-1 px-4 py-6 space-y-6 overflow-y-auto">
|
|
58
|
-
<% navigation_sections.each do |section| %>
|
|
59
|
-
<div class="space-y-2">
|
|
60
|
-
<!-- Section Title -->
|
|
61
|
-
<% if section[:title].present? %>
|
|
62
|
-
<% if section[:href] %>
|
|
63
|
-
<%= link_to section[:href], class: "px-3 text-xs font-semibold text-gray-500 uppercase tracking-wider" do %>
|
|
64
|
-
<%= section[:title] %>
|
|
65
|
-
<% end %>
|
|
66
|
-
<% else %>
|
|
67
|
-
<h3 class="px-3 text-xs font-semibold text-gray-500 uppercase tracking-wider">
|
|
68
|
-
<%= section[:title] %>
|
|
69
|
-
</h3>
|
|
70
|
-
<% end %>
|
|
71
|
-
<% end %>
|
|
72
|
-
|
|
73
|
-
<!-- Navigation Items -->
|
|
74
|
-
<div class="space-y-1">
|
|
75
|
-
<% (section[:items] || []).each do |item| %>
|
|
76
|
-
<% if item[:type] == :collapsible && collapsible %>
|
|
77
|
-
<!-- Collapsible Section -->
|
|
78
|
-
<div>
|
|
79
|
-
<button
|
|
80
|
-
type="button"
|
|
81
|
-
class="group flex items-center justify-between w-full px-3 py-2 text-sm font-medium text-gray-700 rounded-md hover:bg-gray-50 hover:text-gray-900 transition-colors duration-150"
|
|
82
|
-
data-bui-sidebar-target="sectionTrigger"
|
|
83
|
-
data-bui-sidebar-section-id="<%= item[:id] %>"
|
|
84
|
-
data-action="click->bui-sidebar#toggleSection"
|
|
85
|
-
aria-expanded="<%= item[:expanded] || false %>"
|
|
86
|
-
>
|
|
87
|
-
<div class="flex items-center">
|
|
88
|
-
<% if item[:icon].present? %>
|
|
89
|
-
<span class="mr-3 text-gray-400 group-hover:text-gray-500">
|
|
90
|
-
<%= bui_icon(item[:icon], size: :medium) %>
|
|
91
|
-
</span>
|
|
92
|
-
<% end %>
|
|
93
|
-
<span><%= item[:label] %></span>
|
|
94
|
-
</div>
|
|
95
|
-
<span class="ml-3 transform transition-transform duration-150 <%= 'rotate-90' if item[:expanded] %>" data-bui-sidebar-chevron>
|
|
96
|
-
<%= bui_icon("chevron-right", size: :small) %>
|
|
97
|
-
</span>
|
|
98
|
-
</button>
|
|
99
|
-
|
|
100
|
-
<div
|
|
101
|
-
data-bui-sidebar-target="sectionContent"
|
|
102
|
-
data-bui-sidebar-section-id="<%= item[:id] %>"
|
|
103
|
-
class="<%= item[:expanded] ? 'block' : 'hidden' %> mt-1 space-y-1"
|
|
104
|
-
>
|
|
105
|
-
<% (item[:children] || []).each do |child| %>
|
|
106
|
-
<% if child[:href].present? %>
|
|
107
|
-
<a
|
|
108
|
-
href="<%= child[:href] %>"
|
|
109
|
-
class="<%= (child[:active] || false) ? 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 bg-gray-100 text-gray-900' : 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 text-gray-700 hover:bg-gray-50 hover:text-gray-900' %> pl-11"
|
|
110
|
-
>
|
|
111
|
-
<% if child[:icon].present? %>
|
|
112
|
-
<span class="mr-3">
|
|
113
|
-
<%= bui_icon(child[:icon], size: :small) %>
|
|
114
|
-
</span>
|
|
115
|
-
<% end %>
|
|
116
|
-
<%= child[:label] %>
|
|
117
|
-
</a>
|
|
118
|
-
<% else %>
|
|
119
|
-
<div class="<%= (child[:active] || false) ? 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 bg-gray-100 text-gray-900' : 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 text-gray-700 hover:bg-gray-50 hover:text-gray-900' %> pl-11 cursor-default">
|
|
120
|
-
<% if child[:icon].present? %>
|
|
121
|
-
<span class="mr-3">
|
|
122
|
-
<%= bui_icon(child[:icon], size: :small) %>
|
|
123
|
-
</span>
|
|
124
|
-
<% end %>
|
|
125
|
-
<%= child[:label] %>
|
|
126
|
-
</div>
|
|
127
|
-
<% end %>
|
|
128
|
-
<% end %>
|
|
129
|
-
</div>
|
|
130
|
-
</div>
|
|
131
|
-
<% else %>
|
|
132
|
-
<!-- Regular Navigation Item -->
|
|
133
|
-
<% if item[:href].present? %>
|
|
134
|
-
<a
|
|
135
|
-
href="<%= item[:href] %>"
|
|
136
|
-
class="<%= (item[:active] || false) ? 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 bg-gray-100 text-gray-900' : 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 text-gray-700 hover:bg-gray-50 hover:text-gray-900' %>"
|
|
137
|
-
>
|
|
138
|
-
<% if item[:icon].present? %>
|
|
139
|
-
<span class="mr-3 text-gray-400 group-hover:text-gray-500">
|
|
140
|
-
<%= bui_icon(item[:icon], size: :medium) %>
|
|
141
|
-
</span>
|
|
142
|
-
<% end %>
|
|
143
|
-
<%= item[:label] %>
|
|
144
|
-
<% if item[:badge].present? %>
|
|
145
|
-
<span class="ml-auto inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
|
|
146
|
-
<%= item[:badge] %>
|
|
147
|
-
</span>
|
|
148
|
-
<% end %>
|
|
149
|
-
</a>
|
|
150
|
-
<% else %>
|
|
151
|
-
<div class="<%= (item[:active] || false) ? 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 bg-gray-100 text-gray-900' : 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 text-gray-700 hover:bg-gray-50 hover:text-gray-900' %> cursor-default">
|
|
152
|
-
<% if item[:icon].present? %>
|
|
153
|
-
<span class="mr-3 text-gray-400">
|
|
154
|
-
<%= bui_icon(item[:icon], size: :medium) %>
|
|
155
|
-
</span>
|
|
156
|
-
<% end %>
|
|
157
|
-
<%= item[:label] %>
|
|
158
|
-
<% if item[:badge].present? %>
|
|
159
|
-
<span class="ml-auto inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
|
|
160
|
-
<%= item[:badge] %>
|
|
161
|
-
</span>
|
|
162
|
-
<% end %>
|
|
163
|
-
</div>
|
|
164
|
-
<% end %>
|
|
165
|
-
<% end %>
|
|
166
|
-
<% end %>
|
|
167
|
-
</div>
|
|
168
|
-
</div>
|
|
169
|
-
<% end %>
|
|
170
|
-
|
|
171
|
-
<%= content if content.present? %>
|
|
172
|
-
</nav>
|
|
173
|
-
|
|
174
|
-
<!-- Footer Section -->
|
|
175
|
-
<% if has_footer? %>
|
|
176
|
-
<div class="px-6 py-4 border-t border-gray-200">
|
|
177
|
-
<% if footer[:user_info].present? %>
|
|
178
|
-
<div class="flex items-center">
|
|
179
|
-
<% if footer[:user_info][:avatar].present? %>
|
|
180
|
-
<div class="flex-shrink-0">
|
|
181
|
-
<% if footer[:user_info][:avatar].is_a?(Hash) %>
|
|
182
|
-
<%= bui_avatar(**footer[:user_info][:avatar]) %>
|
|
183
|
-
<% else %>
|
|
184
|
-
<%= footer[:user_info][:avatar].html_safe %>
|
|
185
|
-
<% end %>
|
|
186
|
-
</div>
|
|
187
|
-
<% end %>
|
|
188
|
-
<div class="<%= footer[:user_info][:avatar].present? ? 'ml-3' : '' %>">
|
|
189
|
-
<% if footer[:user_info][:name].present? %>
|
|
190
|
-
<p class="text-sm font-medium text-gray-700">
|
|
191
|
-
<%= footer[:user_info][:name] %>
|
|
192
|
-
</p>
|
|
193
|
-
<% end %>
|
|
194
|
-
<% if footer[:user_info][:email].present? %>
|
|
195
|
-
<p class="text-xs text-gray-500">
|
|
196
|
-
<%= footer[:user_info][:email] %>
|
|
197
|
-
</p>
|
|
198
|
-
<% end %>
|
|
199
|
-
</div>
|
|
200
|
-
<% if footer[:user_info][:menu_button].present? %>
|
|
201
|
-
<div class="ml-auto">
|
|
202
|
-
<%= footer[:user_info][:menu_button] %>
|
|
203
|
-
</div>
|
|
204
|
-
<% end %>
|
|
205
|
-
</div>
|
|
206
|
-
<% end %>
|
|
207
|
-
|
|
208
|
-
<% if footer[:content].present? %>
|
|
209
|
-
<div class="<%= footer[:user_info].present? ? 'mt-4' : '' %>">
|
|
210
|
-
<%= footer[:content] %>
|
|
211
|
-
</div>
|
|
212
|
-
<% end %>
|
|
213
|
-
</div>
|
|
214
|
-
<% end %>
|
|
215
|
-
|
|
216
|
-
<!-- Resize Handle (solo se NON collapsible) -->
|
|
217
|
-
<% unless collapsible %>
|
|
218
|
-
<div data-bui-sidebar-target="resizeHandle"
|
|
219
|
-
class="absolute top-0 right-0 w-1 h-full bg-transparent hover:bg-blue-500 cursor-col-resize transition-colors duration-150 group">
|
|
220
|
-
<div class="absolute inset-y-0 -right-1 w-3 flex items-center justify-center">
|
|
221
|
-
<div class="w-0.5 h-8 bg-gray-300 group-hover:bg-blue-500 transition-colors duration-150"></div>
|
|
222
|
-
</div>
|
|
223
|
-
</div>
|
|
224
|
-
<% end %>
|
|
225
|
-
</aside>
|
|
226
|
-
|
|
227
|
-
</div>
|