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,130 +0,0 @@
|
|
|
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, bui_avatar e bui_button
|
|
8
|
-
include BetterUi::General::Components::Icon::IconHelper
|
|
9
|
-
include BetterUi::General::Components::Avatar::AvatarHelper
|
|
10
|
-
include BetterUi::General::Components::Button::ButtonHelper
|
|
11
|
-
attr_reader :width, :position, :theme, :shadow, :border, :header, :footer, :navigation_sections, :collapsible, :classes
|
|
12
|
-
|
|
13
|
-
# Larghezze sidebar con classi Tailwind dirette
|
|
14
|
-
SIDEBAR_WIDTHS = {
|
|
15
|
-
sm: "w-48",
|
|
16
|
-
md: "w-64",
|
|
17
|
-
lg: "w-72",
|
|
18
|
-
xl: "w-80"
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
# Temi sidebar con classi Tailwind dirette
|
|
22
|
-
SIDEBAR_THEMES = {
|
|
23
|
-
default: "bg-white text-gray-900",
|
|
24
|
-
dark: "bg-gray-900 text-white",
|
|
25
|
-
light: "bg-white text-gray-900"
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
# Ombre sidebar con classi Tailwind dirette
|
|
29
|
-
SIDEBAR_SHADOWS = {
|
|
30
|
-
none: "",
|
|
31
|
-
sm: "shadow-sm",
|
|
32
|
-
md: "shadow-md",
|
|
33
|
-
lg: "shadow-lg",
|
|
34
|
-
xl: "shadow-xl"
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
# Bordi sidebar con classi Tailwind dirette
|
|
38
|
-
SIDEBAR_BORDERS = {
|
|
39
|
-
left: "border-r border-gray-200",
|
|
40
|
-
right: "border-l border-gray-200"
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
# @param width [Symbol] Larghezza della sidebar (:sm, :md, :lg, :xl), default :md (w-64)
|
|
44
|
-
# @param position [Symbol] Posizione della sidebar (:left, :right), default :left
|
|
45
|
-
# @param theme [Symbol] Tema colori (:default, :dark, :light), default :default
|
|
46
|
-
# @param shadow [Symbol] Tipo di ombra (:none, :sm, :md, :lg), default :lg
|
|
47
|
-
# @param border [Boolean] Se mostrare il bordo destro/sinistro, default true
|
|
48
|
-
# @param header [Hash] Configurazione header (logo, title, subtitle)
|
|
49
|
-
# @param footer [Hash] Configurazione footer (content, user_info)
|
|
50
|
-
# @param navigation_sections [Array] Array di sezioni di navigazione
|
|
51
|
-
# @param collapsible [Boolean] Se abilitare sezioni collassabili, default true
|
|
52
|
-
# @param classes [String] Classi CSS aggiuntive
|
|
53
|
-
def initialize(
|
|
54
|
-
width: :md,
|
|
55
|
-
position: :left,
|
|
56
|
-
theme: :default,
|
|
57
|
-
shadow: :lg,
|
|
58
|
-
border: true,
|
|
59
|
-
header: {},
|
|
60
|
-
footer: {},
|
|
61
|
-
navigation_sections: [],
|
|
62
|
-
collapsible: true,
|
|
63
|
-
classes: nil
|
|
64
|
-
)
|
|
65
|
-
@width = width.to_sym
|
|
66
|
-
@position = position.to_sym
|
|
67
|
-
@theme = theme.to_sym
|
|
68
|
-
@shadow = shadow.to_sym
|
|
69
|
-
@border = border
|
|
70
|
-
@header = header || {}
|
|
71
|
-
@footer = footer || {}
|
|
72
|
-
@navigation_sections = navigation_sections || []
|
|
73
|
-
@collapsible = collapsible
|
|
74
|
-
@classes = classes
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def container_classes
|
|
78
|
-
base_classes = %w[fixed inset-y-0 h-screen z-50 flex flex-col]
|
|
79
|
-
|
|
80
|
-
# Posizione
|
|
81
|
-
base_classes << (position == :right ? "right-0" : "left-0")
|
|
82
|
-
|
|
83
|
-
# Larghezza
|
|
84
|
-
base_classes << width_class
|
|
85
|
-
|
|
86
|
-
# Tema
|
|
87
|
-
base_classes.concat(theme_classes)
|
|
88
|
-
|
|
89
|
-
# Shadow
|
|
90
|
-
base_classes << shadow_class if shadow != :none
|
|
91
|
-
|
|
92
|
-
# Border
|
|
93
|
-
base_classes << border_class if border
|
|
94
|
-
|
|
95
|
-
# Classi aggiuntive
|
|
96
|
-
base_classes << classes if classes.present?
|
|
97
|
-
|
|
98
|
-
base_classes.compact.join(" ")
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
def has_header?
|
|
103
|
-
header.present? && (header[:title].present? || header[:logo].present?)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def has_footer?
|
|
107
|
-
footer.present? && (footer[:content].present? || footer[:user_info].present?)
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
private
|
|
111
|
-
|
|
112
|
-
def width_class
|
|
113
|
-
SIDEBAR_WIDTHS[@width] || SIDEBAR_WIDTHS[:md]
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def theme_classes
|
|
117
|
-
(SIDEBAR_THEMES[@theme] || SIDEBAR_THEMES[:default]).split
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def shadow_class
|
|
121
|
-
SIDEBAR_SHADOWS[@shadow] || SIDEBAR_SHADOWS[:none]
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def border_class
|
|
125
|
-
SIDEBAR_BORDERS[@position] || SIDEBAR_BORDERS[:left]
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
end
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module BetterUi
|
|
4
|
-
module General
|
|
5
|
-
module Accordion
|
|
6
|
-
class Component < ViewComponent::Base
|
|
7
|
-
renders_many :items, "BetterUi::General::Accordion::ItemComponent"
|
|
8
|
-
|
|
9
|
-
ACCORDION_THEME = {
|
|
10
|
-
default: 'border-gray-200',
|
|
11
|
-
white: 'border-gray-100 bg-white',
|
|
12
|
-
blue: 'border-blue-200',
|
|
13
|
-
red: 'border-red-200',
|
|
14
|
-
green: 'border-green-200',
|
|
15
|
-
yellow: 'border-yellow-200',
|
|
16
|
-
violet: 'border-violet-200',
|
|
17
|
-
orange: 'border-orange-200',
|
|
18
|
-
rose: 'border-rose-200'
|
|
19
|
-
}.freeze
|
|
20
|
-
|
|
21
|
-
ACCORDION_VARIANT = {
|
|
22
|
-
minimal: '',
|
|
23
|
-
bordered: 'border rounded-lg',
|
|
24
|
-
separated: 'space-y-2'
|
|
25
|
-
}.freeze
|
|
26
|
-
|
|
27
|
-
ACCORDION_SIZE = {
|
|
28
|
-
small: 'text-sm',
|
|
29
|
-
medium: 'text-base',
|
|
30
|
-
large: 'text-lg'
|
|
31
|
-
}.freeze
|
|
32
|
-
|
|
33
|
-
def initialize(multiple: false, theme: :default, variant: :bordered, size: :medium,
|
|
34
|
-
classes: '', **options)
|
|
35
|
-
@multiple = multiple
|
|
36
|
-
@theme = theme
|
|
37
|
-
@variant = variant
|
|
38
|
-
@size = size
|
|
39
|
-
@classes = classes
|
|
40
|
-
@options = options
|
|
41
|
-
|
|
42
|
-
validate_params
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
private
|
|
46
|
-
|
|
47
|
-
attr_reader :multiple, :theme, :variant, :size, :classes, :options
|
|
48
|
-
|
|
49
|
-
def validate_params
|
|
50
|
-
validate_theme
|
|
51
|
-
validate_variant
|
|
52
|
-
validate_size
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def validate_theme
|
|
56
|
-
return if ACCORDION_THEME.key?(theme)
|
|
57
|
-
|
|
58
|
-
raise ArgumentError, "Invalid theme: #{theme}. Must be one of #{ACCORDION_THEME.keys}"
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def validate_variant
|
|
62
|
-
return if ACCORDION_VARIANT.key?(variant)
|
|
63
|
-
|
|
64
|
-
raise ArgumentError, "Invalid variant: #{variant}. Must be one of #{ACCORDION_VARIANT.keys}"
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def validate_size
|
|
68
|
-
return if ACCORDION_SIZE.key?(size)
|
|
69
|
-
|
|
70
|
-
raise ArgumentError, "Invalid size: #{size}. Must be one of #{ACCORDION_SIZE.keys}"
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# Attributi per il wrapper principale
|
|
74
|
-
def wrapper_attributes
|
|
75
|
-
base_classes = [
|
|
76
|
-
'bui-accordion',
|
|
77
|
-
ACCORDION_SIZE[size],
|
|
78
|
-
ACCORDION_VARIANT[variant],
|
|
79
|
-
ACCORDION_THEME[theme],
|
|
80
|
-
classes
|
|
81
|
-
].compact.join(' ')
|
|
82
|
-
|
|
83
|
-
{
|
|
84
|
-
class: base_classes,
|
|
85
|
-
'data-controller': 'bui-accordion',
|
|
86
|
-
'data-bui-accordion-multiple-value': multiple
|
|
87
|
-
}.merge(options)
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<div <%= tag.attributes(item_attributes) %>>
|
|
2
|
-
<!-- Header -->
|
|
3
|
-
<button <%= tag.attributes(header_attributes) %>>
|
|
4
|
-
<span><%= title %></span>
|
|
5
|
-
<i class="fas fa-<%= icon %> <%= icon_attributes[:class] %>" <%= tag.attributes(icon_attributes.except(:class)) %>></i>
|
|
6
|
-
</button>
|
|
7
|
-
|
|
8
|
-
<!-- Content -->
|
|
9
|
-
<div <%= tag.attributes(content_attributes) %>>
|
|
10
|
-
<%= content %>
|
|
11
|
-
</div>
|
|
12
|
-
</div>
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module BetterUi
|
|
4
|
-
module General
|
|
5
|
-
module Accordion
|
|
6
|
-
class ItemComponent < ViewComponent::Base
|
|
7
|
-
ITEM_THEME = {
|
|
8
|
-
default: 'border-gray-200 bg-white',
|
|
9
|
-
white: 'border-gray-100 bg-white',
|
|
10
|
-
blue: 'border-blue-200 bg-blue-50',
|
|
11
|
-
red: 'border-red-200 bg-red-50',
|
|
12
|
-
green: 'border-green-200 bg-green-50',
|
|
13
|
-
yellow: 'border-yellow-200 bg-yellow-50',
|
|
14
|
-
violet: 'border-violet-200 bg-violet-50',
|
|
15
|
-
orange: 'border-orange-200 bg-orange-50',
|
|
16
|
-
rose: 'border-rose-200 bg-rose-50'
|
|
17
|
-
}.freeze
|
|
18
|
-
|
|
19
|
-
ITEM_HEADER_THEME = {
|
|
20
|
-
default: 'text-gray-900 hover:bg-gray-50',
|
|
21
|
-
white: 'text-gray-900 hover:bg-gray-50',
|
|
22
|
-
blue: 'text-blue-900 hover:bg-blue-100',
|
|
23
|
-
red: 'text-red-900 hover:bg-red-100',
|
|
24
|
-
green: 'text-green-900 hover:bg-green-100',
|
|
25
|
-
yellow: 'text-yellow-900 hover:bg-yellow-100',
|
|
26
|
-
violet: 'text-violet-900 hover:bg-violet-100',
|
|
27
|
-
orange: 'text-orange-900 hover:bg-orange-100',
|
|
28
|
-
rose: 'text-rose-900 hover:bg-rose-100'
|
|
29
|
-
}.freeze
|
|
30
|
-
|
|
31
|
-
ITEM_SIZE_HEADER = {
|
|
32
|
-
small: 'text-sm px-4 py-3',
|
|
33
|
-
medium: 'text-base px-5 py-4',
|
|
34
|
-
large: 'text-lg px-6 py-5'
|
|
35
|
-
}.freeze
|
|
36
|
-
|
|
37
|
-
ITEM_SIZE_CONTENT = {
|
|
38
|
-
small: 'px-4 py-3',
|
|
39
|
-
medium: 'px-5 py-4',
|
|
40
|
-
large: 'px-6 py-5'
|
|
41
|
-
}.freeze
|
|
42
|
-
|
|
43
|
-
ITEM_SIZE_ICON = {
|
|
44
|
-
small: 'w-4 h-4',
|
|
45
|
-
medium: 'w-5 h-5',
|
|
46
|
-
large: 'w-6 h-6'
|
|
47
|
-
}.freeze
|
|
48
|
-
|
|
49
|
-
def initialize(title:, expanded: false, disabled: false, icon: 'chevron-down',
|
|
50
|
-
theme: :default, size: :medium, classes: '', **options)
|
|
51
|
-
@title = title
|
|
52
|
-
@expanded = expanded
|
|
53
|
-
@disabled = disabled
|
|
54
|
-
@icon = icon
|
|
55
|
-
@theme = theme
|
|
56
|
-
@size = size
|
|
57
|
-
@classes = classes
|
|
58
|
-
@options = options
|
|
59
|
-
|
|
60
|
-
validate_params
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
private
|
|
64
|
-
|
|
65
|
-
attr_reader :title, :expanded, :disabled, :icon, :theme, :size, :classes, :options
|
|
66
|
-
|
|
67
|
-
def validate_params
|
|
68
|
-
validate_theme
|
|
69
|
-
validate_size
|
|
70
|
-
|
|
71
|
-
raise ArgumentError, 'title cannot be blank' if title.blank?
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def validate_theme
|
|
75
|
-
return if ITEM_THEME.key?(theme)
|
|
76
|
-
|
|
77
|
-
raise ArgumentError, "Invalid theme: #{theme}. Must be one of #{ITEM_THEME.keys}"
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def validate_size
|
|
81
|
-
return if ITEM_SIZE_HEADER.key?(size)
|
|
82
|
-
|
|
83
|
-
raise ArgumentError, "Invalid size: #{size}. Must be one of #{ITEM_SIZE_HEADER.keys}"
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def unique_id
|
|
87
|
-
@unique_id ||= "accordion-item-#{SecureRandom.hex(4)}"
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def content_id
|
|
91
|
-
"#{unique_id}-content"
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def header_id
|
|
95
|
-
"#{unique_id}-header"
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# Attributi per il wrapper dell'item
|
|
99
|
-
def item_attributes
|
|
100
|
-
base_classes = [
|
|
101
|
-
'bui-accordion-item',
|
|
102
|
-
ITEM_THEME[theme],
|
|
103
|
-
classes
|
|
104
|
-
].compact.join(' ')
|
|
105
|
-
|
|
106
|
-
{
|
|
107
|
-
class: base_classes,
|
|
108
|
-
'data-bui-accordion-target': 'item'
|
|
109
|
-
}.merge(options)
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# Attributi per il button header
|
|
113
|
-
def header_attributes
|
|
114
|
-
base_classes = [
|
|
115
|
-
'bui-accordion-header',
|
|
116
|
-
'w-full flex items-center justify-between text-left font-medium transition-colors duration-200',
|
|
117
|
-
ITEM_SIZE_HEADER[size],
|
|
118
|
-
ITEM_HEADER_THEME[theme],
|
|
119
|
-
disabled? ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'
|
|
120
|
-
].compact.join(' ')
|
|
121
|
-
|
|
122
|
-
{
|
|
123
|
-
class: base_classes,
|
|
124
|
-
type: 'button',
|
|
125
|
-
id: header_id,
|
|
126
|
-
'aria-expanded': expanded,
|
|
127
|
-
'aria-controls': content_id,
|
|
128
|
-
'data-action': 'click->bui-accordion#toggle',
|
|
129
|
-
'data-bui-accordion-target': 'trigger',
|
|
130
|
-
disabled: disabled
|
|
131
|
-
}
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
# Attributi per il contenuto
|
|
135
|
-
def content_attributes
|
|
136
|
-
base_classes = [
|
|
137
|
-
'bui-accordion-content',
|
|
138
|
-
'transition-all duration-300 ease-in-out overflow-hidden',
|
|
139
|
-
ITEM_SIZE_CONTENT[size],
|
|
140
|
-
expanded? ? 'block' : 'hidden'
|
|
141
|
-
].compact.join(' ')
|
|
142
|
-
|
|
143
|
-
{
|
|
144
|
-
class: base_classes,
|
|
145
|
-
id: content_id,
|
|
146
|
-
'aria-labelledby': header_id,
|
|
147
|
-
'data-bui-accordion-target': 'content'
|
|
148
|
-
}
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
# Attributi per l'icona
|
|
152
|
-
def icon_attributes
|
|
153
|
-
base_classes = [
|
|
154
|
-
'bui-accordion-icon',
|
|
155
|
-
'transition-transform duration-200',
|
|
156
|
-
ITEM_SIZE_ICON[size],
|
|
157
|
-
expanded? ? 'rotate-180' : ''
|
|
158
|
-
].compact.join(' ')
|
|
159
|
-
|
|
160
|
-
{
|
|
161
|
-
class: base_classes,
|
|
162
|
-
'data-bui-accordion-target': 'icon'
|
|
163
|
-
}
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
def disabled?
|
|
167
|
-
disabled
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
def expanded?
|
|
171
|
-
expanded
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
end
|
|
@@ -1,32 +0,0 @@
|
|
|
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>
|
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
module BetterUi
|
|
2
|
-
module General
|
|
3
|
-
module Alert
|
|
4
|
-
class Component < ViewComponent::Base
|
|
5
|
-
# Classi base sempre presenti
|
|
6
|
-
ALERT_BASE_CLASSES = "flex p-4 mb-4 border"
|
|
7
|
-
|
|
8
|
-
# Classi per elementi interni
|
|
9
|
-
ALERT_ICON_CLASSES = "flex-shrink-0 mr-3 w-5 h-5"
|
|
10
|
-
ALERT_ICON_RIGHT_CLASSES = "flex-shrink-0 ml-3 mr-0"
|
|
11
|
-
ALERT_CONTENT_CLASSES = "flex-1"
|
|
12
|
-
ALERT_TITLE_CLASSES = "font-medium mb-1"
|
|
13
|
-
ALERT_MESSAGE_CLASSES = "text-sm"
|
|
14
|
-
ALERT_CLOSE_CLASSES = "ml-auto -my-1.5 -mr-1.5 p-1.5 rounded-md focus:ring-2 focus:ring-offset-2 hover:bg-gray-100"
|
|
15
|
-
|
|
16
|
-
# Temi di alert con classi Tailwind dirette
|
|
17
|
-
ALERT_THEME_CLASSES = {
|
|
18
|
-
default: "bg-black text-white border-gray-900",
|
|
19
|
-
white: "bg-white text-black border-gray-200",
|
|
20
|
-
red: "bg-red-500 text-white border-red-600",
|
|
21
|
-
rose: "bg-rose-500 text-white border-rose-600",
|
|
22
|
-
orange: "bg-orange-500 text-white border-orange-600",
|
|
23
|
-
green: "bg-green-500 text-white border-green-600",
|
|
24
|
-
blue: "bg-blue-500 text-white border-blue-600",
|
|
25
|
-
yellow: "bg-yellow-500 text-black border-yellow-600",
|
|
26
|
-
violet: "bg-violet-500 text-white border-violet-600"
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
# Colori icone per ogni tema
|
|
30
|
-
ALERT_ICON_THEME_CLASSES = {
|
|
31
|
-
default: "text-white",
|
|
32
|
-
white: "text-black",
|
|
33
|
-
red: "text-white",
|
|
34
|
-
rose: "text-white",
|
|
35
|
-
orange: "text-white",
|
|
36
|
-
green: "text-white",
|
|
37
|
-
blue: "text-white",
|
|
38
|
-
yellow: "text-black",
|
|
39
|
-
violet: "text-white"
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
# Colori close button per ogni tema
|
|
43
|
-
ALERT_CLOSE_THEME_CLASSES = {
|
|
44
|
-
default: "text-white focus:ring-gray-600",
|
|
45
|
-
white: "text-black focus:ring-gray-400",
|
|
46
|
-
red: "text-white focus:ring-red-400",
|
|
47
|
-
rose: "text-white focus:ring-rose-400",
|
|
48
|
-
orange: "text-white focus:ring-orange-400",
|
|
49
|
-
green: "text-white focus:ring-green-400",
|
|
50
|
-
blue: "text-white focus:ring-blue-400",
|
|
51
|
-
yellow: "text-black focus:ring-yellow-400",
|
|
52
|
-
violet: "text-white focus:ring-violet-400"
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
# Border radius con classi Tailwind dirette
|
|
56
|
-
ALERT_RADIUS_CLASSES = {
|
|
57
|
-
none: "rounded-none",
|
|
58
|
-
small: "rounded-sm",
|
|
59
|
-
medium: "rounded-md",
|
|
60
|
-
large: "rounded-lg",
|
|
61
|
-
full: "rounded-full"
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
# Classi per layout quando icon è a destra
|
|
65
|
-
ALERT_ICON_RIGHT_LAYOUT_CLASSES = "flex-row-reverse"
|
|
66
|
-
ALERT_CONTENT_RIGHT_CLASSES = "text-right"
|
|
67
|
-
|
|
68
|
-
# Classi per alert dismissible
|
|
69
|
-
ALERT_DISMISSIBLE_CLASSES = "pr-12 relative"
|
|
70
|
-
ALERT_CLOSE_POSITION_CLASSES = "absolute right-4 top-4"
|
|
71
|
-
|
|
72
|
-
# Livelli di importanza con attributi ARIA
|
|
73
|
-
IMPORTANCE_LEVELS = {
|
|
74
|
-
high: { role: "alert", "aria-live": "assertive" },
|
|
75
|
-
medium: { role: "status", "aria-live": "polite" },
|
|
76
|
-
low: { role: "status", "aria-live": "polite" }
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
# @param title [String] titolo dell'alert (opzionale)
|
|
80
|
-
# @param message [String] contenuto dell'alert
|
|
81
|
-
# @param theme [Symbol] :default, :white, :red, :rose, :orange, :green, :blue, :yellow, :violet
|
|
82
|
-
# @param icon [String] nome dell'icona (opzionale)
|
|
83
|
-
# @param icon_position [Symbol] :left, :right posizione dell'icona
|
|
84
|
-
# @param dismissible [Boolean] se l'alert può essere chiuso
|
|
85
|
-
# @param rounded [Symbol] :none, :small, :medium, :large, :full arrotondamento degli angoli
|
|
86
|
-
# @param importance [Symbol] :high, :medium, :low livello di importanza per accessibilità
|
|
87
|
-
# @param html_content [Boolean] se il messaggio contiene HTML
|
|
88
|
-
# @param classes [String] classi CSS aggiuntive
|
|
89
|
-
# @param html_options [Hash] opzioni HTML per il container
|
|
90
|
-
def initialize(
|
|
91
|
-
title: nil,
|
|
92
|
-
message: nil,
|
|
93
|
-
theme: :white,
|
|
94
|
-
icon: nil,
|
|
95
|
-
icon_position: :left,
|
|
96
|
-
dismissible: false,
|
|
97
|
-
rounded: :medium,
|
|
98
|
-
importance: :medium,
|
|
99
|
-
html_content: false,
|
|
100
|
-
classes: nil,
|
|
101
|
-
**html_options
|
|
102
|
-
)
|
|
103
|
-
@title = title
|
|
104
|
-
@message = message
|
|
105
|
-
@theme = theme.to_sym
|
|
106
|
-
@icon = icon
|
|
107
|
-
@icon_position = icon_position.to_sym
|
|
108
|
-
@dismissible = dismissible
|
|
109
|
-
@rounded = rounded.to_sym
|
|
110
|
-
@importance = importance.to_sym
|
|
111
|
-
@html_content = html_content
|
|
112
|
-
@classes = classes
|
|
113
|
-
@html_options = html_options
|
|
114
|
-
|
|
115
|
-
validate_params
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def default_icon
|
|
119
|
-
case @theme
|
|
120
|
-
when :default then "bell"
|
|
121
|
-
when :white then "information-circle"
|
|
122
|
-
when :red, :rose then "exclamation-circle"
|
|
123
|
-
when :orange then "bell"
|
|
124
|
-
when :green then "check-circle"
|
|
125
|
-
when :blue then "information-circle"
|
|
126
|
-
when :yellow then "exclamation-triangle"
|
|
127
|
-
when :violet then "shield-exclamation"
|
|
128
|
-
else "information-circle"
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
# Combina tutte le classi
|
|
133
|
-
def combined_classes
|
|
134
|
-
[
|
|
135
|
-
ALERT_BASE_CLASSES,
|
|
136
|
-
get_theme_class,
|
|
137
|
-
get_border_radius_class,
|
|
138
|
-
get_icon_position_class,
|
|
139
|
-
@dismissible ? ALERT_DISMISSIBLE_CLASSES : nil,
|
|
140
|
-
@classes,
|
|
141
|
-
@html_options[:class]
|
|
142
|
-
].compact.join(" ")
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
# Restituisce gli attributi per l'alert
|
|
146
|
-
def alert_attributes
|
|
147
|
-
attrs = {
|
|
148
|
-
class: combined_classes
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
# Aggiungi attributi ARIA in base al livello di importanza
|
|
152
|
-
importance_attrs = IMPORTANCE_LEVELS[@importance] || IMPORTANCE_LEVELS[:medium]
|
|
153
|
-
importance_attrs.each do |key, value|
|
|
154
|
-
attrs[key] = value
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
# Aggiungi altri attributi HTML se presenti
|
|
158
|
-
@html_options.except(:class).each do |key, value|
|
|
159
|
-
attrs[key] = value
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
attrs
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
# Genera le classi del tema
|
|
166
|
-
def get_theme_class
|
|
167
|
-
ALERT_THEME_CLASSES[@theme] || ALERT_THEME_CLASSES[:white]
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# Genera le classi per il border radius
|
|
171
|
-
def get_border_radius_class
|
|
172
|
-
ALERT_RADIUS_CLASSES[@rounded] || ALERT_RADIUS_CLASSES[:medium]
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
# Genera la classe per la posizione dell'icona (layout)
|
|
176
|
-
def get_icon_position_class
|
|
177
|
-
@icon_position == :right ? ALERT_ICON_RIGHT_LAYOUT_CLASSES : nil
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
# Genera le classi per l'icona
|
|
181
|
-
def get_icon_classes
|
|
182
|
-
if @icon_position == :right
|
|
183
|
-
ALERT_ICON_RIGHT_CLASSES
|
|
184
|
-
else
|
|
185
|
-
ALERT_ICON_CLASSES
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
# Genera le classi per il contenuto
|
|
190
|
-
def get_content_classes
|
|
191
|
-
if @icon_position == :right
|
|
192
|
-
[ ALERT_CONTENT_CLASSES, ALERT_CONTENT_RIGHT_CLASSES ].join(" ")
|
|
193
|
-
else
|
|
194
|
-
ALERT_CONTENT_CLASSES
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
# Genera le classi per l'icona del tema
|
|
199
|
-
def get_icon_theme_class
|
|
200
|
-
ALERT_ICON_THEME_CLASSES[@theme] || ALERT_ICON_THEME_CLASSES[:white]
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
# Genera le classi per il close button
|
|
204
|
-
def get_close_classes
|
|
205
|
-
base_classes = ALERT_CLOSE_CLASSES
|
|
206
|
-
theme_classes = ALERT_CLOSE_THEME_CLASSES[@theme] || ALERT_CLOSE_THEME_CLASSES[:white]
|
|
207
|
-
position_classes = @dismissible ? ALERT_CLOSE_POSITION_CLASSES : nil
|
|
208
|
-
|
|
209
|
-
[ base_classes, theme_classes, position_classes ].compact.join(" ")
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
private
|
|
213
|
-
|
|
214
|
-
def validate_params
|
|
215
|
-
# Validazione tema
|
|
216
|
-
valid_themes = ALERT_THEME_CLASSES.keys
|
|
217
|
-
unless valid_themes.include?(@theme)
|
|
218
|
-
raise ArgumentError, "Il tema deve essere uno tra: #{valid_themes.join(', ')}"
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
# Validazione border radius
|
|
222
|
-
valid_radius = ALERT_RADIUS_CLASSES.keys
|
|
223
|
-
unless valid_radius.include?(@rounded)
|
|
224
|
-
raise ArgumentError, "Il border radius deve essere uno tra: #{valid_radius.join(', ')}"
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
# Validazione posizione icona
|
|
228
|
-
valid_positions = [ :left, :right ]
|
|
229
|
-
unless valid_positions.include?(@icon_position)
|
|
230
|
-
raise ArgumentError, "La posizione dell'icona deve essere una tra: #{valid_positions.join(', ')}"
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
# Validazione livello di importanza
|
|
234
|
-
valid_importance = IMPORTANCE_LEVELS.keys
|
|
235
|
-
unless valid_importance.include?(@importance)
|
|
236
|
-
raise ArgumentError, "Il livello di importanza deve essere uno tra: #{valid_importance.join(', ')}"
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
end
|
|
241
|
-
end
|
|
242
|
-
end
|