@edc-motor/ui 0.4.17 → 0.4.19

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edc-motor/ui",
3
- "version": "0.4.17",
3
+ "version": "0.4.19",
4
4
  "description": "EdC Motor — componentes públicos Vue 3 + tokens SCSS para webs de juegos de mesa (paquete fuente: lo compila el consumidor con Vite)",
5
5
  "license": "GPL-3.0-only",
6
6
  "type": "module",
package/scss/_tokens.scss CHANGED
@@ -112,3 +112,16 @@ $input-border: $border;
112
112
  $input-border-hover: $border-strong;
113
113
  $input-border-focus: $accent-500;
114
114
  $input-focus-ring: $focus-ring;
115
+
116
+ // ---------------------------------------------------------
117
+ // Texto que CONTRASTA con un fondo arbitrario (el acento elegido en
118
+ // Ajustes, el color de una acción…): el navegador resuelve claro u oscuro
119
+ // según la luminosidad REAL del fondo (relative color syntax): blanco puro
120
+ // bajo L≈49.44 y negro puro por encima — el umbral donde el contraste real
121
+ // cambia de bando. La primera declaración es el FALLBACK (texto oscuro)
122
+ // para navegadores sin `lch(from …)`.
123
+ // ---------------------------------------------------------
124
+ @mixin contrast-text($bg) {
125
+ color: #111827;
126
+ color: lch(from #{$bg} calc((49.44 - l) * infinity) 0 0);
127
+ }
@@ -49,13 +49,16 @@
49
49
  }
50
50
  }
51
51
 
52
+ // Relleno de color: el texto NO es fijo — claro u oscuro según el fondo
53
+ // real (contrast-text de tokens), que el acento lo elige el usuario.
52
54
  &--primary {
53
55
  background: $color-accent;
54
- color: #fff;
56
+ @include contrast-text($color-accent);
55
57
 
56
58
  // Hover bien visible: accent-600 apenas se distingue del 500.
57
59
  &:hover:not(:disabled) {
58
60
  background: color-mix(in srgb, $color-accent 72%, black);
61
+ @include contrast-text(color-mix(in srgb, $color-accent 72%, black));
59
62
  }
60
63
  }
61
64
 
@@ -94,23 +97,16 @@
94
97
  }
95
98
  }
96
99
 
