better_ui 0.4.0 → 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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +141 -189
  3. data/app/assets/stylesheets/better_ui/_base.scss +9 -0
  4. data/app/assets/stylesheets/better_ui/_components.scss +2 -0
  5. data/app/assets/stylesheets/better_ui/_utilities.scss +14 -0
  6. data/app/assets/stylesheets/better_ui/application.css +3 -1
  7. data/app/assets/stylesheets/better_ui/components/_avatar.scss +200 -0
  8. data/app/assets/stylesheets/better_ui/components/_badge.scss +154 -0
  9. data/app/assets/stylesheets/better_ui/components/_breadcrumb.scss +106 -0
  10. data/app/assets/stylesheets/better_ui/components/_button.scss +105 -0
  11. data/app/assets/stylesheets/better_ui/components/_card.scss +60 -0
  12. data/app/assets/stylesheets/better_ui/components/_heading.scss +81 -0
  13. data/app/assets/stylesheets/better_ui/components/_icon.scss +134 -0
  14. data/app/assets/stylesheets/better_ui/components/_index.scss +17 -0
  15. data/app/assets/stylesheets/better_ui/components/_link.scss +100 -0
  16. data/app/assets/stylesheets/better_ui/components/_panel.scss +104 -0
  17. data/app/assets/stylesheets/better_ui/components/_spinner.scss +129 -0
  18. data/app/assets/stylesheets/better_ui/components/_table.scss +156 -0
  19. data/app/assets/stylesheets/better_ui/components/_variables.scss +1 -0
  20. data/app/assets/stylesheets/better_ui.scss +4 -0
  21. data/app/components/better_ui/application/alert_component.html.erb +1 -1
  22. data/app/components/better_ui/application/alert_component.rb +95 -89
  23. data/app/components/better_ui/application/card_component.html.erb +24 -0
  24. data/app/components/better_ui/application/card_component.rb +53 -0
  25. data/app/components/better_ui/application/card_container_component.html.erb +8 -0
  26. data/app/components/better_ui/application/card_container_component.rb +14 -0
  27. data/app/components/better_ui/application/toast_component.rb +92 -57
  28. data/app/components/better_ui/general/avatar_component.html.erb +19 -0
  29. data/app/components/better_ui/general/avatar_component.rb +171 -0
  30. data/app/components/better_ui/general/badge_component.html.erb +19 -0
  31. data/app/components/better_ui/general/badge_component.rb +135 -0
  32. data/app/components/better_ui/general/breadcrumb_component.html.erb +7 -31
  33. data/app/components/better_ui/general/breadcrumb_component.rb +64 -66
  34. data/app/components/better_ui/general/button_component.html.erb +6 -6
  35. data/app/components/better_ui/general/button_component.rb +62 -95
  36. data/app/components/better_ui/general/heading_component.html.erb +1 -25
  37. data/app/components/better_ui/general/heading_component.rb +20 -113
  38. data/app/components/better_ui/general/icon_component.rb +37 -61
  39. data/app/components/better_ui/general/link_component.html.erb +17 -0
  40. data/app/components/better_ui/general/link_component.rb +132 -0
  41. data/app/components/better_ui/general/panel_component.rb +51 -56
  42. data/app/components/better_ui/general/spinner_component.html.erb +15 -0
  43. data/app/components/better_ui/general/spinner_component.rb +79 -0
  44. data/app/components/better_ui/general/table_component.html.erb +56 -20
  45. data/app/components/better_ui/general/table_component.rb +89 -87
  46. data/app/helpers/better_ui/general/components/avatar_helper.rb +17 -0
  47. data/app/helpers/better_ui/general/components/badge_helper.rb +17 -0
  48. data/app/helpers/better_ui/general/components/breadcrumb_helper.rb +17 -0
  49. data/app/helpers/better_ui/general/components/button_helper.rb +17 -0
  50. data/app/helpers/better_ui/general/components/heading_helper.rb +17 -0
  51. data/app/helpers/better_ui/general/components/icon_helper.rb +17 -0
  52. data/app/helpers/better_ui/general/components/link_helper.rb +17 -0
  53. data/app/helpers/better_ui/general/components/panel_helper.rb +16 -0
  54. data/app/helpers/better_ui/general/components/spinner_helper.rb +17 -0
  55. data/app/helpers/better_ui/general/components/table_helper.rb +17 -0
  56. data/app/helpers/better_ui/general_helper.rb +15 -0
  57. data/app/helpers/better_ui_helper.rb +12 -0
  58. data/app/views/components/better_ui/general/table/_custom_body_row.html.erb +17 -0
  59. data/app/views/components/better_ui/general/table/_custom_footer_rows.html.erb +17 -0
  60. data/app/views/components/better_ui/general/table/_custom_header_rows.html.erb +12 -0
  61. data/config/routes.rb +2 -13
  62. data/lib/better_ui/engine.rb +66 -16
  63. data/lib/better_ui/version.rb +1 -1
  64. data/lib/better_ui.rb +12 -0
  65. data/lib/generators/better_ui/install_generator.rb +103 -0
  66. data/lib/generators/better_ui/stylesheet_generator.rb +159 -0
  67. data/lib/generators/better_ui/templates/README +125 -0
  68. data/lib/generators/better_ui/templates/components/_avatar.scss +200 -0
  69. data/lib/generators/better_ui/templates/components/_badge.scss +154 -0
  70. data/lib/generators/better_ui/templates/components/_breadcrumb.scss +106 -0
  71. data/lib/generators/better_ui/templates/components/_button.scss +109 -0
  72. data/lib/generators/better_ui/templates/components/_card.scss +60 -0
  73. data/lib/generators/better_ui/templates/components/_heading.scss +81 -0
  74. data/lib/generators/better_ui/templates/components/_icon.scss +134 -0
  75. data/lib/generators/better_ui/templates/components/_index.scss +17 -0
  76. data/lib/generators/better_ui/templates/components/_link.scss +100 -0
  77. data/lib/generators/better_ui/templates/components/_panel.scss +104 -0
  78. data/lib/generators/better_ui/templates/components/_spinner.scss +129 -0
  79. data/lib/generators/better_ui/templates/components/_table.scss +156 -0
  80. data/lib/generators/better_ui/templates/components/_variables.scss +0 -0
  81. data/lib/generators/better_ui/templates/components_stylesheet.scss +35 -0
  82. data/lib/generators/better_ui/templates/index.scss +18 -0
  83. data/lib/generators/better_ui/templates/initializer.rb +41 -0
  84. metadata +120 -49
  85. data/app/assets/javascripts/better_ui/controllers/navbar_controller.js +0 -138
  86. data/app/assets/javascripts/better_ui/controllers/sidebar_controller.js +0 -211
  87. data/app/assets/javascripts/better_ui/controllers/toast_controller.js +0 -161
  88. data/app/assets/javascripts/better_ui/index.js +0 -159
  89. data/app/assets/javascripts/better_ui/toast_manager.js +0 -77
  90. data/app/components/better_ui/theme_helper.rb +0 -169
  91. data/app/controllers/better_ui/docs_controller.rb +0 -34
  92. data/app/helpers/better_ui_application_helper.rb +0 -99
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - alessiobussolari
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-02 00:00:00.000000000 Z
11
+ date: 2025-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -28,44 +28,44 @@ dependencies:
28
28
  name: view_component
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 3.0.0
33
+ version: '3.22'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 3.0.0
40
+ version: '3.22'
41
41
  - !ruby/object:Gem::Dependency
