better_ui_tmp 0.5.1
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +211 -0
- data/Rakefile +8 -0
- data/app/assets/builds/application.js +1 -0
- data/app/assets/builds/better_ui.css +1 -0
- data/app/assets/stylesheets/better_ui.scss +3 -0
- data/app/components/better_ui/application/main/component.html.erb +5 -0
- data/app/components/better_ui/application/main/component.rb +99 -0
- data/app/components/better_ui/application/navbar/component.html.erb +219 -0
- data/app/components/better_ui/application/navbar/component.rb +148 -0
- data/app/components/better_ui/application/sidebar/component.html.erb +184 -0
- data/app/components/better_ui/application/sidebar/component.rb +129 -0
- data/app/components/better_ui/general/alert/component.html.erb +32 -0
- data/app/components/better_ui/general/alert/component.rb +242 -0
- data/app/components/better_ui/general/avatar/component.html.erb +20 -0
- data/app/components/better_ui/general/avatar/component.rb +301 -0
- data/app/components/better_ui/general/badge/component.html.erb +23 -0
- data/app/components/better_ui/general/badge/component.rb +248 -0
- data/app/components/better_ui/general/breadcrumb/component.html.erb +15 -0
- data/app/components/better_ui/general/breadcrumb/component.rb +186 -0
- data/app/components/better_ui/general/button/component.html.erb +34 -0
- data/app/components/better_ui/general/button/component.rb +214 -0
- data/app/components/better_ui/general/card/component.html.erb +21 -0
- data/app/components/better_ui/general/card/component.rb +37 -0
- data/app/components/better_ui/general/container/component.html.erb +8 -0
- data/app/components/better_ui/general/container/component.rb +158 -0
- data/app/components/better_ui/general/divider/component.html.erb +10 -0
- data/app/components/better_ui/general/divider/component.rb +226 -0
- data/app/components/better_ui/general/heading/component.html.erb +22 -0
- data/app/components/better_ui/general/heading/component.rb +257 -0
- data/app/components/better_ui/general/icon/component.html.erb +1 -0
- data/app/components/better_ui/general/icon/component.rb +222 -0
- data/app/components/better_ui/general/link/component.html.erb +18 -0
- data/app/components/better_ui/general/link/component.rb +255 -0
- data/app/components/better_ui/general/panel/component.html.erb +28 -0
- data/app/components/better_ui/general/panel/component.rb +249 -0
- data/app/components/better_ui/general/progress/component.html.erb +11 -0
- data/app/components/better_ui/general/progress/component.rb +160 -0
- data/app/components/better_ui/general/spinner/component.html.erb +35 -0
- data/app/components/better_ui/general/spinner/component.rb +93 -0
- data/app/components/better_ui/general/table/component.html.erb +5 -0
- data/app/components/better_ui/general/table/component.rb +217 -0
- data/app/components/better_ui/general/table/tbody_component.html.erb +3 -0
- data/app/components/better_ui/general/table/tbody_component.rb +30 -0
- data/app/components/better_ui/general/table/td_component.html.erb +3 -0
- data/app/components/better_ui/general/table/td_component.rb +44 -0
- data/app/components/better_ui/general/table/tfoot_component.html.erb +3 -0
- data/app/components/better_ui/general/table/tfoot_component.rb +28 -0
- data/app/components/better_ui/general/table/th_component.html.erb +6 -0
- data/app/components/better_ui/general/table/th_component.rb +51 -0
- data/app/components/better_ui/general/table/thead_component.html.erb +3 -0
- data/app/components/better_ui/general/table/thead_component.rb +28 -0
- data/app/components/better_ui/general/table/tr_component.html.erb +3 -0
- data/app/components/better_ui/general/table/tr_component.rb +30 -0
- data/app/components/better_ui/general/tag/component.html.erb +3 -0
- data/app/components/better_ui/general/tag/component.rb +104 -0
- data/app/components/better_ui/general/tooltip/component.html.erb +7 -0
- data/app/components/better_ui/general/tooltip/component.rb +239 -0
- data/app/controllers/better_ui/application_controller.rb +5 -0
- data/app/helpers/better_ui/application/components/main/main_helper.rb +42 -0
- data/app/helpers/better_ui/application/components/main.rb +13 -0
- data/app/helpers/better_ui/application/components/navbar/navbar_helper.rb +51 -0
- data/app/helpers/better_ui/application/components/navbar.rb +13 -0
- data/app/helpers/better_ui/application/components/sidebar/sidebar_helper.rb +51 -0
- data/app/helpers/better_ui/application/components/sidebar.rb +13 -0
- data/app/helpers/better_ui/application_helper.rb +10 -0
- data/app/helpers/better_ui/form_helper.rb +5 -0
- data/app/helpers/better_ui/general/components/alert/alert_helper.rb +29 -0
- data/app/helpers/better_ui/general/components/alert.rb +13 -0
- data/app/helpers/better_ui/general/components/avatar/avatar_helper.rb +29 -0
- data/app/helpers/better_ui/general/components/avatar.rb +13 -0
- data/app/helpers/better_ui/general/components/badge/badge_helper.rb +53 -0
- data/app/helpers/better_ui/general/components/badge.rb +13 -0
- data/app/helpers/better_ui/general/components/breadcrumb/breadcrumb_helper.rb +37 -0
- data/app/helpers/better_ui/general/components/breadcrumb.rb +13 -0
- data/app/helpers/better_ui/general/components/button/button_helper.rb +65 -0
- data/app/helpers/better_ui/general/components/button.rb +13 -0
- data/app/helpers/better_ui/general/components/card/card_helper.rb +37 -0
- data/app/helpers/better_ui/general/components/card.rb +13 -0
- data/app/helpers/better_ui/general/components/container/container_helper.rb +60 -0
- data/app/helpers/better_ui/general/components/container.rb +13 -0
- data/app/helpers/better_ui/general/components/divider/divider_helper.rb +63 -0
- data/app/helpers/better_ui/general/components/divider.rb +13 -0
- data/app/helpers/better_ui/general/components/heading/heading_helper.rb +72 -0
- data/app/helpers/better_ui/general/components/heading.rb +13 -0
- data/app/helpers/better_ui/general/components/icon/icon_helper.rb +16 -0
- data/app/helpers/better_ui/general/components/icon.rb +13 -0
- data/app/helpers/better_ui/general/components/link/link_helper.rb +89 -0
- data/app/helpers/better_ui/general/components/link.rb +13 -0
- data/app/helpers/better_ui/general/components/panel/panel_helper.rb +83 -0
- data/app/helpers/better_ui/general/components/panel.rb +13 -0
- data/app/helpers/better_ui/general/components/progress/progress_helper.rb +53 -0
- data/app/helpers/better_ui/general/components/progress.rb +11 -0
- data/app/helpers/better_ui/general/components/spinner/spinner_helper.rb +17 -0
- data/app/helpers/better_ui/general/components/spinner.rb +10 -0
- data/app/helpers/better_ui/general/components/table/table_helper.rb +13 -0
- data/app/helpers/better_ui/general/components/table/tbody_helper.rb +13 -0
- data/app/helpers/better_ui/general/components/table/td_helper.rb +19 -0
- data/app/helpers/better_ui/general/components/table/tfoot_helper.rb +13 -0
- data/app/helpers/better_ui/general/components/table/th_helper.rb +19 -0
- data/app/helpers/better_ui/general/components/table/thead_helper.rb +13 -0
- data/app/helpers/better_ui/general/components/table/tr_helper.rb +13 -0
- data/app/helpers/better_ui/general/components/table.rb +25 -0
- data/app/helpers/better_ui/general/components/tag/tag_helper.rb +26 -0
- data/app/helpers/better_ui/general/components/tag.rb +15 -0
- data/app/helpers/better_ui/general/components/tooltip/tooltip_helper.rb +60 -0
- data/app/helpers/better_ui/general/components/tooltip.rb +13 -0
- data/app/helpers/better_ui/general_helper.rb +24 -0
- data/app/helpers/better_ui_helper.rb +16 -0
- data/app/javascript/application.js +1 -0
- data/app/jobs/better_ui/application_job.rb +4 -0
- data/app/mailers/better_ui/application_mailer.rb +6 -0
- data/app/models/better_ui/application_record.rb +5 -0
- data/app/views/components/better_ui/general/table/_custom_body_row.html.erb +17 -0
- data/app/views/components/better_ui/general/table/_custom_footer_rows.html.erb +17 -0
- data/app/views/components/better_ui/general/table/_custom_header_rows.html.erb +12 -0
- data/app/views/layouts/component_preview.html.erb +32 -0
- data/config/initializers/lookbook.rb +23 -0
- data/config/routes.rb +3 -0
- data/lib/better_ui/engine.rb +109 -0
- data/lib/better_ui/version.rb +3 -0
- data/lib/better_ui.rb +37 -0
- data/lib/generators/better_ui/install_generator.rb +103 -0
- data/lib/generators/better_ui/stylesheet_generator.rb +159 -0
- data/lib/generators/better_ui/templates/components/_avatar.scss +200 -0
- data/lib/generators/better_ui/templates/components/_badge.scss +154 -0
- data/lib/generators/better_ui/templates/components/_breadcrumb.scss +106 -0
- data/lib/generators/better_ui/templates/components/_button.scss +109 -0
- data/lib/generators/better_ui/templates/components/_card.scss +60 -0
- data/lib/generators/better_ui/templates/components/_heading.scss +81 -0
- data/lib/generators/better_ui/templates/components/_icon.scss +134 -0
- data/lib/generators/better_ui/templates/components/_index.scss +17 -0
- data/lib/generators/better_ui/templates/components/_link.scss +100 -0
- data/lib/generators/better_ui/templates/components/_panel.scss +104 -0
- data/lib/generators/better_ui/templates/components/_spinner.scss +129 -0
- data/lib/generators/better_ui/templates/components/_table.scss +156 -0
- data/lib/generators/better_ui/templates/components/_variables.scss +0 -0
- data/lib/generators/better_ui/templates/components_stylesheet.scss +35 -0
- data/lib/generators/better_ui/templates/index.scss +18 -0
- data/lib/generators/better_ui/templates/initializer.rb +41 -0
- data/lib/tasks/better_ui_tasks.rake +4 -0
- metadata +260 -0
@@ -0,0 +1,148 @@
|
|
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, bui_avatar e bui_breadcrumb
|
8
|
+
include BetterUi::General::Components::Icon::IconHelper
|
9
|
+
include BetterUi::General::Components::Avatar::AvatarHelper
|
10
|
+
include BetterUi::General::Components::Breadcrumb::BreadcrumbHelper
|
11
|
+
attr_reader :theme, :position, :height, :shadow, :border, :brand, :breadcrumb, :navigation_items, :actions, :classes
|
12
|
+
|
13
|
+
# Temi navbar con classi Tailwind dirette
|
14
|
+
NAVBAR_THEMES = {
|
15
|
+
default: "bg-white text-gray-900 border-gray-200",
|
16
|
+
dark: "bg-gray-900 text-white border-gray-700",
|
17
|
+
light: "bg-gray-50 text-gray-900 border-gray-100"
|
18
|
+
}
|
19
|
+
|
20
|
+
# Altezze navbar con classi Tailwind dirette
|
21
|
+
NAVBAR_HEIGHTS = {
|
22
|
+
sm: "h-12",
|
23
|
+
md: "h-16",
|
24
|
+
lg: "h-20"
|
25
|
+
}
|
26
|
+
|
27
|
+
# Posizioni navbar con classi Tailwind dirette
|
28
|
+
NAVBAR_POSITIONS = {
|
29
|
+
top: "",
|
30
|
+
fixed_top: "fixed top-0 left-0 right-0 z-50",
|
31
|
+
sticky_top: "sticky top-0 z-40"
|
32
|
+
}
|
33
|
+
|
34
|
+
# Ombre navbar con classi Tailwind dirette
|
35
|
+
NAVBAR_SHADOWS = {
|
36
|
+
none: "",
|
37
|
+
sm: "shadow-sm",
|
38
|
+
md: "shadow-md",
|
39
|
+
lg: "shadow-lg",
|
40
|
+
xl: "shadow-xl"
|
41
|
+
}
|
42
|
+
|
43
|
+
# @param theme [Symbol] Tema colori (:default, :dark, :light), default :default
|
44
|
+
# @param position [Symbol] Posizione della navbar (:top, :fixed_top, :sticky_top), default :top
|
45
|
+
# @param height [Symbol] Altezza della navbar (:sm, :md, :lg), default :md
|
46
|
+
# @param shadow [Symbol] Tipo di ombra (:none, :sm, :md, :lg, :xl), default :sm
|
47
|
+
# @param border [Boolean] Se mostrare il bordo inferiore, default true
|
48
|
+
# @param brand [Hash] Configurazione brand (logo, title, href)
|
49
|
+
# @param breadcrumb [Hash] Configurazione breadcrumb (items, separator, theme)
|
50
|
+
# @param navigation_items [Array] Array di elementi di navigazione centrali
|
51
|
+
# @param actions [Array] Array di azioni/pulsanti a destra
|
52
|
+
# @param classes [String] Classi CSS aggiuntive
|
53
|
+
def initialize(
|
54
|
+
theme: :default,
|
55
|
+
position: :top,
|
56
|
+
height: :md,
|
57
|
+
shadow: :sm,
|
58
|
+
border: true,
|
59
|
+
brand: {},
|
60
|
+
breadcrumb: {},
|
61
|
+
navigation_items: [],
|
62
|
+
actions: [],
|
63
|
+
classes: nil
|
64
|
+
)
|
65
|
+
@theme = theme.to_sym
|
66
|
+
@position = position.to_sym
|
67
|
+
@height = height.to_sym
|
68
|
+
@shadow = shadow.to_sym
|
69
|
+
@border = border
|
70
|
+
@brand = brand || {}
|
71
|
+
@breadcrumb = breadcrumb || {}
|
72
|
+
@navigation_items = navigation_items || []
|
73
|
+
@actions = actions || []
|
74
|
+
@classes = classes
|
75
|
+
end
|
76
|
+
|
77
|
+
def container_classes
|
78
|
+
base_classes = %w[w-full flex items-center justify-between px-4 sm:px-6 lg:px-8]
|
79
|
+
|
80
|
+
# Posizione
|
81
|
+
base_classes.concat(position_classes.split) if position != :top
|
82
|
+
|
83
|
+
# Altezza
|
84
|
+
base_classes << height_class
|
85
|
+
|
86
|
+
# Tema
|
87
|
+
base_classes.concat(theme_classes.split)
|
88
|
+
|
89
|
+
# Shadow
|
90
|
+
base_classes << shadow_class if shadow != :none
|
91
|
+
|
92
|
+
# Border
|
93
|
+
base_classes << "border-b" if border
|
94
|
+
|
95
|
+
# Classi aggiuntive
|
96
|
+
base_classes << classes if classes.present?
|
97
|
+
|
98
|
+
base_classes.compact.join(" ")
|
99
|
+
end
|
100
|
+
|
101
|
+
def has_brand?
|
102
|
+
brand.present? && (brand[:title].present? || brand[:logo].present?)
|
103
|
+
end
|
104
|
+
|
105
|
+
def has_breadcrumb?
|
106
|
+
breadcrumb.present? && breadcrumb[:items].present? && breadcrumb[:items].any?
|
107
|
+
end
|
108
|
+
|
109
|
+
def has_navigation?
|
110
|
+
navigation_items.present? && navigation_items.any?
|
111
|
+
end
|
112
|
+
|
113
|
+
def has_actions?
|
114
|
+
actions.present? && actions.any?
|
115
|
+
end
|
116
|
+
|
117
|
+
def render_breadcrumb
|
118
|
+
return unless has_breadcrumb?
|
119
|
+
|
120
|
+
bui_breadcrumb(
|
121
|
+
items: breadcrumb[:items],
|
122
|
+
separator: breadcrumb[:separator] || :chevron,
|
123
|
+
theme: breadcrumb[:theme] || theme,
|
124
|
+
size: :small
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def position_classes
|
131
|
+
NAVBAR_POSITIONS[@position] || NAVBAR_POSITIONS[:top]
|
132
|
+
end
|
133
|
+
|
134
|
+
def height_class
|
135
|
+
NAVBAR_HEIGHTS[@height] || NAVBAR_HEIGHTS[:md]
|
136
|
+
end
|
137
|
+
|
138
|
+
def theme_classes
|
139
|
+
NAVBAR_THEMES[@theme] || NAVBAR_THEMES[:default]
|
140
|
+
end
|
141
|
+
|
142
|
+
def shadow_class
|
143
|
+
NAVBAR_SHADOWS[@shadow] || NAVBAR_SHADOWS[:sm]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
<aside class="<%= container_classes %>">
|
2
|
+
<!-- Header Section -->
|
3
|
+
<% if has_header? %>
|
4
|
+
<div class="px-6 py-4 border-b border-gray-200">
|
5
|
+
<% if header[:logo].present? %>
|
6
|
+
<div class="flex items-center">
|
7
|
+
<div class="flex-shrink-0">
|
8
|
+
<% if header[:logo].is_a?(Hash) %>
|
9
|
+
<%= bui_avatar(**header[:logo]) %>
|
10
|
+
<% else %>
|
11
|
+
<%= header[:logo].html_safe %>
|
12
|
+
<% end %>
|
13
|
+
</div>
|
14
|
+
<% if header[:title].present? %>
|
15
|
+
<div class="ml-3">
|
16
|
+
<h2 class="text-lg font-semibold text-gray-900"><%= header[:title] %></h2>
|
17
|
+
<% if header[:subtitle].present? %>
|
18
|
+
<p class="text-sm text-gray-500"><%= header[:subtitle] %></p>
|
19
|
+
<% end %>
|
20
|
+
</div>
|
21
|
+
<% end %>
|
22
|
+
</div>
|
23
|
+
<% elsif header[:title].present? %>
|
24
|
+
<div>
|
25
|
+
<h2 class="text-lg font-semibold text-gray-900"><%= header[:title] %></h2>
|
26
|
+
<% if header[:subtitle].present? %>
|
27
|
+
<p class="text-sm text-gray-500"><%= header[:subtitle] %></p>
|
28
|
+
<% end %>
|
29
|
+
</div>
|
30
|
+
<% end %>
|
31
|
+
</div>
|
32
|
+
<% end %>
|
33
|
+
|
34
|
+
<!-- Navigation Section -->
|
35
|
+
<nav class="flex-1 px-4 py-6 space-y-6">
|
36
|
+
<% navigation_sections.each do |section| %>
|
37
|
+
<div class="space-y-2">
|
38
|
+
<!-- Section Title -->
|
39
|
+
<% if section[:title].present? %>
|
40
|
+
<h3 class="px-3 text-xs font-semibold text-gray-500 uppercase tracking-wider">
|
41
|
+
<%= section[:title] %>
|
42
|
+
</h3>
|
43
|
+
<% end %>
|
44
|
+
|
45
|
+
<!-- Navigation Items -->
|
46
|
+
<div class="space-y-1">
|
47
|
+
<% (section[:items] || []).each do |item| %>
|
48
|
+
<% if item[:type] == :collapsible && collapsible %>
|
49
|
+
<!-- Collapsible Section -->
|
50
|
+
<div>
|
51
|
+
<button
|
52
|
+
type="button"
|
53
|
+
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"
|
54
|
+
data-collapse-target="#<%= item[:id] %>"
|
55
|
+
aria-expanded="<%= item[:expanded] || false %>"
|
56
|
+
>
|
57
|
+
<div class="flex items-center">
|
58
|
+
<% if item[:icon].present? %>
|
59
|
+
<span class="mr-3 text-gray-400 group-hover:text-gray-500">
|
60
|
+
<%= bui_icon(item[:icon], size: :medium) %>
|
61
|
+
</span>
|
62
|
+
<% end %>
|
63
|
+
<span><%= item[:label] %></span>
|
64
|
+
</div>
|
65
|
+
<span class="ml-3 transform transition-transform duration-150 <%= 'rotate-90' if item[:expanded] %>">
|
66
|
+
<%= bui_icon("chevron-right", size: :small) %>
|
67
|
+
</span>
|
68
|
+
</button>
|
69
|
+
|
70
|
+
<div
|
71
|
+
id="<%= item[:id] %>"
|
72
|
+
class="<%= item[:expanded] ? 'block' : 'hidden' %> mt-1 space-y-1"
|
73
|
+
>
|
74
|
+
<% (item[:children] || []).each do |child| %>
|
75
|
+
<% if child[:href].present? %>
|
76
|
+
<a
|
77
|
+
href="<%= child[:href] %>"
|
78
|
+
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"
|
79
|
+
>
|
80
|
+
<% if child[:icon].present? %>
|
81
|
+
<span class="mr-3">
|
82
|
+
<%= bui_icon(child[:icon], size: :small) %>
|
83
|
+
</span>
|
84
|
+
<% end %>
|
85
|
+
<%= child[:label] %>
|
86
|
+
</a>
|
87
|
+
<% else %>
|
88
|
+
<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">
|
89
|
+
<% if child[:icon].present? %>
|
90
|
+
<span class="mr-3">
|
91
|
+
<%= bui_icon(child[:icon], size: :small) %>
|
92
|
+
</span>
|
93
|
+
<% end %>
|
94
|
+
<%= child[:label] %>
|
95
|
+
</div>
|
96
|
+
<% end %>
|
97
|
+
<% end %>
|
98
|
+
</div>
|
99
|
+
</div>
|
100
|
+
<% else %>
|
101
|
+
<!-- Regular Navigation Item -->
|
102
|
+
<% if item[:href].present? %>
|
103
|
+
<a
|
104
|
+
href="<%= item[:href] %>"
|
105
|
+
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' %>"
|
106
|
+
>
|
107
|
+
<% if item[:icon].present? %>
|
108
|
+
<span class="mr-3 text-gray-400 group-hover:text-gray-500">
|
109
|
+
<%= bui_icon(item[:icon], size: :medium) %>
|
110
|
+
</span>
|
111
|
+
<% end %>
|
112
|
+
<%= item[:label] %>
|
113
|
+
<% if item[:badge].present? %>
|
114
|
+
<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">
|
115
|
+
<%= item[:badge] %>
|
116
|
+
</span>
|
117
|
+
<% end %>
|
118
|
+
</a>
|
119
|
+
<% else %>
|
120
|
+
<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">
|
121
|
+
<% if item[:icon].present? %>
|
122
|
+
<span class="mr-3 text-gray-400">
|
123
|
+
<%= bui_icon(item[:icon], size: :medium) %>
|
124
|
+
</span>
|
125
|
+
<% end %>
|
126
|
+
<%= item[:label] %>
|
127
|
+
<% if item[:badge].present? %>
|
128
|
+
<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">
|
129
|
+
<%= item[:badge] %>
|
130
|
+
</span>
|
131
|
+
<% end %>
|
132
|
+
</div>
|
133
|
+
<% end %>
|
134
|
+
<% end %>
|
135
|
+
<% end %>
|
136
|
+
</div>
|
137
|
+
</div>
|
138
|
+
<% end %>
|
139
|
+
|
140
|
+
<%= content if content.present? %>
|
141
|
+
</nav>
|
142
|
+
|
143
|
+
<!-- Footer Section -->
|
144
|
+
<% if has_footer? %>
|
145
|
+
<div class="px-6 py-4 border-t border-gray-200">
|
146
|
+
<% if footer[:user_info].present? %>
|
147
|
+
<div class="flex items-center">
|
148
|
+
<% if footer[:user_info][:avatar].present? %>
|
149
|
+
<div class="flex-shrink-0">
|
150
|
+
<% if footer[:user_info][:avatar].is_a?(Hash) %>
|
151
|
+
<%= bui_avatar(**footer[:user_info][:avatar]) %>
|
152
|
+
<% else %>
|
153
|
+
<%= footer[:user_info][:avatar].html_safe %>
|
154
|
+
<% end %>
|
155
|
+
</div>
|
156
|
+
<% end %>
|
157
|
+
<div class="<%= footer[:user_info][:avatar].present? ? 'ml-3' : '' %>">
|
158
|
+
<% if footer[:user_info][:name].present? %>
|
159
|
+
<p class="text-sm font-medium text-gray-700">
|
160
|
+
<%= footer[:user_info][:name] %>
|
161
|
+
</p>
|
162
|
+
<% end %>
|
163
|
+
<% if footer[:user_info][:email].present? %>
|
164
|
+
<p class="text-xs text-gray-500">
|
165
|
+
<%= footer[:user_info][:email] %>
|
166
|
+
</p>
|
167
|
+
<% end %>
|
168
|
+
</div>
|
169
|
+
<% if footer[:user_info][:menu_button].present? %>
|
170
|
+
<div class="ml-auto">
|
171
|
+
<%= footer[:user_info][:menu_button] %>
|
172
|
+
</div>
|
173
|
+
<% end %>
|
174
|
+
</div>
|
175
|
+
<% end %>
|
176
|
+
|
177
|
+
<% if footer[:content].present? %>
|
178
|
+
<div class="<%= footer[:user_info].present? ? 'mt-4' : '' %>">
|
179
|
+
<%= footer[:content] %>
|
180
|
+
</div>
|
181
|
+
<% end %>
|
182
|
+
</div>
|
183
|
+
<% end %>
|
184
|
+
</aside>
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BetterUi
|
4
|
+
module Application
|
5
|
+
module Sidebar
|
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
|
+
attr_reader :width, :position, :theme, :shadow, :border, :header, :footer, :navigation_sections, :collapsible, :classes
|
11
|
+
|
12
|
+
# Larghezze sidebar con classi Tailwind dirette
|
13
|
+
SIDEBAR_WIDTHS = {
|
14
|
+
sm: "w-48",
|
15
|
+
md: "w-64",
|
16
|
+
lg: "w-72",
|
17
|
+
xl: "w-80"
|
18
|
+
}
|
19
|
+
|
20
|
+
# Temi sidebar con classi Tailwind dirette
|
21
|
+
SIDEBAR_THEMES = {
|
22
|
+
default: "bg-white text-gray-900",
|
23
|
+
dark: "bg-gray-900 text-white",
|
24
|
+
light: "bg-white text-gray-900"
|
25
|
+
}
|
26
|
+
|
27
|
+
# Ombre sidebar con classi Tailwind dirette
|
28
|
+
SIDEBAR_SHADOWS = {
|
29
|
+
none: "",
|
30
|
+
sm: "shadow-sm",
|
31
|
+
md: "shadow-md",
|
32
|
+
lg: "shadow-lg",
|
33
|
+
xl: "shadow-xl"
|
34
|
+
}
|
35
|
+
|
36
|
+
# Bordi sidebar con classi Tailwind dirette
|
37
|
+
SIDEBAR_BORDERS = {
|
38
|
+
left: "border-r border-gray-200",
|
39
|
+
right: "border-l border-gray-200"
|
40
|
+
}
|
41
|
+
|
42
|
+
# @param width [Symbol] Larghezza della sidebar (:sm, :md, :lg, :xl), default :md (w-64)
|
43
|
+
# @param position [Symbol] Posizione della sidebar (:left, :right), default :left
|
44
|
+
# @param theme [Symbol] Tema colori (:default, :dark, :light), default :default
|
45
|
+
# @param shadow [Symbol] Tipo di ombra (:none, :sm, :md, :lg), default :lg
|
46
|
+
# @param border [Boolean] Se mostrare il bordo destro/sinistro, default true
|
47
|
+
# @param header [Hash] Configurazione header (logo, title, subtitle)
|
48
|
+
# @param footer [Hash] Configurazione footer (content, user_info)
|
49
|
+
# @param navigation_sections [Array] Array di sezioni di navigazione
|
50
|
+
# @param collapsible [Boolean] Se abilitare sezioni collassabili, default true
|
51
|
+
# @param classes [String] Classi CSS aggiuntive
|
52
|
+
def initialize(
|
53
|
+
width: :md,
|
54
|
+
position: :left,
|
55
|
+
theme: :default,
|
56
|
+
shadow: :lg,
|
57
|
+
border: true,
|
58
|
+
header: {},
|
59
|
+
footer: {},
|
60
|
+
navigation_sections: [],
|
61
|
+
collapsible: true,
|
62
|
+
classes: nil
|
63
|
+
)
|
64
|
+
@width = width.to_sym
|
65
|
+
@position = position.to_sym
|
66
|
+
@theme = theme.to_sym
|
67
|
+
@shadow = shadow.to_sym
|
68
|
+
@border = border
|
69
|
+
@header = header || {}
|
70
|
+
@footer = footer || {}
|
71
|
+
@navigation_sections = navigation_sections || []
|
72
|
+
@collapsible = collapsible
|
73
|
+
@classes = classes
|
74
|
+
end
|
75
|
+
|
76
|
+
def container_classes
|
77
|
+
base_classes = %w[fixed inset-y-0 z-50 flex flex-col overflow-y-auto]
|
78
|
+
|
79
|
+
# Posizione
|
80
|
+
base_classes << (position == :right ? "right-0" : "left-0")
|
81
|
+
|
82
|
+
# Larghezza
|
83
|
+
base_classes << width_class
|
84
|
+
|
85
|
+
# Tema
|
86
|
+
base_classes.concat(theme_classes)
|
87
|
+
|
88
|
+
# Shadow
|
89
|
+
base_classes << shadow_class if shadow != :none
|
90
|
+
|
91
|
+
# Border
|
92
|
+
base_classes << border_class if border
|
93
|
+
|
94
|
+
# Classi aggiuntive
|
95
|
+
base_classes << classes if classes.present?
|
96
|
+
|
97
|
+
base_classes.compact.join(" ")
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
def has_header?
|
102
|
+
header.present? && (header[:title].present? || header[:logo].present?)
|
103
|
+
end
|
104
|
+
|
105
|
+
def has_footer?
|
106
|
+
footer.present? && (footer[:content].present? || footer[:user_info].present?)
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def width_class
|
112
|
+
SIDEBAR_WIDTHS[@width] || SIDEBAR_WIDTHS[:md]
|
113
|
+
end
|
114
|
+
|
115
|
+
def theme_classes
|
116
|
+
(SIDEBAR_THEMES[@theme] || SIDEBAR_THEMES[:default]).split
|
117
|
+
end
|
118
|
+
|
119
|
+
def shadow_class
|
120
|
+
SIDEBAR_SHADOWS[@shadow] || SIDEBAR_SHADOWS[:none]
|
121
|
+
end
|
122
|
+
|
123
|
+
def border_class
|
124
|
+
SIDEBAR_BORDERS[@position] || SIDEBAR_BORDERS[:left]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<div <%= tag.attributes(alert_attributes) %>>
|
2
|
+
<% if (@icon.blank? ? default_icon : @icon) && @icon_position == :left %>
|
3
|
+
<div class="<%= get_icon_classes %> <%= get_icon_theme_class %>">
|
4
|
+
<%= render BetterUi::General::Icon::Component.new(name: @icon.blank? ? default_icon : @icon) %>
|
5
|
+
</div>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<div class="<%= get_content_classes %>">
|
9
|
+
<% if @title.present? %>
|
10
|
+
<div class="<%= ALERT_TITLE_CLASSES %>"><%= @title %></div>
|
11
|
+
<% end %>
|
12
|
+
<div class="<%= ALERT_MESSAGE_CLASSES %>">
|
13
|
+
<% if @html_content %>
|
14
|
+
<%= raw @message %>
|
15
|
+
<% else %>
|
16
|
+
<%= @message %>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<% if (@icon.blank? ? default_icon : @icon) && @icon_position == :right %>
|
22
|
+
<div class="<%= get_icon_classes %> <%= get_icon_theme_class %>">
|
23
|
+
<%= render BetterUi::General::Icon::Component.new(name: @icon.blank? ? default_icon : @icon) %>
|
24
|
+
</div>
|
25
|
+
<% end %>
|
26
|
+
|
27
|
+
<% if @dismissible %>
|
28
|
+
<button type="button" class="<%= get_close_classes %>" aria-label="Chiudi">
|
29
|
+
<%= render BetterUi::General::Icon::Component.new(name: "x", size: :sm) %>
|
30
|
+
</button>
|
31
|
+
<% end %>
|
32
|
+
</div>
|