Создайте один раз. Используйте везде.
Доступные строительные блоки, которые органично впишутся в любой продукт.
Карусель слайдов с сенсорными жестами и кнопками перехода назад и вперёд.
Переключайте истории стрелками или выберите слайд с помощью точек.
Доступные строительные блоки, которые органично впишутся в любой продукт.
Понятные решения из небольших надёжных частей.
Полезные интерфейсы с управлением с клавиатуры ещё до загрузки JavaScript.
Доступные строительные блоки, которые органично впишутся в любой продукт.
Понятные решения из небольших надёжных частей.
Полезные интерфейсы с управлением с клавиатуры ещё до загрузки JavaScript.
Доступные строительные блоки, которые органично впишутся в любой продукт.
Понятные решения из небольших надёжных частей.
Полезные интерфейсы с управлением с клавиатуры ещё до загрузки JavaScript.
Доступные строительные блоки, которые органично впишутся в любой продукт.
Понятные решения из небольших надёжных частей.
Полезные интерфейсы с управлением с клавиатуры ещё до загрузки JavaScript.
Доступные строительные блоки, которые органично впишутся в любой продукт.
Понятные решения из небольших надёжных частей.
Полезные интерфейсы с управлением с клавиатуры ещё до загрузки JavaScript.
Доступные строительные блоки, которые органично впишутся в любой продукт.
Понятные решения из небольших надёжных частей.
Полезные интерфейсы с управлением с клавиатуры ещё до загрузки JavaScript.
Фокус останавливает смену слайдов до нажатия Start. Наведение временно её приостанавливает.
Доступные строительные блоки, которые органично впишутся в любой продукт.
Понятные решения из небольших надёжных частей.
Полезные интерфейсы с управлением с клавиатуры ещё до загрузки JavaScript.
Доступные строительные блоки, которые органично впишутся в любой продукт.
Понятные решения из небольших надёжных частей.
Полезные интерфейсы с управлением с клавиатуры ещё до загрузки JavaScript.
Доступные строительные блоки, которые органично впишутся в любой продукт.
Понятные решения из небольших надёжных частей.
Полезные интерфейсы с управлением с клавиатуры ещё до загрузки 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| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
id* | string | — | Уникальный идентификатор корня; используется для стабильных целей ссылок на фрагменты. |
items* | readonly CarouselItem[] | — | Элементы со стабильным id, доступной подписью и children. Пустой набор даёт null. |
aria-label* | string | — | Доступное название карусели. |
axis | "inline" | "block" | "inline" | Логическая ось прокрутки. Для block нужен определённый block-size области просмотра. |
dir | "ltr" | "rtl" | — | Направление текста и продвижения по строчной оси. |
navigation | boolean | true | Отображает постоянные кнопки назад/вперёд в клиентском режиме. |
pagination | boolean | true | Прямые ссылки на фрагменты. Текущее состояние отражается только после подключения клиента. |
labels | Partial<CarouselLabels> | — | Локализует previous, next, goTo, navigation, start, stop и of. |
icons | CarouselIcons | — | Видимое содержимое кнопок назад/вперёд, по умолчанию пустых. Передайте символ, иконку или слово; labels по-прежнему задаёт их названия. |
className | string | — | Класс корня. Оформляйте именованные части селекторами [data-part]. |
style | CarouselStyle | — | Значения CSS, включая размер слайда, интервал и длительность затухания. |
CarouselClient — @gunkin/uiify/components/carousel/client| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
defaultValue / value | number | — | Начальный или управляемый индекс элемента; элементы управления следуют за наблюдаемым состоянием после остановки. |
rewind | boolean | false | Циклический переход на концах без клонирования слайдов. |
mouseDrag | boolean | false | Перетаскивание мышью, включаемое явно. Сенсорный ввод и колёсико остаются нативными. |
autoplay | boolean | CarouselAutoplayOptions | false | Задержка по умолчанию — 5000ms. Параметры: delay, paused, cycles и stopOnInteraction. Включает видимые Stop/Start. |
onSelect / beforeChange / afterChange / onSwipe | callbacks | — | Сообщает о фактических изменениях после остановки и их причинах; семантика управления и прерванного движения описана в руководстве Carousel. |
ref | Ref<CarouselClientHandle> | — | next, previous, goTo, start, stop и reset. |
FadeCarouselClient — @gunkin/uiify/components/carousel/fade| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
swipe | boolean | true | Свайп пальцем или пером; для мыши нужен mouseDrag. Наследует клиентские свойства, кроме axis. Неактивные слайды имеют inert. |
| Клавиша | Действие |
|---|---|
| Tab / Enter | Переводить фокус на нативные ссылки слайдов и переходить по ним; улучшенные кнопки также активируются Space |
| Arrow keys | Использовать нативную прокрутку, пока область просмотра в фокусе |
Базовый Carousel — Server Component с нативной прокруткой, привязкой и конечной навигацией по ссылкам на фрагменты. Интерактивная точка входа /client относится к Tier 2: синхронизированные точки, постоянные стрелки, обратные вызовы, автопрокрутка и перетаскивание мышью требуют гидратации; /fade добавляет переходы прозрачности CSS. Фокус останавливает автопрокрутку до Start, наведение приостанавливает её временно, а предпочтение уменьшенного движения по умолчанию отключает автоматическую смену слайдов. Пример с элементами управления, созданными CSS, экспериментальный.
data-uiify-carouseldata-axisdata-enhanceddata-modedata-carousel-indexdata-statedata-dragging--uiify-carousel-slide-size--uiify-carousel-gap--uiify-carousel-fade-duration