42
- name: redcarpet
42
+ name: tailwindcss-rails
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.6'
47
+ version: '4.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.6'
54
+ version: '4.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: tailwindcss-rails
56
+ name: redcarpet
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '2.0'
61
+ version: '3.6'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '2.0'
68
+ version: '3.6'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: coderay
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -86,86 +86,101 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 6.5.1
89
+ version: '6.5'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 6.5.1
96
+ version: '6.5'
97
97
  - !ruby/object:Gem::Dependency
98
- name: sqlite3
98
+ name: lookbook
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0'
103
+ version: '2.3'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '2.3'
111
111
  - !ruby/object:Gem::Dependency
112
- name: puma
112
+ name: listen
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '3.9'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: '3.9'
125
125
  - !ruby/object:Gem::Dependency
126
- name: lookbook
126
+ name: sqlite3
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '2.1'
131
+ version: '1.6'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '2.1'
138
+ version: '1.6'
139
139
  - !ruby/object:Gem::Dependency
140
- name: listen
140
+ name: puma
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - ">="
143
+ - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '0'
145
+ version: '6.4'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - ">="
150
+ - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '0'
152
+ version: '6.4'
153
153
  - !ruby/object:Gem::Dependency
154
- name: actioncable
154
+ name: rspec-rails
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - ">="
157
+ - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: '0'
159
+ version: '6.1'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - ">="
164
+ - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: '0'
167
- description: Una gem Rails che funziona come engine montabile contenente componenti
168
- UI riutilizzabili e pagine di documentazione
166
+ version: '6.1'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rubocop
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '1.59'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '1.59'
181
+ description: Better UI is a Rails gem that works as a mountable engine containing
182
+ reusable UI components, built with ViewComponent and Tailwind CSS, following the
183
+ BEM methodology. It includes documentation and interactive previews with Lookbook.
169
184
  email:
