@edc-motor/ui 0.5.4 → 0.5.5

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.5.4",
3
+ "version": "0.5.5",
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",
@@ -32,9 +32,23 @@
32
32
  background: var(--swatch-color);
33
33
  color: #fff;
34
34
  cursor: pointer;
35
- transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
35
+ transition: box-shadow 0.15s, border-color 0.15s;
36
36
 
37
- &:hover { transform: scale(1.06); }
37
+ // Realce al hover: SOLO halo (sombra), nunca transform — el
38
+ // scale(1.06) de antes rasterizaba el swatch (y sus 2px de borde) en
39
+ // fracciones de píxel durante la transición: al pasear el ratón por
40
+ // el formulario del modal de bloque la fila entera «bailaba» y los
41
+ // bordes finos vecinos parpadeaban (peor aún con zoom/DPI
42
+ // fraccionario). El halo se pinta fuera de la caja y no toca ni
43
+ // layout ni raster de los vecinos.
44
+ // (el seleccionado conserva su anillo: el halo solo aplica sin marcar)
45
+ &:hover:not(#{&}--selected) {
46
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--swatch-color) 40%, transparent);
47
+ }
48
+
49
+ &--custom-idle:hover:not(#{&}--selected) {
50
+ box-shadow: 0 0 0 3px color-mix(in srgb, #3b82f6 40%, transparent);
51
+ }
38
52
 
39
53
  &--selected { box-shadow: 0 0 0 2px $surface, 0 0 0 4px var(--swatch-color); }
40
54
 
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed, onBeforeUnmount, onMounted } from 'vue'
2
+ import { computed, onBeforeUnmount, onMounted, watch } from 'vue'
3
3
  import { Funnel, X } from '@lucide/vue'
4
4
  import { useAppRightSidebar } from '../composables/useAppRightSidebar'
5
5
 
@@ -17,7 +17,11 @@ import { useAppRightSidebar } from '../composables/useAppRightSidebar'
17
17
  // .app-footer sobre la clase `--docked`; la cabecera no lo necesita: la
18
18
  // barra no la tapa); por debajo de OVERLAY_BREAKPOINT es un drawer
19
19
  // superpuesto con telón (también bajo la cabecera, que sigue usable), click
20
- // fuera y Escape. Se abre y se cierra con el ASA anclada a la propia barra
20
+ // fuera y Escape. Con `overlayAlways` el modo drawer vale para TODAS las
21
+ // anchuras: la barra se superpone siempre al contenido (nunca le roba ancho
22
+ // al main) y se abre/cierra igual que el drawer estrecho — para juegos que
23
+ // prefieren no hacer hueco ni en escritorio. Se abre y se cierra con el ASA
24
+ // anclada a la propia barra
21
25
  // (Funnel cerrada / X abierta), visible solo si la vista registró
22
26
  // contenido; el cascarón puede ajustar su altura con
23
27
  // --app-right-sidebar-handle-top (relativa al techo de la barra).
@@ -32,8 +36,19 @@ const props = withDefaults(
32
36
  closeLabel?: string
33
37
  /** Título por defecto si la vista registra sin título. */
34
38
  fallbackTitle?: string
39
+ /**
40
+ * Drawer superpuesto en TODAS las anchuras: nunca "atraca" (docked) ni
41
+ * le hace hueco el cascarón — siempre telón + superposición, como en
42
+ * estrecho. Por defecto, solo por debajo del corte de 900px.
43
+ */
44
+ overlayAlways?: boolean
35
45
  }>(),
36
- { openLabel: 'Abrir el panel', closeLabel: 'Cerrar el panel', fallbackTitle: 'Filtros' },
46
+ {
47
+ openLabel: 'Abrir el panel',
48
+ closeLabel: 'Cerrar el panel',
49
+ fallbackTitle: 'Filtros',
50
+ overlayAlways: false,
51
+ },
37
52
  )
38
53
 
39
54
  const { hasContent, collapsed, mobileOpen, overlay, title, isOpen, toggle, closeMobile } =
@@ -44,10 +59,13 @@ const { hasContent, collapsed, mobileOpen, overlay, title, isOpen, toggle, close
44
59
  const OVERLAY_BREAKPOINT = 900
45
60
 
46
61
  function checkOverlay() {
47
- overlay.value = window.innerWidth < OVERLAY_BREAKPOINT
62
+ overlay.value = props.overlayAlways || window.innerWidth < OVERLAY_BREAKPOINT
48
63
  if (!overlay.value) mobileOpen.value = false
49
64
  }
50
65
 
66
+ // Si el consumidor cambia el modo en caliente, el estado se recalcula.
67
+ watch(() => props.overlayAlways, checkOverlay)
68
+
51
69
  // En el drawer, Escape cierra (el click fuera lo cubre el telón).
52
70
  function onKeydown(e: KeyboardEvent) {
53
71
  if (e.key === 'Escape' && overlay.value && mobileOpen.value) closeMobile()