From 3fc4ced37bfa158f48f10d45a4689e78e2d02870 Mon Sep 17 00:00:00 2001 From: dev Date: Sat, 23 May 2026 23:18:25 +0200 Subject: [PATCH] feat(carousel): showIndicators + showControls visibility props MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two new eidos-level booleans on `` so consumers can toggle the indicator dots and the prev/next triggers without touching the markup composition. Defaults stay `true` (existing behaviour). The consumer still renders the parts in markup; the recipe just hides them via `display: none` when the eidos root stamps `data-hide-indicators` / `data-hide-controls`. Toggling on/off doesn't unmount the DOM, so ARIA focus is preserved across the change and the layout doesn't reflow into a different size. Naming follows the canonical eidos cascade — `showIndicators` mirrors calendar's `showWeekNumbers`. Mantine uses `withIndicators` (default false); we default `true` because the Eidos recipe assumes indicators are part of the default surface. Demo: two switches added to the eidos visual-props section + snippet preview emits the prop when set to false. Verified: clicking the demo switch flips `data-hide-indicators` on the root and the indicator-group's computed `display` goes from default to `none` without remounting. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../eidos/components/carousel/carousel.css | 15 ++++++++++++++ .../eidos/components/carousel/carousel.svelte | 4 ++++ src/uix/eidos/components/carousel/types.ts | 17 ++++++++++++++++ .../uix/components/carousel/+page.svelte | 20 +++++++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/src/uix/eidos/components/carousel/carousel.css b/src/uix/eidos/components/carousel/carousel.css index 35db01c39..79a9d9011 100644 --- a/src/uix/eidos/components/carousel/carousel.css +++ b/src/uix/eidos/components/carousel/carousel.css @@ -177,6 +177,21 @@ pointer-events: none; } +/* + * Visibility toggles for the dots tablist and prev/next triggers. The + * consumer still composes the parts in markup; these data-attrs from + * the eidos root just hide them via the recipe so toggling on/off + * doesn't unmount the DOM (no focus loss, no layout flicker). + */ +[data-carousel][data-hide-indicators] [data-carousel-indicator-group] { + display: none; +} + +[data-carousel][data-hide-controls] [data-carousel-prev-trigger], +[data-carousel][data-hide-controls] [data-carousel-next-trigger] { + display: none; +} + [data-carousel]:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); diff --git a/src/uix/eidos/components/carousel/carousel.svelte b/src/uix/eidos/components/carousel/carousel.svelte index cc3b55e49..3d17d74e6 100644 --- a/src/uix/eidos/components/carousel/carousel.svelte +++ b/src/uix/eidos/components/carousel/carousel.svelte @@ -16,6 +16,8 @@ color = 'primary', block = true, verticalBlockSize, + showIndicators = true, + showControls = true, value = $bindable(0), orientation = 'horizontal', style, @@ -62,6 +64,8 @@ data-variant={variant} data-color={color} data-block={block ? '' : undefined} + data-hide-indicators={showIndicators ? undefined : ''} + data-hide-controls={showControls ? undefined : ''} > {#snippet children(snippetProps)} {@render bodyContent?.(snippetProps)} diff --git a/src/uix/eidos/components/carousel/types.ts b/src/uix/eidos/components/carousel/types.ts index 7ea385c4b..0795f4783 100644 --- a/src/uix/eidos/components/carousel/types.ts +++ b/src/uix/eidos/components/carousel/types.ts @@ -67,6 +67,23 @@ export type CarouselProps = ProviderProps & { * @default '16rem' */ verticalBlockSize?: string; + /** + * Show the indicator dots tablist. The consumer still renders the + * `` markup — this prop just hides it via + * the recipe when `false`, so toggling it doesn't unmount the dots + * (preserves ARIA focus and avoids layout flicker). Set to `false` + * for hero carousels driven by prev/next or autoplay only. + * @default true + */ + showIndicators?: boolean; + /** + * Show the prev/next trigger buttons. Same semantics as + * `showIndicators` — the consumer still renders the + * `` / `` markup; the + * recipe hides them when `false`. + * @default true + */ + showControls?: boolean; }; export type CarouselViewportProps = ViewportProps; diff --git a/web/routes/uix/components/carousel/+page.svelte b/web/routes/uix/components/carousel/+page.svelte index cfb211f69..b1d35459a 100644 --- a/web/routes/uix/components/carousel/+page.svelte +++ b/web/routes/uix/components/carousel/+page.svelte @@ -58,6 +58,8 @@ let size = $state('md'); let variant = $state('surface'); let color = $state('primary'); + let showIndicators = $state(true); + let showControls = $state(true); // Imperative-API demo: store the handle exposed via the snippet so the // footer buttons + keyboard shortcut can drive the carousel. @@ -191,6 +193,8 @@ autoplay && stopOnLastSnap && ' stopOnLastSnap', disabled && ' disabled', dir && ` dir="${dir}"`, + !showIndicators && ' showIndicators={false}', + !showControls && ' showControls={false}', '>', ' ', ' ', @@ -272,6 +276,8 @@ {size} {variant} {color} + {showIndicators} + {showControls} > {#snippet children(snippet: CarouselProviderSnippetProps)} {(api = snippet.api, isPlaying = snippet.isPlaying, '')} @@ -567,6 +573,20 @@ {/each} + +