170
185
  - alessio.bussolari@pandev.it
171
186
  executables: []
@@ -175,14 +190,30 @@ files:
175
190
  - MIT-LICENSE
176
191
  - README.md
177
192
  - Rakefile
178
- - app/assets/javascripts/better_ui/controllers/navbar_controller.js
179
- - app/assets/javascripts/better_ui/controllers/sidebar_controller.js
180
- - app/assets/javascripts/better_ui/controllers/toast_controller.js
181
- - app/assets/javascripts/better_ui/index.js
182
- - app/assets/javascripts/better_ui/toast_manager.js
193
+ - app/assets/stylesheets/better_ui.scss
194
+ - app/assets/stylesheets/better_ui/_base.scss
195
+ - app/assets/stylesheets/better_ui/_components.scss
196
+ - app/assets/stylesheets/better_ui/_utilities.scss
183
197
  - app/assets/stylesheets/better_ui/application.css
198
+ - app/assets/stylesheets/better_ui/components/_avatar.scss
199
+ - app/assets/stylesheets/better_ui/components/_badge.scss
200
+ - app/assets/stylesheets/better_ui/components/_breadcrumb.scss
201
+ - app/assets/stylesheets/better_ui/components/_button.scss
202
+ - app/assets/stylesheets/better_ui/components/_card.scss
203
+ - app/assets/stylesheets/better_ui/components/_heading.scss
204
+ - app/assets/stylesheets/better_ui/components/_icon.scss
205
+ - app/assets/stylesheets/better_ui/components/_index.scss
206
+ - app/assets/stylesheets/better_ui/components/_link.scss
207
+ - app/assets/stylesheets/better_ui/components/_panel.scss
208
+ - app/assets/stylesheets/better_ui/components/_spinner.scss
209
+ - app/assets/stylesheets/better_ui/components/_table.scss
210
+ - app/assets/stylesheets/better_ui/components/_variables.scss
184
211
  - app/components/better_ui/application/alert_component.html.erb
185
212
  - app/components/better_ui/application/alert_component.rb
213
+ - app/components/better_ui/application/card_component.html.erb
214
+ - app/components/better_ui/application/card_component.rb
215
+ - app/components/better_ui/application/card_container_component.html.erb
216
+ - app/components/better_ui/application/card_container_component.rb
186
217
  - app/components/better_ui/application/header_component.html.erb
187
218
  - app/components/better_ui/application/header_component.rb
188
219
  - app/components/better_ui/application/navbar_component.html.erb
@@ -191,6 +222,10 @@ files:
191
222
  - app/components/better_ui/application/sidebar_component.rb
192
223
  - app/components/better_ui/application/toast_component.html.erb
193
224
  - app/components/better_ui/application/toast_component.rb
225
+ - app/components/better_ui/general/avatar_component.html.erb
226
+ - app/components/better_ui/general/avatar_component.rb
227
+ - app/components/better_ui/general/badge_component.html.erb
228
+ - app/components/better_ui/general/badge_component.rb
194
229
  - app/components/better_ui/general/breadcrumb_component.html.erb
195
230
  - app/components/better_ui/general/breadcrumb_component.rb
196
231
  - app/components/better_ui/general/button_component.html.erb
@@ -199,23 +234,58 @@ files:
199
234
  - app/components/better_ui/general/heading_component.rb
200
235
  - app/components/better_ui/general/icon_component.html.erb
201
236
  - app/components/better_ui/general/icon_component.rb
237
+ - app/components/better_ui/general/link_component.html.erb
238
+ - app/components/better_ui/general/link_component.rb
202
239
  - app/components/better_ui/general/panel_component.html.erb
203
240
  - app/components/better_ui/general/panel_component.rb