97
- .edc-button--danger {
98
- background: $danger;
99
- color: #fff;
100
- &:hover:not(:disabled) { background: color-mix(in srgb, $danger 72%, black); }
101
- }
102
- .edc-button--success {
103
- background: $success;
104
- color: #06281a;
105
- &:hover:not(:disabled) { background: color-mix(in srgb, $success 72%, black); }
106
- }
107
- .edc-button--info {
108
- background: $info;
109
- color: #fff;
110
- &:hover:not(:disabled) { background: color-mix(in srgb, $info 72%, black); }
111
- }
112
- .edc-button--warning {
113
- background: $warning;
114
- color: #2b2005;
115
- &:hover:not(:disabled) { background: color-mix(in srgb, $warning 72%, black); }
100
+ // Variantes semánticas rellenas: mismo criterio que --primary, el texto lo
101
+ // decide el fondo (antes iba fijado a mano y a veces no contrastaba).
102
+ @each $variant, $color in (danger: $danger, success: $success, info: $info, warning: $warning) {
103
+ .edc-button--#{$variant} {
104
+ background: $color;
105
+ @include contrast-text($color);
106
+
107
+ &:hover:not(:disabled) {
108
+ background: color-mix(in srgb, #{$color} 72%, black);
109
+ @include contrast-text(color-mix(in srgb, #{$color} 72%, black));
110
+ }
111
+ }
116
112
  }
@@ -22,7 +22,7 @@
22
22
  }
23
23
 
24
24
  .block__related-button {
25
- justify-self: start;
25
+ justify-self: center; // estrecho: los botones de bloque van centrados
26
26
 
27
27
  @media (min-width: $bp-sm) {
28
28
  justify-self: end;
@@ -21,7 +21,8 @@
21
21
  // Tipografía de bloque: texto $fs-16, subtítulo $fs-20, título $fs-28
22
22
  // (la cabecera sube a 32/24). Los títulos nunca se justifican.
23
23
  &__title { margin: 0; font-size: $fs-28; }
24
- &__subtitle { margin: 0; color: $text-2; font-size: $fs-20; }
24
+ // pre-line: el subtítulo es un textarea — sus saltos de línea cuentan.
25
+ &__subtitle { margin: 0; color: $text-2; font-size: $fs-20; white-space: pre-line; }
25
26
  &__text { color: $text-1; font-size: $fs-16; }
26
27
 
27
28
  &--align-justify &__title,
@@ -160,10 +161,30 @@
160
161
  align-content: center; // centrado frente a la imagen sangrada
161
162
  }
162
163
 
164
+ // Botón del CTA: en estrecho va SIEMPRE centrado (como el del related);
165
+ // de $bp-sm para arriba manda su campo "Alineación del botón".
166
+ &__cta-button--left,
167
+ &__cta-button--center,
168
+ &__cta-button--right {
169
+ justify-self: center;
170
+ }
171
+
172
+ @media (min-width: $bp-sm) {
173
+ &__cta-button--left { justify-self: start; }
174
+ &__cta-button--center { justify-self: center; }
175
+ &__cta-button--right { justify-self: end; }
176
+ }
177
+
163
178
  // La imagen del CTA sangra hasta el borde de la tarjeta según su posición:
164
179
  // en columnas toca arriba, abajo y su lateral (el título viaja a la
165
180
  // columna de texto); arriba/abajo toca los laterales. Esquinas siguiendo
166
181
  // el radio de la tarjeta.
182
+ // La tarjeta del CTA lleva un halo SUTIL del acento, igual por los cuatro
183
+ // bordes (sin offset), además de su sombra de profundidad normal.
184
+ &--cta .block__card {
185
+ box-shadow: $shadow-sm, 0 0 18px color-mix(in srgb, $accent-500 30%, transparent);
186
+ }
187
+
167
188
  &--cta.block--image-right .block__media-layout .block__image-frame,
168
189
  &--cta.block--image-left .block__media-layout .block__image-frame {
169
190
  @container content (min-width: #{$bp-sm}) {
@@ -267,6 +288,9 @@
267
288
  align-items: center;
268
289
  gap: $space-2;
269
290
  padding: $space-2 $space-5;
291
+
292
+ // "Botón grande" (campo button_large del CTA): más aire interior.
293
+ &--large { padding: $space-4 $space-8; }
270
294
  border: 1px solid $accent-500;
271
295
  border-radius: $radius-md;
272
296
  font-size: $fs-18;
@@ -277,9 +301,11 @@
277
301
 
278
302
  // El "fondo" de los estados cruzados es la SUPERFICIE ($surface, el
279
303
  // segundo tono), no el fondo de página puro: menos negro / menos blanco.
304
+ // Relleno de acento: el texto lo decide el FONDO (contrast-text), no el
305
+ // tema — con acentos claros, $text-1 del tema oscuro no se leía.
280
306
  &--primary {
281
307
  background: $accent-500;
282
- color: $text-1;
308
+ @include contrast-text($accent-500);
283
309
 
284
310
  &:hover {
285
311
  background: $surface;
@@ -293,7 +319,7 @@
293
319
 
294
320
  &:hover {
295
321
  background: $accent-500;
296
- color: $text-1;
322
+ @include contrast-text($accent-500);
297
323
  }
298
324
  }
299
325
  }
@@ -116,8 +116,43 @@
116
116
  }
117
117
 
118
118
  // Variante compacta (bloque related): tarjetas y huecos más contenidos.
119
+ // El bloque trae SIEMPRE 6 ítems y es el grid quien decide cuántos enseña
120
+ // para que la rejilla salga siempre completa, sin filas cojas:
121
+ // 4 en 2×2 (estrecho) → 6 en 3×2 (md) → 4 en 4×1 (lg) → 5 en 5×1 (xl).
119
122
  &--compact &__grid {
120
123
  gap: $space-3;
124
+ grid-template-columns: repeat(2, minmax(0, 1fr));
125
+
126
+ @media (min-width: $bp-md) {
127
+ grid-template-columns: repeat(3, minmax(0, 1fr));
128
+ }
129
+
130
+ @media (min-width: $bp-lg) {
131
+ grid-template-columns: repeat(4, minmax(0, 1fr));
132
+ }
133
+
134
+ @media (min-width: $bp-xl) {
135
+ grid-template-columns: repeat(5, minmax(0, 1fr));
136
+ }
137
+ }
138
+
139
+ // Qué huecos se ven en cada tramo (los demás, ocultos): 4 → 6 → 4 → 5.
140
+ &--compact &__slot:nth-child(n + 5) {
141
+ display: none;
142
+
143
+ @media (min-width: $bp-md) {
144
+ display: block;
145
+ }
146
+
147
+ @media (min-width: $bp-lg) {
148
+ display: none;
149
+ }
150
+ }
151
+
152
+ &--compact &__slot:nth-child(5) {
153
+ @media (min-width: $bp-xl) {
154
+ display: block;
155
+ }
121
156
  }
122
157
 
123
158
  &--compact &__fallback {
@@ -44,10 +44,16 @@ const layoutStyle = computed(() => {
44
44
  <p v-if="settings.subtitle" class="block__subtitle">{{ settings.subtitle }}</p>
45
45
  </template>
46
46
  <div v-if="settings.body" class="block__text rich-content" v-html="settings.body" />
47
+ <!-- Alineación propia (button_align; en estrecho el CSS centra
48
+ siempre) y tamaño grande opcional (button_large) -->
47
49
  <a
48
50
  v-if="settings.button_text && settings.button_url"
49
51
  class="block-button"
50
- :class="`block-button--${settings.button_variant || 'primary'}`"
52
+ :class="[
53
+ `block-button--${settings.button_variant || 'primary'}`,
54
+ `block__cta-button--${settings.button_align || 'left'}`,
55
+ settings.button_large ? 'block-button--large' : '',
56
+ ]"
51
57
  :href="String(settings.button_url)"
52
58
  >
53
59
  {{ settings.button_text }}
@@ -9,7 +9,8 @@ import { computed, type CSSProperties } from 'vue'
9
9
  const props = defineProps<{ settings: Record<string, unknown> }>()
10
10
 
11
11
  const width = computed(() => `block--w-${(props.settings.width as string) || 'wide'}`)
12
- const align = computed(() => `block--align-${(props.settings.align as string) || 'left'}`)
12
+ // Sin valor guardado, JUSTIFICADO (el default del campo común del motor).
13
+ const align = computed(() => `block--align-${(props.settings.align as string) || 'justify'}`)
13
14
 
14
15
  const style = computed<CSSProperties>(() => {
15
16
  const background = props.settings.background as string | undefined
@@ -17,7 +18,7 @@ const style = computed<CSSProperties>(() => {
17
18
  '--block-bg': background
18
19
  ? `color-mix(in srgb, ${background} var(--block-tint, 15%), transparent)`
19
20
  : 'transparent',
20
- textAlign: ((props.settings.align as string) || 'left') as CSSProperties['textAlign'],
21
+ textAlign: ((props.settings.align as string) || 'justify') as CSSProperties['textAlign'],
21
22
  }
22
23
  })
23
24
  </script>