Components
Carousel
Slides that scroll sideways and come to rest on one. The browser scrolls and snaps, so a wheel, a swipe and the keyboard all move it, and the arrows, the indicators and autoplay follow in the browser with nothing sent to the page. A slide's width is its class.
Drawn and behaving as Flux UI's carousel does, measured against its live docs.
Carousel
A slide at a time, with arrows over it.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CarouselExample : Component
{
// Placeholders where Flux's page shows photographs.
private static readonly string[] Scenes = ["Seascape", "Woodscape", "Landscape"];
protected override Component? Render() =>
Div.Class("mx-auto w-full max-w-sm")[
Ui.Carousel.TrackClass("rounded-lg")[
Scenes.Select(scene => Ui.CarouselSlide.Key(scene).Class("w-full")[
Div.Class("flex aspect-16/9 items-center justify-center rounded-lg bg-zinc-100 text-sm font-medium text-zinc-500 dark:bg-white/10 dark:text-white/50")[scene]
])
]
];
}Indicators
One button per slide under the carousel, and no arrows.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CarouselIndicatorsExample : Component
{
private static readonly (string Said, string Name, string Role)[] Quotes =
[
("“We shipped a polished UI in days, not weeks.”", "Graham Whitaker", " · Founder, Northwind"),
("“When I reach for a component, it just works.”", "Elise Rowan", " · Engineering Lead, Southline Studio"),
("“I stopped writing UI primitives entirely.”", "Jonah Vale", " · CTO, Alder & Co."),
];
protected override Component? Render() =>
Div.Class("mx-auto w-full max-w-sm")[
Ui.Carousel.Class("w-full").Indicators().Arrows(false)[
Quotes.Select(quote => Ui.CarouselSlide.Key(quote.Name).Class("w-full")[
Div.Class("flex flex-col items-center gap-4 text-center")[
Blockquote.Class("text-balance text-zinc-700 dark:text-zinc-300")[quote.Said],
Ui.Text.Sm[Ui.Text.Inline().Variant(Ui.TextVariant.Strong)[quote.Name], quote.Role]
]
])
]
];
}Autoplay
Moves on every 3.5 seconds, and holds under the pointer.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CarouselAutoplayExample : Component
{
private static readonly string[] Scenes = ["Seascape", "Woodscape", "Landscape"];
protected override Component? Render() =>
Div.Class("mx-auto w-full max-w-sm")[
Ui.Carousel.Autoplay().AutoplayInterval(3500).Indicators().TrackClass("rounded-lg")[
Scenes.Select(scene => Ui.CarouselSlide.Key(scene).Class("w-full")[
Div.Class("flex aspect-16/9 items-center justify-center rounded-lg bg-zinc-100 text-sm font-medium text-zinc-500 dark:bg-white/10 dark:text-white/50")[scene]
])
]
];
}External controls
Ui.CarouselControls anywhere on the page move the carousel that carries their name.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CarouselExternalControlsExample : Component
{
private static readonly (string Name, string Price, string Rating)[] Stays =
[
("Cottage in Mendocino", "$680", "5.0"), ("Lodge in the Thousand Islands", "$370", "4.96"),
("House in the Adirondacks", "$550", "4.88"), ("House in Cape Cod", "$840", "5"),
];
protected override Component? Render() =>
Div.Class("px-6")[
Div.Class("mb-4 flex items-center justify-between")[
Div[Ui.Heading.Lg["Popular stays"], Ui.Text["Handpicked homes in beautiful places"]],
Div[Ui.CarouselControls.Name("popular-stays")]
],
Ui.Carousel.Name("popular-stays").Bleed().Arrows(false)[
Stays.Select(stay => Ui.CarouselSlide.Key(stay.Name).Class("w-4/5 sm:w-1/2 md:w-1/3")[
Div.Class("aspect-2/1 rounded-lg bg-zinc-100 dark:bg-white/10"),
Ui.Heading.Class("mt-2")[stay.Name],
Div.Class("mt-1 flex items-center gap-0.5")[
Ui.Text.Class("text-xs")[stay.Price, " for 2 nights ・"],
Ui.Icon.Name(Ui.IconName.Star).Variant(Ui.IconVariant.Micro).Class("size-3"),
Ui.Text.Class("text-xs text-zinc-800 dark:text-white")[stay.Rating]
]
])
]
];
}Handpicked homes in beautiful places
Arrow position
Inside, the default, or half over each edge.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CarouselArrowPositionExample : Component
{
private static readonly string[] Slides = ["one", "two"];
protected override Component? Render() =>
Div.Class("mx-auto max-w-xs space-y-6")[
Ui.Carousel.Key("inside").TrackClass("rounded-lg")[Labelled("Inside")],
Ui.Carousel.Key("overlap").Overlap.TrackClass("rounded-lg")[Labelled("Overlap")]
];
private static IEnumerable<Component> Labelled(string label) =>
Slides.Select(slide => Ui.CarouselSlide.Key(label + "-" + slide).Class("w-full")[
Div.Class("flex h-40 w-full items-center justify-center bg-zinc-100 text-sm font-medium text-zinc-500 dark:bg-white/10 dark:text-white/50")[label]
]);
}Fade
The edge with more slides behind it fades.
using System.Globalization;
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CarouselFadeExample : Component
{
protected override Component? Render() =>
Div.Class("px-6")[
Ui.Carousel.Fade().Bleed()[
Enumerable.Range(1, 5).Select(number => Ui.CarouselSlide.Key(number).Class("w-4/5 sm:w-1/2 md:w-1/3")[
Div.Class("flex aspect-2/1 items-center justify-center rounded-lg bg-zinc-100 text-2xl font-medium text-zinc-400 dark:bg-white/10 dark:text-white/40")[
number.ToString(CultureInfo.InvariantCulture)
]
])
]
];
}Page advance
An arrow moves by the slides in view.
using System.Globalization;
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CarouselPageExample : Component
{
protected override Component? Render() =>
Div.Class("px-6")[
Ui.Carousel.Page.Bleed()[
Enumerable.Range(1, 10).Select(number => Ui.CarouselSlide.Key(number).Class("w-4/5 sm:w-1/2 md:w-1/3")[
Div.Class("flex aspect-2/1 items-center justify-center rounded-lg bg-zinc-100 text-2xl font-medium text-zinc-400 dark:bg-white/10 dark:text-white/40")[
number.ToString(CultureInfo.InvariantCulture)
]
])
]
];
}Arrows outside
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CarouselOutsideExample : Component
{
private static readonly string[] Slides = ["one", "two"];
protected override Component? Render() =>
Div.Class("mx-auto max-w-xs")[
Ui.Carousel.Outside.TrackClass("rounded-lg")[
Slides.Select(slide => Ui.CarouselSlide.Key(slide).Class("w-full")[
Div.Class("flex h-40 w-full items-center justify-center bg-zinc-100 text-sm font-medium text-zinc-500 dark:bg-white/10 dark:text-white/50")["Outside"]
])
]
];
}Rewind
At the end the next arrow stays, and goes back to the first slide.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CarouselRewindExample : Component
{
private static readonly string[] Scenes = ["Seascape", "Woodscape", "Landscape"];
protected override Component? Render() =>
Div.Class("mx-auto w-full max-w-sm")[
Ui.Carousel.Rewind.Mandatory.TrackClass("rounded-lg")[
Scenes.Select(scene => Ui.CarouselSlide.Key(scene).Class("w-full")[
Div.Class("flex aspect-16/9 items-center justify-center rounded-lg bg-zinc-100 text-sm font-medium text-zinc-500 dark:bg-white/10 dark:text-white/50")[scene]
])
]
];
}Disabled
The arrows and the indicators are out of use; the slides still scroll.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CarouselDisabledExample : Component
{
private static readonly string[] Scenes = ["Seascape", "Woodscape", "Landscape"];
protected override Component? Render() =>
Div.Class("mx-auto w-full max-w-sm")[
Ui.Carousel.Disabled().Indicators().TrackClass("rounded-lg")[
Scenes.Select(scene => Ui.CarouselSlide.Key(scene).Class("w-full")[
Div.Class("flex aspect-16/9 items-center justify-center rounded-lg bg-zinc-100 text-sm font-medium text-zinc-500 dark:bg-white/10 dark:text-white/50")[scene]
])
]
];
}Behaviour
Nothing is sent to the page
The scrolling is the browser's: scroll-snap, so a wheel, a swipe and the keyboard move it as they move any scroller. What a stylesheet cannot do, Rask's runtime does from the markup (data-rask-carousel): it marks the root and each arrow data-at-start and data-at-end, disables the arrow with nowhere to go, marks the slide in view data-selected and its indicator aria-current, moves the track when an arrow or an indicator is pressed, and runs autoplay. There is no OnChange, as Flux has none.
A slide's width is its class, and decides how many are in view. daisyUI's carousel wrapper, which Ui.Carousel used to draw around carousel-item children, is gone.
Autoplay
Autoplay() advances on its interval, 5000ms unless AutoplayInterval says otherwise, and goes back to the first slide after the last. It holds under the pointer and while focus is inside, and never starts for a reader who asked for less motion.
What a screen reader hears
A group called "carousel" holding "slide, 2 of 5". Those words, and the buttons' names, are in the translation catalog.
Reference
Ui.Carousel
Slides that scroll sideways and come to rest on one. The browser scrolls; the runtime moves the rest.
Step | Takes | What it does |
|---|---|---|
.Arrows() | bool | Whether it has its own previous and next arrows. On unless false. |
.ArrowsPosition(…) | Ui.CarouselArrowsPositionInside Overlap Outside Each is a step of its own too, unless an HTML tag has its name. | Where those arrows sit. Inside when unset. |
.ArrowsClass(…) | string | Classes added to each of those arrows. |
.Autoplay() | bool | Advances by itself, holding while it is hovered, focused or moved by hand, and never for a reader who asked for less motion. |
.AutoplayInterval(…) | int | Milliseconds between two advances. 5000 when unset. |
.Indicators() | bool | One button per slide under the carousel, each going to its slide. |
.Disabled() | bool | Takes the arrows and the indicators out of use. The slides still scroll. |
.Fade() | bool | Fades the edge of the track that has more slides behind it. |
.Bleed() | bool | Runs the track through the padding around it, by --ui-bleed (a card sets it) or 1.5rem. |
.Snap(…) | Ui.CarouselSnapProximity Mandatory Each is a step of its own too, unless an HTML tag has its name. | How firmly it rests on a slide. Proximity when unset. |
.Scroll(…) | Ui.CarouselScrollSmooth Instant Each is a step of its own too, unless an HTML tag has its name. | How an arrow or an indicator moves it. Smooth when unset. |
.Advance(…) | Ui.CarouselAdvanceSlide Page Each is a step of its own too, unless an HTML tag has its name. | How far an arrow moves it: a slide, or the slides in view. Slide when unset. |
.Wrap(…) | Ui.CarouselWrapNone Rewind Each is a step of its own too, unless an HTML tag has its name. | What advancing past the last slide does. None when unset; Rewind goes back to the first. |
.Name(…) | string | A name unique on the page, for a Ui.CarouselControls elsewhere to move it by. |
.TrackClass(…) | string | Classes added to the scrolling track. |
Ui.CarouselSlide
One slide. Its class is its width, and so how many are in view.
No steps of its own: what goes inside it is its content.
Ui.CarouselControls
Previous and next buttons anywhere on the page, for the carousel of that name.
Step | Takes | What it does |
|---|---|---|
.Name(…) | string | The Name of the carousel they move. |