better_ui 0.1.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.
- checksums.yaml +4 -4
- data/README.md +65 -1
- 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 +25 -351
- 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 +34 -0
- 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 +18 -25
- 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 +23 -0
- data/config/routes.rb +6 -1
- data/lib/better_ui/engine.rb +24 -1
- data/lib/better_ui/version.rb +1 -1
- metadata +103 -7
- data/app/helpers/better_ui/application_helper.rb +0 -183
- data/app/views/better_ui/docs/component.html.erb +0 -365
- data/app/views/better_ui/docs/index.html.erb +0 -100
- data/app/views/better_ui/docs/show.html.erb +0 -60
- data/app/views/layouts/better_ui/application.html.erb +0 -135
@@ -0,0 +1,159 @@
|
|
1
|
+
// Entry point per tutti i componenti JavaScript di Better UI
|
2
|
+
import { Application } from "@hotwired/stimulus"
|
3
|
+
import ToastController from "./controllers/toast_controller"
|
4
|
+
import NavbarController from "./controllers/navbar_controller"
|
5
|
+
import SidebarController from "./controllers/sidebar_controller"
|
6
|
+
|
7
|
+
// Configura Stimulus
|
8
|
+
const application = Application.start()
|
9
|
+
|
10
|
+
// Registra i controller
|
11
|
+
application.register("toast", ToastController)
|
12
|
+
application.register("navbar", NavbarController)
|
13
|
+
application.register("sidebar", SidebarController)
|
14
|
+
|
15
|
+
// Esporta i controller e altri componenti
|
16
|
+
export { ToastController, NavbarController, SidebarController }
|
17
|
+
export { default as ToastManager } from "./toast_manager"
|
18
|
+
|
19
|
+
// Funzione di utilità per creare e mostrare un toast programmaticamente
|
20
|
+
export function showToast(options = {}) {
|
21
|
+
const {
|
22
|
+
title = null,
|
23
|
+
message = "Notifica",
|
24
|
+
variant = "info",
|
25
|
+
position = "top-right",
|
26
|
+
duration = 5000,
|
27
|
+
dismissible = true,
|
28
|
+
autoHide = true,
|
29
|
+
icon = null
|
30
|
+
} = options;
|
31
|
+
|
32
|
+
// Crea l'elemento toast
|
33
|
+
const toast = document.createElement("div");
|
34
|
+
toast.setAttribute("role", "status");
|
35
|
+
toast.setAttribute("aria-live", "polite");
|
36
|
+
toast.classList.add(
|
37
|
+
"fixed", "z-50", "rounded-lg", "p-4", "border", "shadow-lg",
|
38
|
+
"transform", "transition-transform", "duration-300",
|
39
|
+
"min-w-[20rem]", "max-w-sm", "flex", "items-start",
|
40
|
+
position
|
41
|
+
);
|
42
|
+
|
43
|
+
// Aggiungi classi specifiche per la variante
|
44
|
+
const variantClasses = {
|
45
|
+
primary: ["bg-orange-50", "border-orange-300"],
|
46
|
+
info: ["bg-blue-50", "border-blue-300"],
|
47
|
+
success: ["bg-green-50", "border-green-300"],
|
48
|
+
warning: ["bg-yellow-50", "border-yellow-300"],
|
49
|
+
danger: ["bg-red-50", "border-red-300"],
|
50
|
+
dark: ["bg-gray-800", "border-gray-700"]
|
51
|
+
};
|
52
|
+
|
53
|
+
// Applica le classi della variante
|
54
|
+
const selectedVariant = variantClasses[variant] || variantClasses.info;
|
55
|
+
toast.classList.add(...selectedVariant);
|
56
|
+
|
57
|
+
// Aggiungi attributi per Stimulus
|
58
|
+
toast.setAttribute("data-controller", "toast");
|
59
|
+
toast.setAttribute("data-toast-duration-value", duration);
|
60
|
+
toast.setAttribute("data-toast-auto-hide-value", autoHide);
|
61
|
+
toast.setAttribute("data-toast-position-value", position);
|
62
|
+
|
63
|
+
// Costruisci il contenuto HTML
|
64
|
+
let html = "";
|
65
|
+
|
66
|
+
// Icona
|
67
|
+
const defaultIcons = {
|
68
|
+
primary: "bell",
|
69
|
+
info: "info-circle",
|
70
|
+
success: "check-circle",
|
71
|
+
warning: "exclamation-triangle",
|
72
|
+
danger: "exclamation-circle",
|
73
|
+
dark: "shield-exclamation"
|
74
|
+
};
|
75
|
+
|
76
|
+
const iconName = icon || defaultIcons[variant] || defaultIcons.info;
|
77
|
+
|
78
|
+
if (iconName) {
|
79
|
+
const iconColorClasses = {
|
80
|
+
primary: "text-orange-500",
|
81
|
+
info: "text-blue-500",
|
82
|
+
success: "text-green-500",
|
83
|
+
warning: "text-yellow-500",
|
84
|
+
danger: "text-red-500",
|
85
|
+
dark: "text-gray-400"
|
86
|
+
};
|
87
|
+
|
88
|
+
html += `
|
89
|
+
<div class="flex-shrink-0 mr-3 mt-0.5 ${iconColorClasses[variant] || iconColorClasses.info}">
|
90
|
+
<i class="fas fa-${iconName}"></i>
|
91
|
+
</div>
|
92
|
+
`;
|
93
|
+
}
|
94
|
+
|
95
|
+
// Contenuto
|
96
|
+
const titleColorClasses = {
|
97
|
+
primary: "text-orange-800",
|
98
|
+
info: "text-blue-800",
|
99
|
+
success: "text-green-800",
|
100
|
+
warning: "text-yellow-800",
|
101
|
+
danger: "text-red-800",
|
102
|
+
dark: "text-white"
|
103
|
+
};
|
104
|
+
|
105
|
+
const messageColorClasses = {
|
106
|
+
primary: "text-orange-700",
|
107
|
+
info: "text-blue-700",
|
108
|
+
success: "text-green-700",
|
109
|
+
warning: "text-yellow-700",
|
110
|
+
danger: "text-red-700",
|
111
|
+
dark: "text-gray-300"
|
112
|
+
};
|
113
|
+
|
114
|
+
html += '<div class="flex-1">';
|
115
|
+
|
116
|
+
if (title) {
|
117
|
+
html += `<div class="font-medium ${titleColorClasses[variant] || titleColorClasses.info}">${title}</div>`;
|
118
|
+
}
|
119
|
+
|
120
|
+
if (message) {
|
121
|
+
html += `<div class="mt-1 ${messageColorClasses[variant] || messageColorClasses.info}">${message}</div>`;
|
122
|
+
}
|
123
|
+
|
124
|
+
if (autoHide) {
|
125
|
+
html += `
|
126
|
+
<div class="w-full bg-gray-200 h-1 mt-2 rounded overflow-hidden">
|
127
|
+
<div class="bg-current h-1 transition-all" data-toast-target="progressBar"></div>
|
128
|
+
</div>
|
129
|
+
`;
|
130
|
+
}
|
131
|
+
|
132
|
+
html += '</div>';
|
133
|
+
|
134
|
+
// Pulsante di chiusura
|
135
|
+
if (dismissible) {
|
136
|
+
const closeButtonColorClasses = {
|
137
|
+
primary: "text-orange-500 hover:bg-orange-100",
|
138
|
+
info: "text-blue-500 hover:bg-blue-100",
|
139
|
+
success: "text-green-500 hover:bg-green-100",
|
140
|
+
warning: "text-yellow-500 hover:bg-yellow-100",
|
141
|
+
danger: "text-red-500 hover:bg-red-100",
|
142
|
+
dark: "text-gray-400 hover:bg-gray-700"
|
143
|
+
};
|
144
|
+
|
145
|
+
html += `
|
146
|
+
<button type="button" class="ml-auto -mr-1.5 -mt-1.5 inline-flex h-8 w-8 rounded-lg p-1.5 focus:ring-2 focus:ring-gray-400 ${closeButtonColorClasses[variant] || closeButtonColorClasses.info}" data-action="toast#hide" aria-label="Chiudi">
|
147
|
+
<i class="fas fa-xmark"></i>
|
148
|
+
</button>
|
149
|
+
`;
|
150
|
+
}
|
151
|
+
|
152
|
+
// Inserisci il contenuto
|
153
|
+
toast.innerHTML = html;
|
154
|
+
|
155
|
+
// Aggiungi il toast al documento
|
156
|
+
document.body.appendChild(toast);
|
157
|
+
|
158
|
+
return toast;
|
159
|
+
}
|
@@ -0,0 +1,77 @@
|
|
1
|
+
// Gestore per l'impilamento dei toast in diverse posizioni
|
2
|
+
class ToastManager {
|
3
|
+
constructor() {
|
4
|
+
// Mantiene traccia dei toast attivi per posizione
|
5
|
+
this.toasts = {
|
6
|
+
'top-right': [],
|
7
|
+
'top-left': [],
|
8
|
+
'bottom-right': [],
|
9
|
+
'bottom-left': [],
|
10
|
+
'top-center': [],
|
11
|
+
'bottom-center': []
|
12
|
+
}
|
13
|
+
|
14
|
+
// Offset di base per ogni posizione (in px)
|
15
|
+
this.baseOffset = 16; // equivalente a Tailwind top-4 (16px)
|
16
|
+
|
17
|
+
// Spaziatura tra i toast (in px)
|
18
|
+
this.spacing = 12;
|
19
|
+
}
|
20
|
+
|
21
|
+
// Registra un nuovo toast e calcola la sua posizione
|
22
|
+
registerToast(toast, position) {
|
23
|
+
if (!this.toasts[position]) {
|
24
|
+
console.warn(`Posizione toast non valida: ${position}. Utilizzo 'top-right' come predefinita.`);
|
25
|
+
position = 'top-right';
|
26
|
+
}
|
27
|
+
|
28
|
+
// Aggiungi il toast all'array della posizione specifica
|
29
|
+
this.toasts[position].push(toast);
|
30
|
+
|
31
|
+
// Ricalcola le posizioni per tutti i toast in questa posizione
|
32
|
+
this.updatePositions(position);
|
33
|
+
|
34
|
+
return () => this.removeToast(toast, position);
|
35
|
+
}
|
36
|
+
|
37
|
+
// Rimuove un toast e ricalcola le posizioni
|
38
|
+
removeToast(toast, position) {
|
39
|
+
const index = this.toasts[position].indexOf(toast);
|
40
|
+
if (index !== -1) {
|
41
|
+
this.toasts[position].splice(index, 1);
|
42
|
+
this.updatePositions(position);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
// Aggiorna le posizioni di tutti i toast in una data posizione
|
47
|
+
updatePositions(position) {
|
48
|
+
const isTopPosition = position.startsWith('top-');
|
49
|
+
const toastArray = this.toasts[position];
|
50
|
+
|
51
|
+
let currentOffset = this.baseOffset;
|
52
|
+
|
53
|
+
toastArray.forEach((toast, index) => {
|
54
|
+
// Applica la posizione corretta
|
55
|
+
if (isTopPosition) {
|
56
|
+
toast.style.top = `${currentOffset}px`;
|
57
|
+
} else {
|
58
|
+
toast.style.bottom = `${currentOffset}px`;
|
59
|
+
}
|
60
|
+
|
61
|
+
// Aggiorna l'offset per il prossimo toast
|
62
|
+
const height = toast.offsetHeight;
|
63
|
+
currentOffset += height + this.spacing;
|
64
|
+
});
|
65
|
+
}
|
66
|
+
|
67
|
+
// Metodo statico per accedere all'istanza singleton
|
68
|
+
static getInstance() {
|
69
|
+
if (!ToastManager.instance) {
|
70
|
+
ToastManager.instance = new ToastManager();
|
71
|
+
}
|
72
|
+
return ToastManager.instance;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
// Esporta il gestore come singleton
|
77
|
+
export default ToastManager.getInstance();
|
@@ -12,360 +12,34 @@
|
|
12
12
|
*
|
13
13
|
*= require_tree .
|
14
14
|
*= require_self
|
15
|
+
*= require font-awesome
|
15
16
|
*/
|
16
17
|
|
17
|
-
/*
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*= require_self
|
18
|
+
/*
|
19
|
+
* BetterUI - Utilizziamo Tailwind CSS per tutti gli stili
|
21
20
|
*/
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
--better-ui-danger: #dc3545;
|
29
|
-
--better-ui-warning: #ffc107;
|
30
|
-
--better-ui-info: #17a2b8;
|
31
|
-
|
32
|
-
/* Colori di sfondo */
|
33
|
-
--better-ui-bg-light: #ffffff;
|
34
|
-
--better-ui-bg-dark: #343a40;
|
35
|
-
|
36
|
-
/* Colori di testo */
|
37
|
-
--better-ui-text-dark: #343a40;
|
38
|
-
--better-ui-text-light: #f8f9fa;
|
39
|
-
|
40
|
-
/* Bordi */
|
41
|
-
--better-ui-border-color: #dee2e6;
|
42
|
-
--better-ui-border-radius: 0.25rem;
|
43
|
-
|
44
|
-
/* Spaziature */
|
45
|
-
--better-ui-spacer: 1rem;
|
46
|
-
--better-ui-spacer-sm: 0.5rem;
|
47
|
-
--better-ui-spacer-lg: 1.5rem;
|
48
|
-
|
49
|
-
/* Transizioni */
|
50
|
-
--better-ui-transition: all 0.2s ease-in-out;
|
51
|
-
}
|
52
|
-
|
53
|
-
/*
|
54
|
-
* Button
|
55
|
-
*/
|
56
|
-
.better-ui-button {
|
57
|
-
display: inline-block;
|
58
|
-
font-weight: 400;
|
59
|
-
text-align: center;
|
60
|
-
white-space: nowrap;
|
61
|
-
vertical-align: middle;
|
62
|
-
user-select: none;
|
63
|
-
border: 1px solid transparent;
|
64
|
-
padding: var(--better-ui-spacer-sm) var(--better-ui-spacer);
|
65
|
-
font-size: 1rem;
|
22
|
+
/* Stili per il syntax highlighting di CodeRay */
|
23
|
+
.syntax-ruby {
|
24
|
+
color: #333;
|
25
|
+
background-color: #f8f8f8;
|
26
|
+
font-family: Monaco, Consolas, 'Courier New', monospace;
|
66
27
|
line-height: 1.5;
|
67
|
-
border-radius: var(--better-ui-border-radius);
|
68
|
-
transition: var(--better-ui-transition);
|
69
|
-
cursor: pointer;
|
70
|
-
}
|
71
|
-
|
72
|
-
.better-ui-button:focus {
|
73
|
-
outline: 0;
|
74
|
-
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
75
|
-
}
|
76
|
-
|
77
|
-
.better-ui-button-primary {
|
78
|
-
color: var(--better-ui-text-light);
|
79
|
-
background-color: var(--better-ui-primary);
|
80
|
-
border-color: var(--better-ui-primary);
|
81
|
-
}
|
82
|
-
|
83
|
-
.better-ui-button-primary:hover {
|
84
|
-
background-color: #0069d9;
|
85
|
-
border-color: #0062cc;
|
86
|
-
}
|
87
|
-
|
88
|
-
.better-ui-button-secondary {
|
89
|
-
color: var(--better-ui-text-light);
|
90
|
-
background-color: var(--better-ui-secondary);
|
91
|
-
border-color: var(--better-ui-secondary);
|
92
|
-
}
|
93
|
-
|
94
|
-
.better-ui-button-secondary:hover {
|
95
|
-
background-color: #5a6268;
|
96
|
-
border-color: #545b62;
|
97
|
-
}
|
98
|
-
|
99
|
-
.better-ui-button-success {
|
100
|
-
color: var(--better-ui-text-light);
|
101
|
-
background-color: var(--better-ui-success);
|
102
|
-
border-color: var(--better-ui-success);
|
103
|
-
}
|
104
|
-
|
105
|
-
.better-ui-button-success:hover {
|
106
|
-
background-color: #218838;
|
107
|
-
border-color: #1e7e34;
|
108
|
-
}
|
109
|
-
|
110
|
-
.better-ui-button-danger {
|
111
|
-
color: var(--better-ui-text-light);
|
112
|
-
background-color: var(--better-ui-danger);
|
113
|
-
border-color: var(--better-ui-danger);
|
114
|
-
}
|
115
|
-
|
116
|
-
.better-ui-button-danger:hover {
|
117
|
-
background-color: #c82333;
|
118
|
-
border-color: #bd2130;
|
119
|
-
}
|
120
|
-
|
121
|
-
.better-ui-button:disabled {
|
122
|
-
opacity: 0.65;
|
123
|
-
cursor: not-allowed;
|
124
|
-
}
|
125
|
-
|
126
|
-
/*
|
127
|
-
* Alert
|
128
|
-
*/
|
129
|
-
.better-ui-alert {
|
130
|
-
position: relative;
|
131
|
-
padding: var(--better-ui-spacer);
|
132
|
-
margin-bottom: var(--better-ui-spacer);
|
133
|
-
border: 1px solid transparent;
|
134
|
-
border-radius: var(--better-ui-border-radius);
|
135
|
-
transition: var(--better-ui-transition);
|
136
|
-
}
|
137
|
-
|
138
|
-
.better-ui-alert-message {
|
139
|
-
margin-right: 2rem;
|
140
|
-
}
|
141
|
-
|
142
|
-
.better-ui-alert-close {
|
143
|
-
position: absolute;
|
144
|
-
top: var(--better-ui-spacer-sm);
|
145
|
-
right: var(--better-ui-spacer-sm);
|
146
|
-
background: transparent;
|
147
|
-
border: none;
|
148
|
-
font-size: 1.25rem;
|
149
|
-
font-weight: 700;
|
150
|
-
line-height: 1;
|
151
|
-
cursor: pointer;
|
152
|
-
opacity: 0.5;
|
153
|
-
transition: var(--better-ui-transition);
|
154
|
-
}
|
155
|
-
|
156
|
-
.better-ui-alert-close:hover {
|
157
|
-
opacity: 1;
|
158
|
-
}
|
159
|
-
|
160
|
-
.better-ui-alert-info {
|
161
|
-
color: #0c5460;
|
162
|
-
background-color: #d1ecf1;
|
163
|
-
border-color: #bee5eb;
|
164
|
-
}
|
165
|
-
|
166
|
-
.better-ui-alert-success {
|
167
|
-
color: #155724;
|
168
|
-
background-color: #d4edda;
|
169
|
-
border-color: #c3e6cb;
|
170
|
-
}
|
171
|
-
|
172
|
-
.better-ui-alert-warning {
|
173
|
-
color: #856404;
|
174
|
-
background-color: #fff3cd;
|
175
|
-
border-color: #ffeeba;
|
176
|
-
}
|
177
|
-
|
178
|
-
.better-ui-alert-danger {
|
179
|
-
color: #721c24;
|
180
|
-
background-color: #f8d7da;
|
181
|
-
border-color: #f5c6cb;
|
182
|
-
}
|
183
|
-
|
184
|
-
.better-ui-alert-closing {
|
185
|
-
opacity: 0;
|
186
|
-
transform: translateY(-10px);
|
187
|
-
}
|
188
|
-
|
189
|
-
/*
|
190
|
-
* Card
|
191
|
-
*/
|
192
|
-
.better-ui-card {
|
193
|
-
position: relative;
|
194
|
-
display: flex;
|
195
|
-
flex-direction: column;
|
196
|
-
min-width: 0;
|
197
|
-
word-wrap: break-word;
|
198
|
-
background-color: var(--better-ui-bg-light);
|
199
|
-
background-clip: border-box;
|
200
|
-
border: 1px solid var(--better-ui-border-color);
|
201
|
-
border-radius: var(--better-ui-border-radius);
|
202
|
-
margin-bottom: var(--better-ui-spacer);
|
203
|
-
}
|
204
|
-
|
205
|
-
.better-ui-card-header {
|
206
|
-
padding: 0.75rem 1.25rem;
|
207
|
-
margin-bottom: 0;
|
208
|
-
background-color: rgba(0, 0, 0, 0.03);
|
209
|
-
border-bottom: 1px solid var(--better-ui-border-color);
|
210
|
-
}
|
211
|
-
|
212
|
-
.better-ui-card-title {
|
213
|
-
margin: 0;
|
214
|
-
font-size: 1.25rem;
|
215
|
-
font-weight: 500;
|
216
|
-
}
|
217
|
-
|
218
|
-
.better-ui-card-body {
|
219
|
-
flex: 1 1 auto;
|
220
|
-
padding: 1.25rem;
|
221
|
-
}
|
222
|
-
|
223
|
-
.better-ui-card-footer {
|
224
|
-
padding: 0.75rem 1.25rem;
|
225
|
-
background-color: rgba(0, 0, 0, 0.03);
|
226
|
-
border-top: 1px solid var(--better-ui-border-color);
|
227
|
-
}
|
228
|
-
|
229
|
-
/*
|
230
|
-
* Tabs
|
231
|
-
*/
|
232
|
-
.better-ui-tabs {
|
233
|
-
margin-bottom: var(--better-ui-spacer);
|
234
|
-
}
|
235
|
-
|
236
|
-
.better-ui-tab-list {
|
237
|
-
display: flex;
|
238
|
-
flex-wrap: wrap;
|
239
|
-
padding-left: 0;
|
240
|
-
margin-bottom: 0;
|
241
|
-
list-style: none;
|
242
|
-
border-bottom: 1px solid var(--better-ui-border-color);
|
243
|
-
}
|
244
|
-
|
245
|
-
.better-ui-tab-item {
|
246
|
-
display: block;
|
247
|
-
padding: 0.5rem 1rem;
|
248
|
-
border: 1px solid transparent;
|
249
|
-
border-top-left-radius: var(--better-ui-border-radius);
|
250
|
-
border-top-right-radius: var(--better-ui-border-radius);
|
251
|
-
cursor: pointer;
|
252
|
-
background: none;
|
253
|
-
margin-bottom: -1px;
|
254
|
-
}
|
255
|
-
|
256
|
-
.better-ui-tab-item:hover {
|
257
|
-
border-color: #e9ecef #e9ecef var(--better-ui-border-color);
|
258
|
-
}
|
259
|
-
|
260
|
-
.better-ui-tab-active {
|
261
|
-
color: var(--better-ui-primary);
|
262
|
-
background-color: var(--better-ui-bg-light);
|
263
|
-
border-color: var(--better-ui-border-color) var(--better-ui-border-color) var(--better-ui-bg-light);
|
264
|
-
}
|
265
|
-
|
266
|
-
.better-ui-tab-content {
|
267
|
-
padding: var(--better-ui-spacer);
|
268
|
-
border: 1px solid var(--better-ui-border-color);
|
269
|
-
border-top: 0;
|
270
|
-
border-bottom-right-radius: var(--better-ui-border-radius);
|
271
|
-
border-bottom-left-radius: var(--better-ui-border-radius);
|
272
|
-
}
|
273
|
-
|
274
|
-
/*
|
275
|
-
* Modal
|
276
|
-
*/
|
277
|
-
.better-ui-modal {
|
278
|
-
position: fixed;
|
279
|
-
top: 0;
|
280
|
-
left: 0;
|
281
|
-
width: 100%;
|
282
|
-
height: 100%;
|
283
|
-
z-index: 1050;
|
284
|
-
display: none;
|
285
|
-
overflow: hidden;
|
286
|
-
align-items: center;
|
287
|
-
justify-content: center;
|
288
|
-
}
|
289
|
-
|
290
|
-
.better-ui-modal-background {
|
291
|
-
position: fixed;
|
292
|
-
top: 0;
|
293
|
-
left: 0;
|
294
|
-
width: 100%;
|
295
|
-
height: 100%;
|
296
|
-
background-color: rgba(0, 0, 0, 0.5);
|
297
|
-
opacity: 0;
|
298
|
-
transition: opacity 0.3s ease;
|
299
|
-
}
|
300
|
-
|
301
|
-
.better-ui-modal-background-visible {
|
302
|
-
opacity: 1;
|
303
|
-
}
|
304
|
-
|
305
|
-
.better-ui-modal-dialog {
|
306
|
-
position: relative;
|
307
|
-
width: 100%;
|
308
|
-
max-width: 500px;
|
309
|
-
margin: 1.75rem auto;
|
310
|
-
background-color: var(--better-ui-bg-light);
|
311
|
-
border-radius: var(--better-ui-border-radius);
|
312
|
-
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
313
|
-
transform: translateY(-20px);
|
314
|
-
opacity: 0;
|
315
|
-
transition: transform 0.3s ease, opacity 0.3s ease;
|
316
|
-
}
|
317
|
-
|
318
|
-
.better-ui-modal-dialog-visible {
|
319
|
-
transform: translateY(0);
|
320
|
-
opacity: 1;
|
321
|
-
}
|
322
|
-
|
323
|
-
.better-ui-modal-header {
|
324
|
-
display: flex;
|
325
|
-
align-items: flex-start;
|
326
|
-
justify-content: space-between;
|
327
|
-
padding: 1rem;
|
328
|
-
border-bottom: 1px solid var(--better-ui-border-color);
|
329
|
-
}
|
330
|
-
|
331
|
-
.better-ui-modal-title {
|
332
|
-
margin: 0;
|
333
|
-
font-size: 1.25rem;
|
334
|
-
font-weight: 500;
|
335
|
-
}
|
336
|
-
|
337
|
-
.better-ui-modal-close {
|
338
|
-
background: transparent;
|
339
|
-
border: 0;
|
340
|
-
font-size: 1.5rem;
|
341
|
-
font-weight: 700;
|
342
|
-
line-height: 1;
|
343
|
-
color: var(--better-ui-text-dark);
|
344
|
-
opacity: 0.5;
|
345
|
-
cursor: pointer;
|
346
|
-
}
|
347
|
-
|
348
|
-
.better-ui-modal-close:hover {
|
349
|
-
opacity: 1;
|
350
|
-
}
|
351
|
-
|
352
|
-
.better-ui-modal-body {
|
353
|
-
position: relative;
|
354
|
-
padding: 1rem;
|
355
|
-
}
|
356
|
-
|
357
|
-
.better-ui-modal-footer {
|
358
|
-
display: flex;
|
359
|
-
align-items: center;
|
360
|
-
justify-content: flex-end;
|
361
|
-
padding: 1rem;
|
362
|
-
border-top: 1px solid var(--better-ui-border-color);
|
363
|
-
}
|
364
|
-
|
365
|
-
.better-ui-modal-footer > .better-ui-button {
|
366
|
-
margin-left: 0.5rem;
|
367
|
-
}
|
368
|
-
|
369
|
-
body.better-ui-modal-open {
|
370
|
-
overflow: hidden;
|
371
28
|
}
|
29
|
+
.syntax-ruby .keyword { color: #0066CC; font-weight: bold; }
|
30
|
+
.syntax-ruby .string, .syntax-ruby .string-content { color: #008800; }
|
31
|
+
.syntax-ruby .comment { color: #888888; font-style: italic; }
|
32
|
+
.syntax-ruby .constant { color: #CC0000; }
|
33
|
+
.syntax-ruby .class { color: #0086B3; font-weight: bold; }
|
34
|
+
.syntax-ruby .module { color: #0086B3; font-weight: bold; }
|
35
|
+
.syntax-ruby .symbol { color: #AA6600; }
|
36
|
+
.syntax-ruby .function { color: #990000; }
|
37
|
+
.syntax-ruby .regexp { color: #AA6600; }
|
38
|
+
.syntax-ruby .integer, .syntax-ruby .float { color: #0000DD; }
|
39
|
+
.syntax-ruby .global-variable, .syntax-ruby .instance-variable { color: #336699; }
|
40
|
+
.syntax-ruby .predefined { color: #3377BB; font-weight: bold; }
|
41
|
+
.syntax-ruby .error { color: #FF0000; background-color: #FFAAAA; }
|
42
|
+
.syntax-ruby .delimiter { color: #555555; }
|
43
|
+
.syntax-ruby .method { color: #990000; font-weight: bold; }
|
44
|
+
.syntax-ruby .attribute-name { color: #994500; }
|
45
|
+
.syntax-ruby .value { color: #0066CC; }
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<div role="alert" class="<%= container_classes %>" <%= @data&.map { |k, v| "data-#{k}=\"#{v}\"" }&.join(' ')&.html_safe %>>
|
2
|
+
<% if effective_icon.present? %>
|
3
|
+
<div class="<%= icon_classes %>">
|
4
|
+
<%= render BetterUi::General::IconComponent.new(name: effective_icon) %>
|
5
|
+
</div>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<div class="<%= content_classes %>">
|
9
|
+
<% if @title.present? %>
|
10
|
+
<div class="<%= title_classes %>"><%= @title %></div>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<% if @message.present? %>
|
14
|
+
<div class="<%= message_classes %>"><%= @message %></div>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<% if content.present? %>
|
18
|
+
<div class="<%= message_classes %>"><%= content %></div>
|
19
|
+
<% end %>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<% if @dismissible %>
|
23
|
+
<button type="button" class="<%= close_button_classes %>" data-dismiss-target="[role='alert']" aria-label="Chiudi">
|
24
|
+
<%= render BetterUi::General::IconComponent.new(name: "xmark") %>
|
25
|
+
</button>
|
26
|
+
<% end %>
|
27
|
+
</div>
|