Skip to content

Commit fca032d

Browse files
Refactored ProgressBar + Carousel Stepper (#952)
* allow people to pass handlers to modal close * refactored progress / backwards compatible * get example working again * feat: progress bar accounts for any range and computes a progress * initial stepper * feat: indeterminate * feat: indeterminate animation code snippet * feat: improve progress examples * docs: finish progress docs * feat: stepper * tests: initial tests * refactor: carousel test reorganization * refactor: remove test numbers * tests: add multiple slides tests * tests: add non-draggable test * feat: mobile tests * feat: enabled and disabled tests * test: slide snapping * test: csr * test: autoplay tests * test: add state tests * test: stepper tests * docs: carousel docs * autoplay and last stepper tests
1 parent e1db6c2 commit fca032d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1759
-535
lines changed

apps/website/src/routes/docs/headless/carousel/examples/carousel.css

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
gap: 0.5rem;
1919
padding: 1rem;
2020
border: 2px dotted hsl(var(--foreground));
21-
outline: none;
2221
}
2322

2423
.carousel-buttons {
@@ -43,6 +42,7 @@
4342
.carousel-pagination-bullet {
4443
cursor: pointer;
4544
padding-inline: 0.5rem;
45+
outline: none;
4646
}
4747

4848
.carousel-pagination-bullet[data-active] {
@@ -71,3 +71,31 @@
7171
.carousel-conditional .carousel-slide[data-active] {
7272
opacity: 1;
7373
}
74+
75+
.carousel-stepper {
76+
display: flex;
77+
justify-content: space-between;
78+
}
79+
80+
.carousel-step {
81+
display: flex;
82+
gap: 1rem;
83+
align-items: center;
84+
}
85+
86+
.carousel-step::before {
87+
content: attr(data-step);
88+
display: grid;
89+
place-items: center;
90+
width: 2rem;
91+
height: 2rem;
92+
border-radius: 50%;
93+
background-color: hsl(var(--muted));
94+
95+
/* Slight adjustment for visual centering */
96+
padding-bottom: 0.1em;
97+
}
98+
99+
.carousel-step[data-current]::before {
100+
background-color: hsl(var(--primary));
101+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { component$, PropsOf, useSignal, useStyles$ } from '@builder.io/qwik';
2+
import { Carousel, Progress } from '@qwik-ui/headless';
3+
import styles from '../../progress/snippets/progress.css?inline';
4+
5+
export const CarouselProgress = component$((props: PropsOf<typeof Progress.Root>) => {
6+
useStyles$(styles);
7+
8+
return (
9+
<Progress.Root {...props} class="progress" style={{ marginBottom: '2rem' }}>
10+
<Progress.Indicator class="progress-indicator" />
11+
</Progress.Root>
12+
);
13+
});
14+
15+
export default component$(() => {
16+
useStyles$(styles);
17+
18+
const progress = useSignal(0);
19+
const colors = ['red', 'green', 'blue', 'yellow', 'purple', 'orange', 'pink'];
20+
21+
return (
22+
<>
23+
<CarouselProgress bind:value={progress} />
24+
<Carousel.Root class="carousel-root" bind:progress={progress}>
25+
<div class="carousel-buttons">
26+
<Carousel.Previous>Prev</Carousel.Previous>
27+
<Carousel.Next>Next</Carousel.Next>
28+
</div>
29+
{colors.map((color) => (
30+
<Carousel.Slide key={color} class="carousel-slide">
31+
{color}
32+
</Carousel.Slide>
33+
))}
34+
</Carousel.Root>
35+
</>
36+
);
37+
});
38+
// internal
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { component$, useStyles$ } from '@builder.io/qwik';
2+
import { Carousel } from '@qwik-ui/headless';
3+
4+
export default component$(() => {
5+
useStyles$(styles);
6+
7+
return (
8+
<Carousel.Root class="carousel-root" gap={30}>
9+
<Carousel.Stepper class="carousel-stepper">
10+
{Array.from({ length: 3 }).map((_, index) => (
11+
<Carousel.Step class="carousel-step">Header {index + 1}</Carousel.Step>
12+
))}
13+
</Carousel.Stepper>
14+
15+
{Array.from({ length: 3 }).map((_, index) => (
16+
<Carousel.Slide class="carousel-slide">Content {index + 1}</Carousel.Slide>
17+
))}
18+
</Carousel.Root>
19+
);
20+
});
21+
// internal
22+
import styles from './carousel.css?inline';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { component$, useStyles$ } from '@builder.io/qwik';
2+
import { Carousel } from '@qwik-ui/headless';
3+
4+
export default component$(() => {
5+
useStyles$(styles);
6+
7+
return (
8+
<Carousel.Root class="carousel-root" gap={30}>
9+
<Carousel.Stepper class="carousel-stepper">
10+
{Array.from({ length: 3 }).map((_, index) => (
11+
<Carousel.Step as="div" class="carousel-step">
12+
Header {index + 1}
13+
</Carousel.Step>
14+
))}
15+
</Carousel.Stepper>
16+
17+
<Carousel.Scroller class="carousel-scroller">
18+
{Array.from({ length: 3 }).map((_, index) => (
19+
<Carousel.Slide class="carousel-slide">Content {index + 1}</Carousel.Slide>
20+
))}
21+
</Carousel.Scroller>
22+
</Carousel.Root>
23+
);
24+
});
25+
// internal
26+
import styles from './carousel.css?inline';
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { component$, useStyles$ } from '@builder.io/qwik';
2+
import { Carousel } from '@qwik-ui/headless';
3+
4+
export default component$(() => {
5+
useStyles$(styles);
6+
7+
return (
8+
<Carousel.Root class="carousel-root" gap={30}>
9+
<Carousel.Stepper class="carousel-stepper">
10+
{Array.from({ length: 3 }).map((_, index) => (
11+
<Carousel.Step class="carousel-step">Header {index + 1}</Carousel.Step>
12+
))}
13+
</Carousel.Stepper>
14+
15+
<Carousel.Scroller class="carousel-scroller">
16+
{Array.from({ length: 3 }).map((_, index) => (
17+
<Carousel.Slide class="carousel-slide">Content {index + 1}</Carousel.Slide>
18+
))}
19+
</Carousel.Scroller>
20+
</Carousel.Root>
21+
);
22+
});
23+
// internal
24+
import styles from './carousel.css?inline';
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { component$, useOn, useSignal, useStyles$, $ } from '@builder.io/qwik';
2+
import { Carousel } from '@qwik-ui/headless';
3+
4+
export default component$(() => {
5+
useStyles$(styles);
6+
7+
const colors = ['red', 'green', 'blue', 'yellow', 'purple', 'orange', 'pink'];
8+
const isPlaying = useSignal<boolean>(false);
9+
10+
useOn(
11+
'qvisible',
12+
$(() => {
13+
isPlaying.value = true;
14+
}),
15+
);
16+
17+
return (
18+
<>
19+
<Carousel.Root
20+
class="carousel-root"
21+
gap={30}
22+
autoPlayIntervalMs={3500}
23+
bind:autoplay={isPlaying}
24+
>
25+
<div class="carousel-buttons">
26+
<Carousel.Previous>Prev</Carousel.Previous>
27+
<Carousel.Next>Next</Carousel.Next>
28+
</div>
29+
<Carousel.Scroller class="carousel-scroller">
30+
{colors.map((color, index) => (
31+
<Carousel.Slide key={color} class="carousel-slide">
32+
{color}
33+
<div>{index === 1 && <button>I stop autoplay on focus!</button>}</div>
34+
</Carousel.Slide>
35+
))}
36+
</Carousel.Scroller>
37+
</Carousel.Root>
38+
<p>isPlaying: {isPlaying.value.toString()}</p>
39+
<button onClick$={() => (isPlaying.value = !isPlaying.value)}>
40+
Toggle autoplay
41+
</button>
42+
</>
43+
);
44+
});
45+
// internal
46+
import styles from './carousel.css?inline';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { component$, useStyles$ } from '@builder.io/qwik';
2+
import { Carousel } from '@qwik-ui/headless';
3+
4+
export default component$(() => {
5+
useStyles$(styles);
6+
7+
const space = { marginBlock: '1rem' };
8+
9+
return (
10+
<Carousel.Root class="carousel-root" gap={30}>
11+
{/* example stepper css uses flex for horizontal examples */}
12+
<Carousel.Stepper class="carousel-stepper" style={{ flexDirection: 'column' }}>
13+
{Array.from({ length: 3 }).map((_, index) => (
14+
<>
15+
<Carousel.Step class="carousel-step">Header {index + 1}</Carousel.Step>
16+
<Carousel.Slide style={space} class="carousel-slide">
17+
Content {index + 1}
18+
</Carousel.Slide>
19+
</>
20+
))}
21+
</Carousel.Stepper>
22+
</Carousel.Root>
23+
);
24+
});
25+
// internal
26+
import styles from './carousel.css?inline';

0 commit comments

Comments
 (0)