Skip to content

Commit

Permalink
Carousel (#894)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
thejackshelton authored Jul 30, 2024
1 parent cf6d30e commit ff7fade
Show file tree
Hide file tree
Showing 54 changed files with 2,426 additions and 698 deletions.
11 changes: 11 additions & 0 deletions .changeset/healthy-pumpkins-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@qwik-ui/headless': patch
---

## Carousel

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.

## Dropdown

More improvements have been made to the dropdown component, including new features, components, and QOL updates.
Original file line number Diff line number Diff line change
@@ -1,37 +1,24 @@
.carousel {
--slide-size: 100%;
--slide-height: 5rem;
height: 100%;
max-width: 500px;
overflow: hidden;
.carousel-root {
width: 100%;
}

.carousel-container {
backface-visibility: hidden;
display: flex;
touch-action: pan-y;
margin-left: calc(var(--slide-spacing) * -1);
transition-property: transform;
transition-timing-function: ease;
overflow-x: visible;
padding-block: 0.5rem;
.carousel-scroller {
margin-bottom: 0.5rem;
}

.carousel-slide {
flex: 0 0 var(--slide-size);
min-width: 0;
position: relative;
user-select: none;
transition-property: transform;
border: 2px dotted hsl(var(--primary));
pointer-events: none;
min-height: 10rem;
margin-top: 0.5rem;
user-select: none;
}

.carousel-pagination {
display: flex;
gap: 0.5rem;
padding: 1rem;
border: 2px dotted hsl(var(--foreground));
outline: none;
}

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

.carousel-buttons button[aria-disabled='true'] {
opacity: 0.5;
}

.carousel-buttons button {
border: 2px dotted hsl(var(--foreground));
padding: 0.5rem;
Expand All @@ -53,20 +36,38 @@
background-color: hsla(var(--primary) / 0.08);
}

.carousel-img {
pointer-events: none;
.carousel-buttons button:disabled {
opacity: 0.5;
}

.carousel-pagination-bullet {
cursor: pointer;
padding-inline: 0.5rem;
}

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

.carousel-pagination-bullet:hover {
background-color: hsla(var(--primary) / 0.08);
}

.carousel-conditional {
position: relative;
height: 200px;
}

.carousel-conditional .carousel-slide {
opacity: 0;
transition: opacity 0.5s;
/* NOT display block */
display: revert;
position: absolute;
inset: 0;
}

.carousel-conditional .carousel-slide[data-active] {
opacity: 1;
}
30 changes: 30 additions & 0 deletions apps/website/src/routes/docs/headless/carousel/examples/center.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { component$, useStyles$ } from '@builder.io/qwik';
import { Carousel } from '@qwik-ui/headless';

export default component$(() => {
useStyles$(styles);

const colors = ['red', 'green', 'blue', 'yellow', 'purple', 'orange', 'pink'];

return (
<Carousel.Root class="carousel-root" gap={30} align="center">
<div class="carousel-buttons">
<Carousel.Previous>Prev</Carousel.Previous>
<Carousel.Next>Next</Carousel.Next>
</div>
<Carousel.Scroller class="carousel-scroller">
{colors.map((color) => (
<Carousel.Slide
style={{ flexBasis: '300px' }}
key={color}
class="carousel-slide"
>
{color}
</Carousel.Slide>
))}
</Carousel.Scroller>
</Carousel.Root>
);
});
// internal
import styles from './carousel.css?inline';
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { component$, useStyles$ } from '@builder.io/qwik';
import { Carousel } from '@qwik-ui/headless';

export default component$(() => {
useStyles$(styles);

const colors = ['red', 'green', 'blue', 'yellow', 'purple', 'orange', 'pink'];

return (
<Carousel.Root class="carousel-root" gap={30}>
<div class="carousel-buttons">
<Carousel.Previous>Prev</Carousel.Previous>
<Carousel.Next>Next</Carousel.Next>
</div>
<div class="carousel-conditional">
{colors.map((color) => (
<Carousel.Slide key={color} class="carousel-slide">
{color}
</Carousel.Slide>
))}
</div>
</Carousel.Root>
);
});
// internal
import styles from './carousel.css?inline';
34 changes: 34 additions & 0 deletions apps/website/src/routes/docs/headless/carousel/examples/csr.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { component$, useSignal, useStyles$ } from '@builder.io/qwik';
import { Carousel } from '@qwik-ui/headless';

export default component$(() => {
useStyles$(styles);

const colors = ['red', 'green', 'blue', 'yellow', 'purple', 'orange', 'pink'];
const renderCarousel = useSignal(false);

return (
<>
<button onClick$={() => (renderCarousel.value = !renderCarousel.value)}>
Render Carousel
</button>
{renderCarousel.value && (
<Carousel.Root class="carousel-root">
<div class="carousel-buttons">
<Carousel.Previous>Prev</Carousel.Previous>
<Carousel.Next>Next</Carousel.Next>
</div>
<Carousel.Scroller class="carousel-scroller">
{colors.map((color) => (
<Carousel.Slide key={color} class="carousel-slide">
{color}
</Carousel.Slide>
))}
</Carousel.Scroller>
</Carousel.Root>
)}
</>
);
});
// internal
import styles from './carousel.css?inline';
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { component$, useStyles$ } from '@builder.io/qwik';
import { Carousel } from '@qwik-ui/headless';

export default component$(() => {
useStyles$(styles);

return (
<Carousel.Root class="carousel-root" gap={30}>
<div class="carousel-buttons">
<Carousel.Previous>Prev</Carousel.Previous>
<Carousel.Next>Next</Carousel.Next>
</div>
<Carousel.Scroller class="carousel-scroller">
<Carousel.Slide style={{ flexBasis: '200px' }} class="carousel-slide">
red
</Carousel.Slide>
<Carousel.Slide style={{ flexBasis: '400px' }} class="carousel-slide">
green
</Carousel.Slide>
<Carousel.Slide style={{ flexBasis: '300px' }} class="carousel-slide">
blue
</Carousel.Slide>
<Carousel.Slide style={{ flexBasis: '350px' }} class="carousel-slide">
yellow
</Carousel.Slide>
<Carousel.Slide style={{ flexBasis: '100px' }} class="carousel-slide">
purple
</Carousel.Slide>
</Carousel.Scroller>
</Carousel.Root>
);
});
// internal
import styles from './carousel.css?inline';
30 changes: 30 additions & 0 deletions apps/website/src/routes/docs/headless/carousel/examples/end.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { component$, useStyles$ } from '@builder.io/qwik';
import { Carousel } from '@qwik-ui/headless';

export default component$(() => {
useStyles$(styles);

const colors = ['red', 'green', 'blue', 'yellow', 'purple', 'orange', 'pink'];

return (
<Carousel.Root class="carousel-root" gap={30} align="end">
<div class="carousel-buttons">
<Carousel.Previous>Prev</Carousel.Previous>
<Carousel.Next>Next</Carousel.Next>
</div>
<Carousel.Scroller class="carousel-scroller">
{colors.map((color) => (
<Carousel.Slide
style={{ flexBasis: '300px' }}
key={color}
class="carousel-slide"
>
{color}
</Carousel.Slide>
))}
</Carousel.Scroller>
</Carousel.Root>
);
});
// internal
import styles from './carousel.css?inline';
Loading

0 comments on commit ff7fade

Please sign in to comment.