241
+ - app/components/better_ui/general/spinner_component.html.erb
242
+ - app/components/better_ui/general/spinner_component.rb
204
243
  - app/components/better_ui/general/table_component.html.erb
205
244
  - app/components/better_ui/general/table_component.rb
206
- - app/components/better_ui/theme_helper.rb
207
245
  - app/controllers/better_ui/application_controller.rb
208
- - app/controllers/better_ui/docs_controller.rb
209
- - app/helpers/better_ui_application_helper.rb
246
+ - app/helpers/better_ui/general/components/avatar_helper.rb
247
+ - app/helpers/better_ui/general/components/badge_helper.rb
248
+ - app/helpers/better_ui/general/components/breadcrumb_helper.rb
249
+ - app/helpers/better_ui/general/components/button_helper.rb
250
+ - app/helpers/better_ui/general/components/heading_helper.rb
251
+ - app/helpers/better_ui/general/components/icon_helper.rb
252
+ - app/helpers/better_ui/general/components/link_helper.rb
253
+ - app/helpers/better_ui/general/components/panel_helper.rb
254
+ - app/helpers/better_ui/general/components/spinner_helper.rb
255
+ - app/helpers/better_ui/general/components/table_helper.rb
256
+ - app/helpers/better_ui/general_helper.rb
257
+ - app/helpers/better_ui_helper.rb
210
258
  - app/jobs/better_ui/application_job.rb
211
259
  - app/mailers/better_ui/application_mailer.rb
212
260
  - app/models/better_ui/application_record.rb
261
+ - app/views/components/better_ui/general/table/_custom_body_row.html.erb
262
+ - app/views/components/better_ui/general/table/_custom_footer_rows.html.erb
263
+ - app/views/components/better_ui/general/table/_custom_header_rows.html.erb
213
264
  - app/views/layouts/component_preview.html.erb
214
265
  - config/initializers/lookbook.rb
215
266
  - config/routes.rb
216
267
  - lib/better_ui.rb
217
268
  - lib/better_ui/engine.rb
218
269
  - lib/better_ui/version.rb
270
+ - lib/generators/better_ui/install_generator.rb
271
+ - lib/generators/better_ui/stylesheet_generator.rb
272
+ - lib/generators/better_ui/templates/README
273
+ - lib/generators/better_ui/templates/components/_avatar.scss
274
+ - lib/generators/better_ui/templates/components/_badge.scss
275
+ - lib/generators/better_ui/templates/components/_breadcrumb.scss
276
+ - lib/generators/better_ui/templates/components/_button.scss
277
+ - lib/generators/better_ui/templates/components/_card.scss
278
+ - lib/generators/better_ui/templates/components/_heading.scss
279
+ - lib/generators/better_ui/templates/components/_icon.scss
280
+ - lib/generators/better_ui/templates/components/_index.scss
281
+ - lib/generators/better_ui/templates/components/_link.scss
282
+ - lib/generators/better_ui/templates/components/_panel.scss
283
+ - lib/generators/better_ui/templates/components/_spinner.scss
284
+ - lib/generators/better_ui/templates/components/_table.scss
285
+ - lib/generators/better_ui/templates/components/_variables.scss
286
+ - lib/generators/better_ui/templates/components_stylesheet.scss
287
+ - lib/generators/better_ui/templates/index.scss
288
+ - lib/generators/better_ui/templates/initializer.rb
219
289
  - lib/tasks/better_ui_tasks.rake
220
290
  homepage: https://github.com/alessiobussolari/better_ui
221
291
  licenses:
@@ -225,6 +295,7 @@ metadata:
225
295
  homepage_uri: https://github.com/alessiobussolari/better_ui
226
296
  source_code_uri: https://github.com/alessiobussolari/better_ui
227
297
  changelog_uri: https://github.com/alessiobussolari/better_ui/blob/main/CHANGELOG.md
298
+ rubygems_mfa_required: 'true'
228
299
  post_install_message:
229
300
  rdoc_options: []
230
301
  require_paths:
@@ -233,7 +304,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
233
304
  requirements:
234
305
  - - ">="
235
306
  - !ruby/object:Gem::Version
236
- version: '0'
307
+ version: '3.0'
237
308
  required_rubygems_version: !ruby/object:Gem::Requirement
238
309
  requirements:
239
310
  - - ">="
@@ -243,5 +314,5 @@ requirements: []
243
314
  rubygems_version: 3.5.11
244
315
  signing_key:
245
316
  specification_version: 4
