Skip to content

Commit ff7fade

Browse files
Carousel (#894)
* refactor: setup initial carousel testsw * fix: carousel in CSR * add expectation * test: added test cases * test: some additional test cases * not draggable * CSS scroll snapping on mobile * threshold tests * try simpler code refactor * small docs * grab index from inline * improved examples * use scorllLeft instead * hacky impl * fix: slide snapping * better naming * much simpler carousel * fix: get proper array order * account for slide margin * updated correct index * update with css scroll snapping * simplify container * get buttons working again * setup for drag to do its own behavior * get mouse working again * correct indexes again * it worksgit add . * down to touch interacitons * initial touch working * finally workinggit add . * add pagination * carousel pagination * first attempt at multiple slides per view * update next button based on slidesPerView * feat: keyboard navigation with pagination * focus management from previous and next when out of slides * bullets render based on slides in view * add non-draggable example * touch ups * correct styles * mouse dragging works on variable slide widths * works on variable widths for index changes * pagination works again * correct scroll snapping again * improve carousel a11y * without scrollbar * better styles and remove num slides in inline * transitions sort of working * center and end alignments * more tests notes * feat: looped support * improved a11ty * home and enter keys for pagination * add home & end test cases w/ pagination * add aria live polite * add announcements to the content inside of the carousel and collapsible * add inert based on slidesPerView * tabpanel in pagination carousels * add accessible name * cleaner code * initial working autoplay * bound signals * simplify bound signal * improved autoplay and tabs aria * add in aria-selected * accessible name for autoplay player button * respecting reduced motion * autoplay looping working * improved experience when consuming and also support for updating flex-basis automatically when slides per view change * setup for the initial index * more test cases * multiple slides working on the server * proper gap * add correct initial index * get initial indexes sort of working * correct snapping again on mobile with initial index * almost * next and prev buttons should work * improved styling * upgrade to 1.7.2 * no caret * add in caret only in root * initial working * initial working in all snap modes * carousel docs * add in changeset
1 parent cf6d30e commit ff7fade

Some content is hidden

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

54 files changed

+2426
-698
lines changed

.changeset/healthy-pumpkins-repair.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'@qwik-ui/headless': patch
3+
---
4+
5+
## Carousel
6+
7+
The carousel has been refactored from the ground up, including new features, components, and QOL updates. It is still in a draft state, and development is ongoing.
8+
9+
## Dropdown
10+
11+
More improvements have been made to the dropdown component, including new features, components, and QOL updates.
Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,24 @@
1-
.carousel {
2-
--slide-size: 100%;
3-
--slide-height: 5rem;
4-
height: 100%;
5-
max-width: 500px;
6-
overflow: hidden;
1+
.carousel-root {
2+
width: 100%;
73
}
84

9-
.carousel-container {
10-
backface-visibility: hidden;
11-
display: flex;
12-
touch-action: pan-y;
13-
margin-left: calc(var(--slide-spacing) * -1);
14-
transition-property: transform;
15-
transition-timing-function: ease;
16-
overflow-x: visible;
17-
padding-block: 0.5rem;
5+
.carousel-scroller {
6+
margin-bottom: 0.5rem;
187
}
198

209
.carousel-slide {
21-
flex: 0 0 var(--slide-size);
22-
min-width: 0;
23-
position: relative;
24-
user-select: none;
25-
transition-property: transform;
2610
border: 2px dotted hsl(var(--primary));
27-
pointer-events: none;
11+
min-height: 10rem;
12+
margin-top: 0.5rem;
13+
user-select: none;
2814
}
2915

3016
.carousel-pagination {
3117
display: flex;
3218
gap: 0.5rem;
3319
padding: 1rem;
3420
border: 2px dotted hsl(var(--foreground));
21+
outline: none;
3522
}
3623

3724
.carousel-buttons {
@@ -40,10 +27,6 @@
4027
border: 2px dotted hsl(var(--accent));
4128
}
4229

43-
.carousel-buttons button[aria-disabled='true'] {
44-
opacity: 0.5;
45-
}
46-
4730
.carousel-buttons button {
4831
border: 2px dotted hsl(var(--foreground));
4932
padding: 0.5rem;
@@ -53,20 +36,38 @@
5336
background-color: hsla(var(--primary) / 0.08);
5437
}
5538

56-
.carousel-img {
57-
pointer-events: none;
39+
.carousel-buttons button:disabled {
40+
opacity: 0.5;
5841
}
5942

6043
.carousel-pagination-bullet {
6144
cursor: pointer;
6245
padding-inline: 0.5rem;
6346
}
6447

65-
.pagination-underline {
48+
.carousel-pagination-bullet[data-active] {
6649
outline: 2px dotted hsl(var(--primary));
6750
background-color: hsla(var(--primary) / 0.08);
6851
}
6952

7053
.carousel-pagination-bullet:hover {
7154
background-color: hsla(var(--primary) / 0.08);
7255
}
56+
57+
.carousel-conditional {
58+
position: relative;
59+
height: 200px;
60+
}
61+
62+
.carousel-conditional .carousel-slide {
63+
opacity: 0;
64+
transition: opacity 0.5s;
65+
/* NOT display block */
66+
display: revert;
67+
position: absolute;
68+
inset: 0;
69+
}
70+
71+
.carousel-conditional .carousel-slide[data-active] {
72+
opacity: 1;
73+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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 colors = ['red', 'green', 'blue', 'yellow', 'purple', 'orange', 'pink'];
8+
9+
return (
10+
<Carousel.Root class="carousel-root" gap={30} align="center">
11+
<div class="carousel-buttons">
12+
<Carousel.Previous>Prev</Carousel.Previous>
13+
<Carousel.Next>Next</Carousel.Next>
14+
</div>
15+
<Carousel.Scroller class="carousel-scroller">
16+
{colors.map((color) => (
17+
<Carousel.Slide
18+
style={{ flexBasis: '300px' }}
19+
key={color}
20+
class="carousel-slide"
21+
>
22+
{color}
23+
</Carousel.Slide>
24+
))}
25+
</Carousel.Scroller>
26+
</Carousel.Root>
27+
);
28+
});
29+
// internal
30+
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 colors = ['red', 'green', 'blue', 'yellow', 'purple', 'orange', 'pink'];
8+
9+
return (
10+
<Carousel.Root class="carousel-root" gap={30}>
11+
<div class="carousel-buttons">
12+
<Carousel.Previous>Prev</Carousel.Previous>
13+
<Carousel.Next>Next</Carousel.Next>
14+
</div>
15+
<div class="carousel-conditional">
16+
{colors.map((color) => (
17+
<Carousel.Slide key={color} class="carousel-slide">
18+
{color}
19+
</Carousel.Slide>
20+
))}
21+
</div>
22+
</Carousel.Root>
23+
);
24+
});
25+
// internal
26+
import styles from './carousel.css?inline';
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { component$, 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 renderCarousel = useSignal(false);
9+
10+
return (
11+
<>
12+
<button onClick$={() => (renderCarousel.value = !renderCarousel.value)}>
13+
Render Carousel
14+
</button>
15+
{renderCarousel.value && (
16+
<Carousel.Root class="carousel-root">
17+
<div class="carousel-buttons">
18+
<Carousel.Previous>Prev</Carousel.Previous>
19+
<Carousel.Next>Next</Carousel.Next>
20+
</div>
21+
<Carousel.Scroller class="carousel-scroller">
22+
{colors.map((color) => (
23+
<Carousel.Slide key={color} class="carousel-slide">
24+
{color}
25+
</Carousel.Slide>
26+
))}
27+
</Carousel.Scroller>
28+
</Carousel.Root>
29+
)}
30+
</>
31+
);
32+
});
33+
// internal
34+
import styles from './carousel.css?inline';
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
<div class="carousel-buttons">
10+
<Carousel.Previous>Prev</Carousel.Previous>
11+
<Carousel.Next>Next</Carousel.Next>
12+
</div>
13+
<Carousel.Scroller class="carousel-scroller">
14+
<Carousel.Slide style={{ flexBasis: '200px' }} class="carousel-slide">
15+
red
16+
</Carousel.Slide>
17+
<Carousel.Slide style={{ flexBasis: '400px' }} class="carousel-slide">
18+
green
19+
</Carousel.Slide>
20+
<Carousel.Slide style={{ flexBasis: '300px' }} class="carousel-slide">
21+
blue
22+
</Carousel.Slide>
23+
<Carousel.Slide style={{ flexBasis: '350px' }} class="carousel-slide">
24+
yellow
25+
</Carousel.Slide>
26+
<Carousel.Slide style={{ flexBasis: '100px' }} class="carousel-slide">
27+
purple
28+
</Carousel.Slide>
29+
</Carousel.Scroller>
30+
</Carousel.Root>
31+
);
32+
});
33+
// internal
34+
import styles from './carousel.css?inline';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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 colors = ['red', 'green', 'blue', 'yellow', 'purple', 'orange', 'pink'];
8+
9+
return (
10+
<Carousel.Root class="carousel-root" gap={30} align="end">
11+
<div class="carousel-buttons">
12+
<Carousel.Previous>Prev</Carousel.Previous>
13+
<Carousel.Next>Next</Carousel.Next>
14+
</div>
15+
<Carousel.Scroller class="carousel-scroller">
16+
{colors.map((color) => (
17+
<Carousel.Slide
18+
style={{ flexBasis: '300px' }}
19+
key={color}
20+
class="carousel-slide"
21+
>
22+
{color}
23+
</Carousel.Slide>
24+
))}
25+
</Carousel.Scroller>
26+
</Carousel.Root>
27+
);
28+
});
29+
// internal
30+
import styles from './carousel.css?inline';

0 commit comments

Comments
 (0)