Popup
<gstock-popup>
|
GstockPopup
Ejemplos
<gstock-popup active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
gstock-popup {
--arrow-color: var(--gstock-color-background-brand-bold);
}
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: dashed 2px var(--gstock-color-border);
margin-block: 50px;
margin-inline: 100px;
}
.box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Activación
Los popups están inactivos y ocultos hasta que se aplica el atributo active. Al eliminar el atributo se desmonta toda la lógica de posicionamiento y los listeners, lo que significa que puedes tener muchos popups inactivos en la página sin afectar el rendimiento.
<gstock-popup active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: dashed 2px var(--gstock-color-border);
margin-block: 50px;
margin-inline: 100px;
}
.box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Anclas externas
Por defecto, las anclas se insertan en el popup usando el slot anchor. Si tu ancla necesita estar fuera del popup, puedes pasar el id del ancla al atributo anchor. Alternativamente, puedes pasar una referencia del elemento a la propiedad anchor para lograr el mismo efecto sin usar un id.
<span id="external-anchor"></span>
<gstock-popup anchor="external-anchor" placement="top" active>
<div class="box"></div>
</gstock-popup>
<style>
#external-anchor {
display: inline-block;
width: 150px;
height: 150px;
border: dashed 2px var(--gstock-color-border);
margin-block: 50px 0;
margin-inline: 100px;
}
#external-anchor ~ gstock-popup .box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Ubicación
Use el atributo placement para indicar al popup la ubicación preferida. Ten en cuenta que la posición real puede variar para asegurar que el panel permanezca en el viewport si estás usando características de posicionamiento como flip y shift.
Dado que la ubicación es preferida cuando se usa flip, puedes observar la ubicación actual del popup cuando está activo mirando el atributo data-current-placement. Este atributo se actualizará cuando el popup se voltee para encontrar espacio disponible y se eliminará cuando el popup se desactive.
<gstock-popup placement="top" active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: dashed 2px var(--gstock-color-border);
margin-block: 50px;
margin-inline: 100px;
}
.box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Distancia
Use el atributo distance para cambiar la distancia entre el popup y su ancla. Un valor positivo alejará más el popup y un valor negativo lo acercará.
<gstock-popup distance="0" active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: dashed 2px var(--gstock-color-border);
margin-block: 50px;
margin-inline: 100px;
}
.box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Desplazamiento lateral
El atributo skidding es similar a distance, pero en su lugar te permite desplazar el popup a lo largo del eje del ancla. Se permiten valores tanto positivos como negativos.
<gstock-popup placement="top" skidding="0" active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: dashed 2px var(--gstock-color-border);
margin-block: 50px;
margin-inline: 100px;
}
.box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Flechas
Añade una flecha a tu popup con el atributo arrow. Generalmente es una buena idea establecer una distance para hacer espacio para la flecha. Para ajustar el color y tamaño de la flecha, usa las propiedades personalizadas --arrow-color y --arrow-size, respectivamente. También puedes seleccionar la parte arrow para añadir estilos adicionales como sombras y bordes.
Por defecto, la flecha se alineará lo más cerca posible del centro del ancla, considerando el espacio disponible y el arrow-padding. Puedes usar el atributo arrow-placement para forzar que la flecha se alinee al inicio, final o centro del popup.
<gstock-popup placement="top" arrow arrow-placement="anchor" distance="8" active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
gstock-popup {
--arrow-color: var(--gstock-color-background-brand-bold);
}
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: dashed 2px var(--gstock-color-border);
margin-block: 50px;
margin-inline: 100px;
}
.box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Sincronización con las dimensiones del ancla
Use el atributo sync para hacer que el popup tenga el mismo ancho o alto que el elemento ancla. Esto es útil para controles que necesitan que el popup mantenga el mismo ancho o alto que el disparador.
<gstock-popup sync="width" active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: dashed 2px var(--gstock-color-border);
margin-block: 150px 0;
margin-inline: 100px;
}
.box {
width: 100%;
height: 100%;
min-width: 50px;
min-height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Estrategia de posicionamiento
Por defecto, el popup se posiciona usando una estrategia de posicionamiento absoluto. Sin embargo, si tu ancla está fija o existe dentro de un contenedor que tiene overflow: auto|hidden, el popup corre el riesgo de ser recortado. Para solucionar esto, puedes usar una estrategia de posicionamiento fijo estableciendo el atributo strategy a fixed.
La estrategia de posicionamiento fijo reduce los saltos cuando el ancla está fija y permite que el popup salga de contenedores que lo recortan. Al usar esta estrategia, es importante tener en cuenta que el contenido se posicionará relativo a su bloque contenedor, que generalmente es el viewport a menos que un ancestro use transform, perspective o filter. Consulta esta página para más detalles.
En este ejemplo, puedes ver cómo el popup sale del contenedor con overflow cuando está fijo. La estrategia de posicionamiento fijo tiende a ser menos eficiente que absoluta, así que evita usarla innecesariamente.
Activa el interruptor y desplaza el contenedor para ver la diferencia.
<gstock-popup placement="top" strategy="fixed" active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
.preview__canvas {
position: relative;
height: 300px;
overflow: auto;
}
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: 2px dashed var(--gstock-color-border);
margin-block: 200px 100px;
margin-inline: 100px;
}
.box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Volteo automático
Cuando el popup no tiene suficiente espacio en su ubicación preferida, puede voltearse automáticamente para mantenerse visible. Para habilitar esto, usa el atributo flip. Por defecto, el popup se volteará a la ubicación opuesta, pero puedes configurar ubicaciones de respaldo preferidas usando flip-fallback-placement y flip-fallback-strategy. Hay opciones adicionales disponibles para controlar el límite y el padding del comportamiento de volteo.
Desplaza el contenedor para ver cómo el popup se voltea para evitar el recorte.
<gstock-popup placement="top" flip active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
.preview__canvas {
position: relative;
height: 300px;
overflow: auto;
}
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: 2px dashed var(--gstock-color-border);
margin-block: 200px 100px;
margin-inline: 100px;
}
.box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Ubicaciones de respaldo para el volteo
Al usar el atributo flip, puedes personalizar la ubicación del popup cuando la ubicación preferida no tiene espacio. Para esto, usa flip-fallback-placements y flip-fallback-strategy.
Si la ubicación preferida no tiene espacio, se usará la primera ubicación adecuada encontrada en flip-fallback-placement. El valor de este atributo debe ser una cadena que incluya cualquier número de ubicaciones separadas por un espacio, por ejemplo "right bottom".
Si ninguna ubicación de respaldo funciona, la ubicación final será determinada por flip-fallback-strategy. Este valor puede ser initial (por defecto), donde la ubicación vuelve a la posición en placement, o best-fit, donde la ubicación se elige basándose en el espacio disponible.
Desplaza el contenedor para ver cómo el popup cambia su ubicación de respaldo para evitar el recorte.
<gstock-popup placement="top" flip flip-fallback-placements="right bottom" flip-fallback-strategy="initial" active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
.preview__canvas {
position: relative;
height: 300px;
overflow: auto;
}
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: 2px dashed var(--gstock-color-border);
margin-block: 200px 100px;
margin-inline: 100px;
}
.box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Desplazamiento
Cuando un popup es más largo que su ancla, corre el riesgo de ser recortado por un contenedor con overflow. En este caso, usa el atributo shift para desplazar el popup a lo largo de su eje y volver a la vista. Puedes personalizar el comportamiento de desplazamiento usando shiftBoundary y shift-padding.
Activa el interruptor para ver la diferencia.
<gstock-popup placement="top" shift shift-padding="10" active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
.preview__canvas {
position: relative;
overflow: auto;
}
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: 2px dashed var(--gstock-color-border);
margin-block: 50px;
margin-inline: 100px;
}
.box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Tamaño automático
Use el atributo auto-size para indicar al popup que se redimensione cuando sea necesario para evitar que sea recortado. Los valores posibles son horizontal, vertical y both. Puedes usar autoSizeBoundary y auto-size-padding para personalizar el comportamiento de esta opción. El tamaño automático funciona bien con flip, pero si estás usando auto-size-padding asegúrate de que flip-padding tenga el mismo valor.
Cuando se usa auto-size, se aplicará una o ambas de --auto-size-available-width y --auto-size-available-height al elemento host. Estos valores determinan el espacio disponible que tiene el popover antes de que ocurra el recorte. Como se propagan en cascada, puedes usarlos para establecer un max-width/height en el contenido de tu popup y controlar fácilmente su overflow.
Desplaza el contenedor para ver cómo el popup se redimensiona cuando su espacio disponible cambia.
<gstock-popup placement="top" auto-size="both" auto-size-padding="10" active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
.preview__canvas {
position: relative;
height: 300px;
overflow: auto;
}
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: dashed 2px var(--gstock-color-border);
margin-block: 250px 100px;
margin-inline: 100px;
}
.box {
/* This sets the preferred size of the popup's content */
width: 100px;
height: 200px;
/* This sets the maximum dimensions and allows scrolling when auto-size kicks in */
max-width: var(--auto-size-available-width);
max-height: var(--auto-size-available-height);
overflow: auto;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
</style>
Puente de hover
Cuando existe un espacio entre el ancla y el elemento popup, esta opción añadirá un “puente de hover” que llena el espacio usando un elemento invisible. Esto hace que escuchar eventos como mouseover y mouseout sea más sensato porque el puntero técnicamente nunca abandona el elemento. El puente de hover solo se dibujará cuando el popover esté activo. Con fines de demostración, el puente en este ejemplo se muestra en magenta.
<gstock-popup hover-bridge distance="10" active>
<span slot="anchor"></span>
<div class="box"></div>
</gstock-popup>
<style>
span[slot='anchor'] {
display: inline-block;
width: 150px;
height: 150px;
border: dashed 2px var(--gstock-color-border);
margin-block: 100px 0;
margin-inline: 100px;
}
.box {
width: 100px;
height: 50px;
background: var(--gstock-color-background-brand-bold);
border-radius: var(--gstock-border-radius-sm);
}
gstock-popup::part(hover-bridge) {
background: magenta;
opacity: 0.5;
}
</style>
Elementos virtuales
En la mayoría de los casos, los popups están anclados a un elemento real. A veces, puede ser útil anclarlos a un no-elemento. Para hacer esto, puedes pasar un VirtualElement a la propiedad anchor. Un elemento virtual debe contener una función llamada getBoundingClientRect() que devuelva un objeto DOMRect como se muestra a continuación.
const virtualElement = {
getBoundingClientRect() {
// ...
return { width, height, x, y, top, left, right, bottom };
},
};
Este ejemplo ancla un popup al cursor del ratón usando un elemento virtual. Como tal, se requiere un ratón para verlo correctamente.
<gstock-popup placement="right-start">
<div class="circle"></div>
</gstock-popup>
<gstock-switch size="small">Highlight mouse cursor</gstock-switch>
<script type="module">
const popup = document.querySelector('gstock-popup');
const circle = document.querySelector('.circle');
const enabled = document.querySelector('gstock-switch');
let clientX = 0;
let clientY = 0;
popup.anchor = {
getBoundingClientRect() {
return {
width: 0,
height: 0,
x: clientX,
y: clientY,
top: clientY,
left: clientX,
right: clientX,
bottom: clientY,
};
},
};
enabled.addEventListener('gstock-change-event', () => {
popup.active = enabled.checked;
});
document.addEventListener('mousemove', event => {
clientX = event.clientX;
clientY = event.clientY;
if (popup.active) {
popup.reposition();
}
});
</script>
<style>
gstock-popup::part(popup) {
z-index: 1000;
pointer-events: none;
}
.circle {
width: 100px;
height: 100px;
border: solid 4px var(--gstock-color-border);
border-radius: var(--gstock-border-radius-full);
translate: -50px -50px;
animation: 1s virtual-cursor infinite;
}
@keyframes virtual-cursor {
0% {
scale: 1;
}
50% {
scale: 1.1;
}
}
</style>
A veces el getBoundingClientRects puede derivarse de un elemento real. En este caso, proporciona el elemento ancla como contexto para asegurar que el recorte y las actualizaciones de posición del popup funcionen bien.
const virtualElement = {
getBoundingClientRect() {
// ...
return { width, height, x, y, top, left, right, bottom };
},
contextElement: anchorElement,
};