246
- summary: Componenti UI riutilizzabili per Rails con documentazione integrata
317
+ summary: Elegant and reusable UI components for Rails with integrated documentation
247
318
  test_files: []
@@ -1,138 +0,0 @@
1
- // Navbar controller per gestire il comportamento del menu mobile e dei dropdown
2
- import { Controller } from "@hotwired/stimulus"
3
-
4
- export default class extends Controller {
5
- static targets = ["menu", "dropdown", "submenu"]
6
-
7
- connect() {
8
- // Verifica se siamo su mobile e aggiorna lo stato del menu
9
- this.updateMenuState();
10
-
11
- // Aggiungi un event listener per il resize della finestra
12
- window.addEventListener("resize", this.updateMenuState.bind(this));
13
-
14
- // Chiudi menu quando si clicca su un link (solo su mobile)
15
- if (this.hasMenuTarget) {
16
- const links = this.menuTarget.querySelectorAll("a");
17
- links.forEach(link => {
18
- link.addEventListener("click", () => {
19
- // Se siamo su mobile, chiudi il menu
20
- if (window.innerWidth < 768) {
21
- this.closeMenu();
22
- }
23
- });
24
- });
25
- }
26
-
27
- // Aggiungi listener per i click all'esterno del menu
28
- document.addEventListener("click", this.handleClickOutside.bind(this))
29
- }
30
-
31
- disconnect() {
32
- // Rimuovi event listener per il resize della finestra
33
- window.removeEventListener("resize", this.updateMenuState.bind(this));
34
-
35
- // Rimuovi listener al disconnette
36
- document.removeEventListener("click", this.handleClickOutside.bind(this))
37
- }
38
-
39
- // Metodo per alternare l'apertura/chiusura del menu
40
- toggleMenu(event) {
41
- event.stopPropagation()
42
- const isExpanded = this.menuTarget.classList.contains("hidden") === false
43
-
44
- if (isExpanded) {
45
- this.closeMenu()
46
- } else {
47
- this.openMenu()
48
- }
49
- }
50
-
51
- // Metodo per chiudere il menu
52
- closeMenu() {
53
- this.menuTarget.classList.add("hidden")
54
-
55
- // Aggiorna l'attributo aria-expanded
56
- const button = this.element.querySelector("[aria-controls='navbar-menu']")
57
- if (button) {
58
- button.setAttribute("aria-expanded", "false")
59
- }
60
- }
61
-
62
- // Metodo per aggiornare lo stato del menu in base alla dimensione della finestra
63
- updateMenuState() {
64
- if (this.hasMenuTarget) {
65
- // Se siamo su desktop (md breakpoint - 768px)
66
- if (window.innerWidth >= 768) {
67
- // Assicurati che il menu sia visibile su desktop
68
- this.menuTarget.classList.remove("hidden");
69
- this.menuTarget.classList.add("md:block");
70
- } else {
71
- // Su mobile, nascondi il menu di default
72
- this.menuTarget.classList.add("hidden");
73
- }
74
-
75
- // Aggiorna l'attributo aria-expanded
76
- const button = this.element.querySelector("[aria-controls='navbar-menu']");
77
- if (button) {
78
- const isExpanded = window.innerWidth >= 768 ? "true" : "false";
79
- button.setAttribute("aria-expanded", isExpanded);
80
- }
81
- }
82
- }
83
-
84
- openMenu() {
85
- this.menuTarget.classList.remove("hidden")
86
-
87
- // Chiudi tutti i dropdown nel menu mobile
88
- if (this.hasSubmenuTarget) {
89
- this.submenuTargets.forEach(submenu => {
90
- submenu.classList.add("hidden")
91
- })
92
- }
93
-
94
- // Aggiorna stato del pulsante
95
- event.currentTarget.setAttribute("aria-expanded", "true")
96
- }
97
-
98
- toggleDropdown(event) {
99
- event.stopPropagation()
100
- const button = event.currentTarget
101
- const dropdownId = button.getAttribute("aria-controls")
102
- const dropdown = document.getElementById(dropdownId)
103
-
104
- if (dropdown) {
105
- const isExpanded = button.getAttribute("aria-expanded") === "true"
106
-
107
- if (isExpanded) {
108
- dropdown.classList.add("hidden")
109
- button.setAttribute("aria-expanded", "false")
110
- } else {
111
- // Chiudi tutti gli altri dropdown prima di aprire quello corrente
112
- if (this.hasSubmenuTarget) {
113
- this.submenuTargets.forEach(submenu => {
114
- if (submenu.id !== dropdownId) {
115
- submenu.classList.add("hidden")
116
-
117
- // Trova e aggiorna il pulsante associato
118
- const associatedButton = this.element.querySelector(`[aria-controls='${submenu.id}']`)
119
- if (associatedButton) {
120
- associatedButton.setAttribute("aria-expanded", "false")
121
- }
122
- }
123
- })
124
- }
125
-
126
- dropdown.classList.remove("hidden")
127
- button.setAttribute("aria-expanded", "true")
128
- }
129
- }
130
- }
131
-
132
- handleClickOutside(event) {
133
- // Chiudi il menu se si fa clic all'esterno
134
- if (this.element.contains(event.target) === false) {
135
- this.closeMenu()
136
- }
137
- }
138
- }
@@ -1,211 +0,0 @@
1
- // Sidebar controller per gestire il comportamento del menu laterale
2
- import { Controller } from "@hotwired/stimulus"
3
-
4
- export default class extends Controller {
5
- static targets = ["container", "overlay", "toggleButton", "toggleIcon", "dropdown", "submenu", "chevron"]
6
- static values = {
7
- collapsed: { type: Boolean, default: false },
8
- position: { type: String, default: "left" },
9
- overlayOnMobile: { type: Boolean, default: true }
10
- }
11
-
12
- connect() {
13
- // Applica lo stato iniziale
14
- if (this.collapsedValue) {
15
- this.collapse();
16
- } else {
17
- // Assicuriamo che la sidebar sia espansa all'inizio
18
- this.containerTarget.style.transform = "translateX(0)";
19
- }
20
-
21
- // Imposta i listener per il ridimensionamento della finestra
22
- window.addEventListener("resize", this.handleResize.bind(this));
23
-
24
- // Gestisci lo stato iniziale in base alla dimensione della finestra
25
- this.handleResize();
26
-
27
- // Trova e apri i sottomenu con elementi attivi
28
- this.openSubmenuWithActiveItems();
29
- }
30
-
31
- disconnect() {
32
- // Rimuovi i listener all'uscita
33
- window.removeEventListener("resize", this.handleResize.bind(this));
34
- }
35
-
36
- // Toggle dell'intera sidebar
37
- toggle() {
38
- if (this.isCollapsed()) {
39
- this.expand();
40
- } else {
41
- this.collapse();
42
- }
43
- }
44
-
45
- // Espandi la sidebar
46
- expand() {
47
- // Mostra la sidebar completa
48
- this.containerTarget.classList.remove("transform-translate");
49
- this.containerTarget.style.transform = "translateX(0)";
50
-
51
- // Ruota l'icona del toggle button
52
- if (this.hasToggleIconTarget) {
53
- if (this.positionValue === "left") {
54
- this.toggleIconTarget.style.transform = "rotate(0deg)";
55
- } else {
56
- this.toggleIconTarget.style.transform = "rotate(0deg)";
57
- }
58
- }
59
-
60
- // Aggiorna lo stato
61
- this.collapsedValue = false;
62
- }
63
-
64
- // Contrai la sidebar
65
- collapse() {
66
- const width = this.containerTarget.offsetWidth;
67
- // Usa un valore più piccolo per mantenere visibile una parte della sidebar
68
- const translateValue = this.positionValue === "left" ? `-${width - 10}px` : `${width - 10}px`;
69
-
70
- // Nascondi la sidebar
71
- this.containerTarget.classList.add("transform-translate");
72
- this.containerTarget.style.transform = `translateX(${translateValue})`;
73
-
74
- // Ruota l'icona del toggle button
75
- if (this.hasToggleIconTarget) {
76
- if (this.positionValue === "left") {
77
- this.toggleIconTarget.style.transform = "rotate(180deg)";
78
- } else {
79
- this.toggleIconTarget.style.transform = "rotate(180deg)";
80
- }
81
- }
82
-
83
- // Aggiorna lo stato
84
- this.collapsedValue = true;
85
- }
86
-
87
- // Apri la sidebar
88
- open() {
89
- // Mostra la sidebar
90
- this.containerTarget.style.transform = "translateX(0)";
91
-
92
- // Mostra l'overlay se necessario
93
- if (this.overlayOnMobileValue && window.innerWidth < 768) {
94
- this.overlayTarget.classList.remove("hidden");
95
- this.overlayTarget.classList.add("opacity-100");
96
- document.body.classList.add("overflow-hidden");
97
- }
98
-
99
- // Aggiorna lo stato
100
- this.collapsedValue = false;
101
- }
102
-
103
- // Chiudi la sidebar
104
- close() {
105
- // Se è già contratta su desktop, non fare nulla
106
- if (this.collapsedValue && window.innerWidth >= 768) {
107
- return;
108
- }
109
-
110
- // Su mobile, nascondi completamente
111
- if (window.innerWidth < 768) {
112
- const width = this.containerTarget.offsetWidth;
113
- const translateValue = this.positionValue === "left" ? `-${width}px` : `${width}px`;
114
- this.containerTarget.style.transform = `translateX(${translateValue})`;
115
-
116
- // Nascondi l'overlay
117
- this.overlayTarget.classList.add("hidden");
118
- this.overlayTarget.classList.remove("opacity-100");
119
- document.body.classList.remove("overflow-hidden");
120
- } else {
121
- // Su desktop, contrai
122
- this.collapse();
123
- }
124
- }
125
-
126
- // Verifica se la sidebar è contratta
127
- isCollapsed() {
128
- return this.collapsedValue;
129
- }
130
-
131
- // Handler per il ridimensionamento della finestra
132
- handleResize() {
133
- // Su mobile, mostra l'overlay se la sidebar è aperta
134
- if (window.innerWidth < 768) {
135
- const isHidden = this.containerTarget.style.transform.includes("translateX");
136
-
137
- if (!isHidden && this.overlayOnMobileValue) {
138
- this.overlayTarget.classList.remove("hidden");
139
- } else {
140
- this.overlayTarget.classList.add("hidden");
141
- }
142
- } else {
143
- // Su desktop, nascondi l'overlay
144
- this.overlayTarget.classList.add("hidden");
145
- document.body.classList.remove("overflow-hidden");
146
-
147
- // Ripristina lo stato della sidebar in base al valore di collapsed
148
- if (this.collapsedValue) {
149
- this.collapse();
150
- } else {
151
- this.expand();
152
- }
153
- }
154
- }
155
-
156
- // Toggle di un sottomenu
157
- toggleSubmenu(event) {
158
- const button = event.currentTarget;
159
- const submenuId = button.getAttribute("aria-controls");
160
- const submenu = document.getElementById(submenuId);
161
- const chevron = button.querySelector("[data-sidebar-target='chevron']");
162
-
163
- if (submenu) {
164
- const isExpanded = button.getAttribute("aria-expanded") === "true";
165
-
166
- if (isExpanded) {
167
- // Chiudi il sottomenu
168
- submenu.classList.add("hidden");
169
- button.setAttribute("aria-expanded", "false");
170
- if (chevron) {
171
- chevron.querySelector("svg").style.transform = "rotate(0deg)";
172
- }
173
- } else {
174
- // Apri il sottomenu
175
- submenu.classList.remove("hidden");
176
- button.setAttribute("aria-expanded", "true");
177
- if (chevron) {
178
- chevron.querySelector("svg").style.transform = "rotate(180deg)";
179
- }
180
- }
181
- }
182
- }
183
-
184
- // Apri automaticamente i sottomenu che contengono elementi attivi
185
- openSubmenuWithActiveItems() {
186
- // Trova tutti i dropdown
187
- if (this.hasDropdownTarget) {
188
- this.dropdownTargets.forEach(dropdown => {
189
- const submenuId = dropdown.getAttribute("aria-controls");
190
- const submenu = document.getElementById(submenuId);
191
-
192
- if (submenu) {
193
- // Verifica se il sottomenu contiene elementi attivi
194
- const activeItems = submenu.querySelectorAll(".bg-gray-100, .bg-gray-700, .bg-orange-700, .bg-blue-700");
195
-
196
- if (activeItems.length > 0) {
197
- // Apri il sottomenu
198
- submenu.classList.remove("hidden");
199
- dropdown.setAttribute("aria-expanded", "true");
200
-
201
- // Ruota l'icona chevron se presente
202
- const chevron = dropdown.querySelector("[data-sidebar-target='chevron']");
203
- if (chevron) {
204
- chevron.querySelector("svg").style.transform = "rotate(180deg)";
205
- }
206
- }
207
- }
208
- });
209
- }
210
- }
211
- }