Crea una vez. Publica donde quieras.
Piezas accesibles que encajan en cualquier producto.
Carrusel de diapositivas con gestos táctiles y controles anterior y siguiente.
Recorre las historias con las flechas o elige una diapositiva con los puntos.
Piezas accesibles que encajan en cualquier producto.
Patrones claros, compuestos por piezas pequeñas y confiables.
Interfaces útiles y listas para el teclado antes de cargar JavaScript.
Piezas accesibles que encajan en cualquier producto.
Patrones claros, compuestos por piezas pequeñas y confiables.
Interfaces útiles y listas para el teclado antes de cargar JavaScript.
Piezas accesibles que encajan en cualquier producto.
Patrones claros, compuestos por piezas pequeñas y confiables.
Interfaces útiles y listas para el teclado antes de cargar JavaScript.
Piezas accesibles que encajan en cualquier producto.
Patrones claros, compuestos por piezas pequeñas y confiables.
Interfaces útiles y listas para el teclado antes de cargar JavaScript.
Piezas accesibles que encajan en cualquier producto.
Patrones claros, compuestos por piezas pequeñas y confiables.
Interfaces útiles y listas para el teclado antes de cargar JavaScript.
Piezas accesibles que encajan en cualquier producto.
Patrones claros, compuestos por piezas pequeñas y confiables.
Interfaces útiles y listas para el teclado antes de cargar JavaScript.
El foco detiene la rotación hasta presionar Iniciar. Pasar el puntero la pausa temporalmente.
Piezas accesibles que encajan en cualquier producto.
Patrones claros, compuestos por piezas pequeñas y confiables.
Interfaces útiles y listas para el teclado antes de cargar JavaScript.
Piezas accesibles que encajan en cualquier producto.
Patrones claros, compuestos por piezas pequeñas y confiables.
Interfaces útiles y listas para el teclado antes de cargar JavaScript.
Piezas accesibles que encajan en cualquier producto.
Patrones claros, compuestos por piezas pequeñas y confiables.
Interfaces útiles y listas para el teclado antes de cargar JavaScript.
"use client";
import { CarouselClient } from "@gunkin/uiify/components/carousel/client";
const items = ["One", "Two", "Three"].map((label) => ({
id: label,
label,
className: "",
children: <div className="">{label}</div>,
}));
export default function Example() {
return <CarouselClient id="featured" aria-label="Featured cards" className="" items={items} />;
}/* Optional carousel skin. The native scrollbar is only hidden once real controls replace it. */
@layer components {
[data-uiify-carousel] {
position: relative;
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: var(--space-sm);
inline-size: 100%;
max-inline-size: 40rem;
}
/* Full-width rows: an optional rotation button, the viewport, and the status text. */
[data-uiify-carousel] > [data-part="viewport"],
[data-uiify-carousel] > [data-part="status"],
[data-uiify-carousel] > button[data-part="controls"][data-carousel-action="rotation"] {
grid-column: 1 / -1;
}
/*
* Hide the scrollbar only once the carousel is attached AND renders buttons that can
* take over from it. Without scripting the scrollbar is the sole indication that the
* content scrolls at all, so the static carousel keeps it. `scrollbar-width` alone is
* enough for the supported engines — no prefixed fallback.
*/
[data-uiify-carousel][data-enhanced]:has(> button[data-part="controls"])
> [data-part="viewport"] {
scrollbar-width: none;
}
[data-uiify-carousel]
> [data-part="viewport"]
> [data-part="slide"]
> [data-part="slide-content"] {
display: flex;
container-type: inline-size;
min-block-size: 18rem;
aspect-ratio: 1;
align-items: center;
justify-content: center;
border: var(--border-width) solid var(--border);
border-radius: var(--radius-xl);
corner-shape: squircle;
background-color: var(--card);
color: var(--foreground);
font-size: 2.25rem;
font-weight: var(--weight-semibold);
line-height: 1;
box-shadow: var(--shadow-popover);
}
/* The controls are Button-skinned (`outline`; previous/next at the icon size). */
[data-uiify-carousel] > button[data-part="controls"][data-carousel-action="rotation"] {
justify-self: start;
margin-block-end: var(--space-sm);
}
[data-uiify-carousel] > button[data-part="controls"][data-carousel-action="previous"],
[data-uiify-carousel] > button[data-part="controls"][data-carousel-action="next"] {
font-size: 1.25rem;
line-height: 1;
}
[data-uiify-carousel] > [data-part="dots"] > a:focus-visible {
outline: none;
box-shadow: 0 0 0 var(--ring-width) color-mix(in oklch, var(--ring) 16%, transparent);
}
[data-uiify-carousel] > [data-part="dots"] {
/* Explicit middle column: pagination stays centred whether or not the
previous/next buttons exist to occupy the outer columns. */
grid-column: 2;
justify-self: stretch;
display: flex;
justify-content: center;
gap: var(--space-xs);
}
[data-uiify-carousel] > [data-part="dots"] > a {
display: inline-grid;
place-items: center;
inline-size: 2.75rem;
block-size: 2.75rem;
border-radius: var(--radius-full);
background-color: transparent;
color: var(--muted-foreground);
text-decoration: none;
transition: var(--transition-colors);
font-size: 0;
}
[data-uiify-carousel] > [data-part="dots"] > a::after {
content: "";
inline-size: 0.5rem;
block-size: 0.5rem;
border-radius: 50%;
background: var(--input);
}
[data-uiify-carousel] > [data-part="dots"] > a[aria-current="true"]::after {
background: var(--primary);
}
}
@layer components {
[data-uiify-carousel] [data-part="story"] {
display: grid;
grid-template-rows: auto 1fr auto;
inline-size: 100%;
block-size: 100%;
min-inline-size: 0;
min-block-size: 0;
padding: clamp(0.875rem, 4cqi, 1.5rem);
text-align: start;
}
[data-uiify-carousel] [data-part="story-topline"],
[data-uiify-carousel] [data-part="story-footer"] {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 0.5rem;
color: var(--muted-foreground);
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
font-size: 0.75rem;
font-weight: 500;
letter-spacing: 0.08em;
}
[data-uiify-carousel] [data-part="story-body"] {
display: grid;
align-content: center;
gap: 0.75rem;
min-inline-size: 0;
padding-block: 1rem;
}
[data-uiify-carousel] [data-part="story-eyebrow"] {
color: var(--primary);
font-size: 0.75rem;
font-weight: 600;
letter-spacing: 0.1em;
}
[data-uiify-carousel] [data-part="story-body"] > h3 {
max-inline-size: 12ch;
margin: 0;
color: var(--foreground);
font-size: clamp(1.25rem, 6cqi, 2rem);
font-weight: 600;
letter-spacing: -0.045em;
line-height: 1.08;
white-space: pre-line;
}
[data-uiify-carousel] [data-part="story-body"] > p {
max-inline-size: 30ch;
margin: 0;
color: var(--muted-foreground);
font-size: 0.875rem;
line-height: 1.55;
}
}"use client";
import { CarouselClient } from "@gunkin/uiify/components/carousel/client";
const items = ["One", "Two", "Three"].map((label) => ({
id: label,
label,
className: "",
children: <div className="">{label}</div>,
}));
export default function Example() {
return (
<CarouselClient
id="featured"
aria-label="Featured cards"
className={
"relative grid [grid-template-columns:auto_1fr_auto] items-center gap-sm [inline-size:100%] [max-inline-size" +
":40rem] [&>button[data-part=controls]]:relative [&>button[data-part=controls]]:isolate [&>button[data-part=" +
"controls]]:inline-flex [&>button[data-part=controls]]:items-center [&>button[data-part=controls]]:justify-c" +
"enter [&>button[data-part=controls][hidden]]:hidden [&>button[data-part=controls]]:min-h-11 [&>button[data-" +
"part=controls]]:min-w-11 [&>button[data-part=controls]]:gap-1.5 [&>button[data-part=controls]]:px-5 [&>butt" +
"on[data-part=controls]]:py-0 [&>button[data-part=controls]]:border-[length:var(--border-width)] [&>button[d" +
"ata-part=controls]]:border-solid [&>button[data-part=controls]]:[border-color:color-mix(in_oklch,_var(--for" +
"eground)_20%,_transparent)] [&>button[data-part=controls]]:rounded-full [&>button[data-part=controls]]:bg-t" +
"ransparent [&>button[data-part=controls]]:bg-clip-padding [&>button[data-part=controls]]:text-foreground [&" +
">button[data-part=controls]]:font-medium [&>button[data-part=controls]]:text-base [&>button[data-part=contr" +
"ols]]:leading-6 [&>button[data-part=controls]]:[font-family:inherit] [&>button[data-part=controls]]:no-unde" +
"rline [&>button[data-part=controls]]:cursor-pointer [&>button[data-part=controls]]:[transition:var(--transi" +
"tion-colors)] [&>button[data-part=controls]]:disabled:opacity-50 [&>button[data-part=controls]]:disabled:cu" +
"rsor-not-allowed [&>button[data-part=controls]]:focus-visible:outline-none [&>button[data-part=controls]]:f" +
"ocus-visible:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_transparent)] [@media" +
"_(any-hover:_hover)_and_(any-pointer:_fine)]:[&>button[data-part=controls]:hover:not(:disabled)]:[backgroun" +
"d-color:color-mix(in_oklch,_var(--foreground)_10%,_transparent)] [&>button[data-part=controls]:active:not(:" +
"disabled)]:[background-color:color-mix(in_oklch,_var(--foreground)_16%,_transparent)] [&>button[data-part=c" +
"ontrols]]:before:content-none [&>button[data-part=controls]]:after:content-[''] [&>button[data-part=control" +
"s]]:after:absolute [&>button[data-part=controls]]:after:[inset:calc(-1_*_var(--border-width))] [&>button[da" +
"ta-part=controls]]:after:z-[-1] [&>button[data-part=controls]]:after:rounded-[inherit] [&>button[data-part=" +
"controls]]:after:pointer-events-none [&>button[data-part=controls]]:after:[padding:var(--border-width)] [&>" +
"button[data-part=controls]]:after:[background-image:linear-gradient(to_bottom,_color-mix(in_oklch,_var(--fo" +
"reground)_25%,_transparent),_transparent_75%)] [&>button[data-part=controls]]:after:[mask:linear-gradient(#" +
"fff_0_0)_content-box_exclude,_linear-gradient(#fff_0_0)] [&>[data-part=viewport]]:[grid-column:1_/_-1] [&>[" +
"data-part=status]]:[grid-column:1_/_-1] [&>button[data-part=controls][data-carousel-action=rotation]]:[grid" +
"-column:1_/_-1] data-[enhanced]:[&:has(>button[data-part=controls])>[data-part=viewport]]:[scrollbar-width:" +
"none] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:flex [&>[data-part=viewport]>[da" +
"ta-part=slide]>[data-part=slide-content]]:[container-type:inline-size] [&>[data-part=viewport]>[data-part=s" +
"lide]>[data-part=slide-content]]:[min-block-size:18rem] [&>[data-part=viewport]>[data-part=slide]>[data-par" +
"t=slide-content]]:[aspect-ratio:1] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:ite" +
"ms-center [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:justify-center [&>[data-part" +
"=viewport]>[data-part=slide]>[data-part=slide-content]]:border-[length:var(--border-width)] [&>[data-part=v" +
"iewport]>[data-part=slide]>[data-part=slide-content]]:border-solid [&>[data-part=viewport]>[data-part=slide" +
"]>[data-part=slide-content]]:border-border [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-conte" +
"nt]]:rounded-xl [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[corner-shape:squircle" +
"] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:bg-card [&>[data-part=viewport]>[dat" +
"a-part=slide]>[data-part=slide-content]]:text-foreground [&>[data-part=viewport]>[data-part=slide]>[data-pa" +
"rt=slide-content]]:[font-size:2.25rem] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]" +
":font-[number:var(--weight-semibold)] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:" +
"leading-none [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:shadow-popover [&>button[" +
"data-part=controls][data-carousel-action=rotation]]:[justify-self:start] [&>button[data-part=controls][data" +
"-carousel-action=rotation]]:[margin-block-end:var(--space-sm)] [&>button[data-part=controls][data-carousel-" +
"action=previous]]:[font-size:1.25rem] [&>button[data-part=controls][data-carousel-action=previous]]:leading" +
"-none [&>button[data-part=controls][data-carousel-action=next]]:[font-size:1.25rem] [&>button[data-part=con" +
"trols][data-carousel-action=next]]:leading-none [&>[data-part=dots]>a:focus-visible]:[outline:none] [&>[dat" +
"a-part=dots]>a:focus-visible]:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_tran" +
"sparent)] [&>[data-part=dots]]:[grid-column:2] [&>[data-part=dots]]:[justify-self:stretch] [&>[data-part=do" +
"ts]]:flex [&>[data-part=dots]]:justify-center [&>[data-part=dots]]:gap-xs [&>[data-part=dots]>a]:inline-gri" +
"d [&>[data-part=dots]>a]:place-items-center [&>[data-part=dots]>a]:[inline-size:2.75rem] [&>[data-part=dots" +
"]>a]:[block-size:2.75rem] [&>[data-part=dots]>a]:rounded-[var(--radius-full)] [&>[data-part=dots]>a]:bg-tra" +
"nsparent [&>[data-part=dots]>a]:text-muted-foreground [&>[data-part=dots]>a]:no-underline [&>[data-part=dot" +
"s]>a]:[transition:var(--transition-colors)] [&>[data-part=dots]>a]:[font-size:0] [&>[data-part=dots]>a::aft" +
"er]:content-[''] [&>[data-part=dots]>a::after]:[inline-size:0.5rem] [&>[data-part=dots]>a::after]:[block-si" +
"ze:0.5rem] [&>[data-part=dots]>a::after]:rounded-[50%] [&>[data-part=dots]>a::after]:bg-input [&>[data-part" +
"=dots]>a[aria-current=true]::after]:bg-primary [&_[data-part=story]]:grid [&_[data-part=story]]:[grid-templ" +
"ate-rows:auto_1fr_auto] [&_[data-part=story]]:[inline-size:100%] [&_[data-part=story]]:[block-size:100%] [&" +
"_[data-part=story]]:[min-inline-size:0] [&_[data-part=story]]:[min-block-size:0] [&_[data-part=story]]:[pad" +
"ding:clamp(0.875rem,_4cqi,_1.5rem)] [&_[data-part=story]]:text-start [&_[data-part=story-topline]]:flex [&_" +
"[data-part=story-topline]]:items-center [&_[data-part=story-topline]]:justify-between [&_[data-part=story-t" +
"opline]]:flex-wrap [&_[data-part=story-topline]]:[gap:0.5rem] [&_[data-part=story-topline]]:text-muted-fore" +
"ground [&_[data-part=story-topline]]:[font-family:ui-monospace,_\"SF_Mono\",_Menlo,_Consolas,_monospace] [&_[" +
"data-part=story-topline]]:[font-size:0.75rem] [&_[data-part=story-topline]]:[font-weight:500] [&_[data-part" +
"=story-topline]]:[letter-spacing:0.08em] [&_[data-part=story-footer]]:flex [&_[data-part=story-footer]]:ite" +
"ms-center [&_[data-part=story-footer]]:justify-between [&_[data-part=story-footer]]:flex-wrap [&_[data-part" +
"=story-footer]]:[gap:0.5rem] [&_[data-part=story-footer]]:text-muted-foreground [&_[data-part=story-footer]" +
"]:[font-family:ui-monospace,_\"SF_Mono\",_Menlo,_Consolas,_monospace] [&_[data-part=story-footer]]:[font-size" +
":0.75rem] [&_[data-part=story-footer]]:[font-weight:500] [&_[data-part=story-footer]]:[letter-spacing:0.08e" +
"m] [&_[data-part=story-body]]:grid [&_[data-part=story-body]]:[align-content:center] [&_[data-part=story-bo" +
"dy]]:[gap:0.75rem] [&_[data-part=story-body]]:[min-inline-size:0] [&_[data-part=story-body]]:[padding-block" +
":1rem] [&_[data-part=story-eyebrow]]:text-primary [&_[data-part=story-eyebrow]]:[font-size:0.75rem] [&_[dat" +
"a-part=story-eyebrow]]:[font-weight:600] [&_[data-part=story-eyebrow]]:[letter-spacing:0.1em] [&_[data-part" +
"=story-body]>h3]:[max-inline-size:12ch] [&_[data-part=story-body]>h3]:m-0 [&_[data-part=story-body]>h3]:tex" +
"t-foreground [&_[data-part=story-body]>h3]:[font-size:clamp(1.25rem,_6cqi,_2rem)] [&_[data-part=story-body]" +
">h3]:[font-weight:600] [&_[data-part=story-body]>h3]:[letter-spacing:-0.045em] [&_[data-part=story-body]>h3" +
"]:[line-height:1.08] [&_[data-part=story-body]>h3]:[white-space:pre-line] [&_[data-part=story-body]>p]:[max" +
"-inline-size:30ch] [&_[data-part=story-body]>p]:m-0 [&_[data-part=story-body]>p]:text-muted-foreground [&_[" +
"data-part=story-body]>p]:[font-size:0.875rem] [&_[data-part=story-body]>p]:[line-height:1.55]"
}
items={items}
/>
);
}/* app.css */
@layer reset, ui, app, tokens, base, demo, components, utilities, theme;
@import "@gunkin/uiify/styles/reset";
@import "@gunkin/uiify/components/behavior.css";
@import "@gunkin/uiify/styles/tokens";
@import "@gunkin/uiify/styles/tailwind";
@import "tailwindcss/utilities.css";
@theme { --spacing: 0.25rem; --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; }
@source inline('relative grid [grid-template-columns:auto_1fr_auto] items-center gap-sm [inline-size:100%] [max-inline-size:40rem] [&>button[data-part=controls]]:relative [&>button[data-part=controls]]:isolate [&>button[data-part=controls]]:inline-flex [&>button[data-part=controls]]:items-center [&>button[data-part=controls]]:justify-center [&>button[data-part=controls][hidden]]:hidden [&>button[data-part=controls]]:min-h-11 [&>button[data-part=controls]]:min-w-11 [&>button[data-part=controls]]:gap-1.5 [&>button[data-part=controls]]:px-5 [&>button[data-part=controls]]:py-0 [&>button[data-part=controls]]:border-[length:var(--border-width)] [&>button[data-part=controls]]:border-solid [&>button[data-part=controls]]:[border-color:color-mix(in_oklch,_var(--foreground)_20%,_transparent)] [&>button[data-part=controls]]:rounded-full [&>button[data-part=controls]]:bg-transparent [&>button[data-part=controls]]:bg-clip-padding [&>button[data-part=controls]]:text-foreground [&>button[data-part=controls]]:font-medium [&>button[data-part=controls]]:text-base [&>button[data-part=controls]]:leading-6 [&>button[data-part=controls]]:[font-family:inherit] [&>button[data-part=controls]]:no-underline [&>button[data-part=controls]]:cursor-pointer [&>button[data-part=controls]]:[transition:var(--transition-colors)] [&>button[data-part=controls]]:disabled:opacity-50 [&>button[data-part=controls]]:disabled:cursor-not-allowed [&>button[data-part=controls]]:focus-visible:outline-none [&>button[data-part=controls]]:focus-visible:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_transparent)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[&>button[data-part=controls]:hover:not(:disabled)]:[background-color:color-mix(in_oklch,_var(--foreground)_10%,_transparent)] [&>button[data-part=controls]:active:not(:disabled)]:[background-color:color-mix(in_oklch,_var(--foreground)_16%,_transparent)] [&>button[data-part=controls]]:before:content-none [&>button[data-part=controls]]:after:absolute [&>button[data-part=controls]]:after:[inset:calc(-1_*_var(--border-width))] [&>button[data-part=controls]]:after:z-[-1] [&>button[data-part=controls]]:after:rounded-[inherit] [&>button[data-part=controls]]:after:pointer-events-none [&>button[data-part=controls]]:after:[padding:var(--border-width)] [&>button[data-part=controls]]:after:[background-image:linear-gradient(to_bottom,_color-mix(in_oklch,_var(--foreground)_25%,_transparent),_transparent_75%)] [&>button[data-part=controls]]:after:[mask:linear-gradient(#fff_0_0)_content-box_exclude,_linear-gradient(#fff_0_0)] [&>[data-part=viewport]]:[grid-column:1_/_-1] [&>[data-part=status]]:[grid-column:1_/_-1] [&>button[data-part=controls][data-carousel-action=rotation]]:[grid-column:1_/_-1] data-[enhanced]:[&:has(>button[data-part=controls])>[data-part=viewport]]:[scrollbar-width:none] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:flex [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[container-type:inline-size] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[min-block-size:18rem] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[aspect-ratio:1] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:items-center [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:justify-center [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:border-[length:var(--border-width)] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:border-solid [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:border-border [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:rounded-xl [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[corner-shape:squircle] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:bg-card [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:text-foreground [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[font-size:2.25rem] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:font-[number:var(--weight-semibold)] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:leading-none [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:shadow-popover [&>button[data-part=controls][data-carousel-action=rotation]]:[justify-self:start] [&>button[data-part=controls][data-carousel-action=rotation]]:[margin-block-end:var(--space-sm)] [&>button[data-part=controls][data-carousel-action=previous]]:[font-size:1.25rem] [&>button[data-part=controls][data-carousel-action=previous]]:leading-none [&>button[data-part=controls][data-carousel-action=next]]:[font-size:1.25rem] [&>button[data-part=controls][data-carousel-action=next]]:leading-none [&>[data-part=dots]>a:focus-visible]:[outline:none] [&>[data-part=dots]>a:focus-visible]:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_transparent)] [&>[data-part=dots]]:[grid-column:2] [&>[data-part=dots]]:[justify-self:stretch] [&>[data-part=dots]]:flex [&>[data-part=dots]]:justify-center [&>[data-part=dots]]:gap-xs [&>[data-part=dots]>a]:inline-grid [&>[data-part=dots]>a]:place-items-center [&>[data-part=dots]>a]:[inline-size:2.75rem] [&>[data-part=dots]>a]:[block-size:2.75rem] [&>[data-part=dots]>a]:rounded-[var(--radius-full)] [&>[data-part=dots]>a]:bg-transparent [&>[data-part=dots]>a]:text-muted-foreground [&>[data-part=dots]>a]:no-underline [&>[data-part=dots]>a]:[transition:var(--transition-colors)] [&>[data-part=dots]>a]:[font-size:0] [&>[data-part=dots]>a::after]:[inline-size:0.5rem] [&>[data-part=dots]>a::after]:[block-size:0.5rem] [&>[data-part=dots]>a::after]:rounded-[50%] [&>[data-part=dots]>a::after]:bg-input [&>[data-part=dots]>a[aria-current=true]::after]:bg-primary [&_[data-part=story]]:grid [&_[data-part=story]]:[grid-template-rows:auto_1fr_auto] [&_[data-part=story]]:[inline-size:100%] [&_[data-part=story]]:[block-size:100%] [&_[data-part=story]]:[min-inline-size:0] [&_[data-part=story]]:[min-block-size:0] [&_[data-part=story]]:[padding:clamp(0.875rem,_4cqi,_1.5rem)] [&_[data-part=story]]:text-start [&_[data-part=story-topline]]:flex [&_[data-part=story-topline]]:items-center [&_[data-part=story-topline]]:justify-between [&_[data-part=story-topline]]:flex-wrap [&_[data-part=story-topline]]:[gap:0.5rem] [&_[data-part=story-topline]]:text-muted-foreground [&_[data-part=story-topline]]:[font-family:ui-monospace,_"SF_Mono",_Menlo,_Consolas,_monospace] [&_[data-part=story-topline]]:[font-size:0.75rem] [&_[data-part=story-topline]]:[font-weight:500] [&_[data-part=story-topline]]:[letter-spacing:0.08em] [&_[data-part=story-footer]]:flex [&_[data-part=story-footer]]:items-center [&_[data-part=story-footer]]:justify-between [&_[data-part=story-footer]]:flex-wrap [&_[data-part=story-footer]]:[gap:0.5rem] [&_[data-part=story-footer]]:text-muted-foreground [&_[data-part=story-footer]]:[font-family:ui-monospace,_"SF_Mono",_Menlo,_Consolas,_monospace] [&_[data-part=story-footer]]:[font-size:0.75rem] [&_[data-part=story-footer]]:[font-weight:500] [&_[data-part=story-footer]]:[letter-spacing:0.08em] [&_[data-part=story-body]]:grid [&_[data-part=story-body]]:[align-content:center] [&_[data-part=story-body]]:[gap:0.75rem] [&_[data-part=story-body]]:[min-inline-size:0] [&_[data-part=story-body]]:[padding-block:1rem] [&_[data-part=story-eyebrow]]:text-primary [&_[data-part=story-eyebrow]]:[font-size:0.75rem] [&_[data-part=story-eyebrow]]:[font-weight:600] [&_[data-part=story-eyebrow]]:[letter-spacing:0.1em] [&_[data-part=story-body]>h3]:[max-inline-size:12ch] [&_[data-part=story-body]>h3]:m-0 [&_[data-part=story-body]>h3]:text-foreground [&_[data-part=story-body]>h3]:[font-size:clamp(1.25rem,_6cqi,_2rem)] [&_[data-part=story-body]>h3]:[font-weight:600] [&_[data-part=story-body]>h3]:[letter-spacing:-0.045em] [&_[data-part=story-body]>h3]:[line-height:1.08] [&_[data-part=story-body]>h3]:[white-space:pre-line] [&_[data-part=story-body]>p]:[max-inline-size:30ch] [&_[data-part=story-body]>p]:m-0 [&_[data-part=story-body]>p]:text-muted-foreground [&_[data-part=story-body]>p]:[font-size:0.875rem] [&_[data-part=story-body]>p]:[line-height:1.55]');
@source inline("[&>button[data-part=controls]]:after:content-[''] [&>[data-part=dots]>a::after]:content-['']");
@layer base { :root { --uiify-control-text: var(--text-sm); } @media (pointer: coarse) { :root { --uiify-control-text: var(--text-base); } } }
/* Authored animation and registered properties used by the Tailwind skin.
* Visual rules belong in utility recipes; only at-rule definitions live here. */
@layer components {
@keyframes uiify-presence-in {
from {
opacity: 0;
scale: var(--presence-scale);
}
}
}
@layer components {
@keyframes uiify-presence-out {
to {
opacity: 0;
scale: var(--presence-scale);
}
}
}
@property --uiify-spinner-tail {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
@property --uiify-spinner-length {
syntax: "<angle>";
inherits: false;
initial-value: 36deg;
}
@layer components {
@keyframes uiify-spinner-rotate {
to {
transform: rotate(360deg);
}
}
}
@layer components {
@keyframes uiify-spinner-orbit {
0% {
--uiify-spinner-tail: 0deg;
--uiify-spinner-length: 36deg;
}
50% {
--uiify-spinner-tail: 90deg;
--uiify-spinner-length: 324deg;
}
100% {
--uiify-spinner-tail: 360deg;
--uiify-spinner-length: 36deg;
}
}
}
@layer components {
@keyframes uiify-skeleton-pulse {
50% {
opacity: 0.45;
}
}
}
@layer components {
@keyframes uiify-skeleton-shimmer {
to {
background-position: -200% 0;
}
}
}
@layer components {
@keyframes uiify-skeleton-reveal {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}
@property --candle-body-height {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-body-top {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --candle-slot {
syntax: "<percentage>";
inherits: true;
initial-value: 100%;
}
@property --candle-wick-height {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-wick-top {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --candle-x {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-scale {
syntax: "<number>";
inherits: true;
initial-value: 1;
}
@property --line-y {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --line-prev-y {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --line-count {
syntax: "<integer>";
inherits: false;
initial-value: 1;
}
@property --line-scale {
syntax: "<number>";
inherits: true;
initial-value: 1;
}
@layer components {
@keyframes uiify-otp-input-caret-blink {
50% {
opacity: 0;
}
}
}Carousel| Prop | Tipo | Predeterminado | Descripción |
|---|---|---|---|
id* | string | — | Id único de la raíz; se usa para derivar destinos de fragmento estables. |
items* | readonly CarouselItem[] | — | Elementos con id estable, etiqueta accesible y children. Si está vacío, renderiza null. |
aria-label* | string | — | Nombre accesible del carrusel. |
axis | "inline" | "block" | "inline" | Eje lógico de desplazamiento. Block necesita un block-size definido para el área visible. |
dir | "ltr" | "rtl" | — | Dirección del texto y de la progresión en línea. |
navigation | boolean | true | Renderiza los botones persistentes anterior/siguiente en modo cliente. |
pagination | boolean | true | Enlaces directos a fragmentos. El estado actual solo se expone tras conectar el cliente. |
labels | Partial<CarouselLabels> | — | Traduce previous, next, goTo, navigation, start, stop y of. |
icons | CarouselIcons | — | Contenido visible de los botones anterior/siguiente, vacíos de forma predeterminada. Pasa un glifo, un ícono o una palabra; las etiquetas siguen dándoles nombre. |
className | string | — | Clase de la raíz. Aplica estilos a las partes con nombre mediante selectores [data-part]. |
style | CarouselStyle | — | Valores CSS, incluidos el tamaño de diapositiva, la separación y la duración del fundido. |
CarouselClient — @gunkin/uiify/components/carousel/client| Prop | Tipo | Predeterminado | Descripción |
|---|---|---|---|
defaultValue / value | number | — | Índice de elemento inicial o controlado; el estado observado al terminar el movimiento determina los controles. |
rewind | boolean | false | Vuelve al otro extremo al llegar al final, sin clonar diapositivas. |
mouseDrag | boolean | false | Arrastre con mouse opcional. El tacto y la rueda siguen siendo nativos. |
autoplay | boolean | CarouselAutoplayOptions | false | La espera predeterminada es 5000ms. Opciones: delay, paused, cycles y stopOnInteraction. Incluye controles visibles para detener e iniciar. |
onSelect / beforeChange / afterChange / onSwipe | callbacks | — | Informa los cambios reales al terminar el movimiento y sus motivos; consulta la guía de Carousel para la semántica del control y de los movimientos interrumpidos. |
ref | Ref<CarouselClientHandle> | — | next, previous, goTo, start, stop y reset. |
FadeCarouselClient — @gunkin/uiify/components/carousel/fade| Prop | Tipo | Predeterminado | Descripción |
|---|---|---|---|
swipe | boolean | true | Deslizamiento táctil o con lápiz; el mouse requiere mouseDrag. Hereda las props de cliente salvo axis. Las diapositivas inactivas son inertes. |
| Tecla | Acción |
|---|---|
| Tab / Enter | Dar el foco y seguir enlaces nativos de diapositivas; los botones mejorados también se activan con Space |
| Arrow keys | Usar el desplazamiento nativo mientras el área visible tiene el foco |
El Carousel base es un componente de servidor con desplazamiento nativo, ajuste y navegación finita por fragmentos. La entrada interactiva /client es Tier 2: los puntos sincronizados, las flechas persistentes, los callbacks, la reproducción automática y el arrastre con mouse requieren hidratación; /fade añade transiciones de opacidad CSS. El foco detiene la reproducción automática hasta activar el control de inicio, pasar el puntero la pausa temporalmente y el movimiento reducido desactiva la rotación automática de forma predeterminada. El laboratorio de controles generados con CSS es experimental.
data-uiify-carouseldata-axisdata-enhanceddata-modedata-carousel-indexdata-statedata-dragging--uiify-carousel-slide-size--uiify-carousel-gap--uiify-carousel-fade-duration