Skip to content

Commit 0ec4952

Browse files
authored
feat(styled kit): carousel component (#1086)
* feat(styled kit): carousel component * chore: changeset
1 parent f75773c commit 0ec4952

File tree

15 files changed

+716
-85
lines changed

15 files changed

+716
-85
lines changed

.changeset/tender-rocks-trade.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik-ui/styled': patch
3+
---
4+
5+
FEAT: The styled kit Carousel component is now available.

apps/website/src/_state/component-statuses.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const statusByComponent: ComponentKitsStatuses = {
1414
Checkbox: ComponentStatus.Draft,
1515
Dropdown: ComponentStatus.Draft,
1616
RadioGroup: ComponentStatus.Draft,
17+
Carousel: ComponentStatus.Draft,
1718
},
1819
headless: {
1920
Checkbox: ComponentStatus.Draft,
Lines changed: 77 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,141 @@
11
export const api = {
2-
carousel: [
2+
"carousel": [
33
{
4-
bullet: [],
4+
"bullet": []
55
},
66
{
7-
inline: [],
7+
"inline": []
88
},
99
{
10-
next: [],
10+
"next": []
1111
},
1212
{
13-
pagination: [],
13+
"pagination": []
1414
},
1515
{
16-
player: [],
16+
"player": []
1717
},
1818
{
19-
previous: [],
19+
"previous": []
2020
},
2121
{
22-
root: [
22+
"root": [
2323
{
24-
PublicCarouselRootProps: [
24+
"PublicCarouselRootProps": [
2525
{
26-
comment: 'The gap between slides',
27-
prop: 'gap',
28-
type: 'number',
26+
"comment": "The gap between slides",
27+
"prop": "gap",
28+
"type": "number"
2929
},
3030
{
31-
comment: 'Number of slides to show at once',
32-
prop: 'slidesPerView',
33-
type: 'number',
31+
"comment": "Number of slides to show at once",
32+
"prop": "slidesPerView",
33+
"type": "number"
3434
},
3535
{
36-
comment: 'Whether the carousel is draggable',
37-
prop: 'draggable',
38-
type: 'boolean',
36+
"comment": "Whether the carousel is draggable",
37+
"prop": "draggable",
38+
"type": "boolean"
3939
},
4040
{
41-
comment: 'Alignment of slides within the viewport',
42-
prop: 'align',
43-
type: "'start' | 'center' | 'end'",
41+
"comment": "Alignment of slides within the viewport",
42+
"prop": "align",
43+
"type": "'start' | 'center' | 'end'"
4444
},
4545
{
46-
comment: 'Whether the carousel should rewind',
47-
prop: 'rewind',
48-
type: 'boolean',
46+
"comment": "Whether the carousel should rewind",
47+
"prop": "rewind",
48+
"type": "boolean"
4949
},
5050
{
51-
comment: 'Bind the selected index to a signal',
52-
prop: "'bind:selectedIndex'",
53-
type: 'Signal<number>',
51+
"comment": "Bind the selected index to a signal",
52+
"prop": "'bind:selectedIndex'",
53+
"type": "Signal<number>"
5454
},
5555
{
56-
comment: 'change the initial index of the carousel on render',
57-
prop: 'startIndex',
58-
type: 'number',
56+
"comment": "change the initial index of the carousel on render",
57+
"prop": "startIndex",
58+
"type": "number"
5959
},
6060
{
61-
comment:
62-
'@deprecated Use bind:selectedIndex instead\n Bind the current slide index to a signal',
63-
prop: "'bind:currSlideIndex'",
64-
type: 'Signal<number>',
61+
"comment": "@deprecated Use bind:selectedIndex instead\n Bind the current slide index to a signal",
62+
"prop": "'bind:currSlideIndex'",
63+
"type": "Signal<number>"
6564
},
6665
{
67-
comment: 'Whether the carousel should autoplay',
68-
prop: "'bind:autoplay'",
69-
type: 'Signal<boolean>',
66+
"comment": "Whether the carousel should autoplay",
67+
"prop": "'bind:autoplay'",
68+
"type": "Signal<boolean>"
7069
},
7170
{
72-
comment: 'the current progress of the carousel',
73-
prop: "'bind:progress'",
74-
type: 'Signal<number>',
71+
"comment": "the current progress of the carousel",
72+
"prop": "'bind:progress'",
73+
"type": "Signal<number>"
7574
},
7675
{
77-
comment: 'Time in milliseconds before the next slide plays during autoplay',
78-
prop: 'autoPlayIntervalMs',
79-
type: 'number',
76+
"comment": "Time in milliseconds before the next slide plays during autoplay",
77+
"prop": "autoPlayIntervalMs",
78+
"type": "number"
8079
},
8180
{
82-
comment: '@internal Total number of slides',
83-
prop: '_numSlides',
84-
type: 'number',
81+
"comment": "@internal Total number of slides",
82+
"prop": "_numSlides",
83+
"type": "number"
8584
},
8685
{
87-
comment: '@internal Whether this carousel has a title',
88-
prop: '_isTitle',
89-
type: 'boolean',
86+
"comment": "@internal Whether this carousel has a title",
87+
"prop": "_isTitle",
88+
"type": "boolean"
9089
},
9190
{
92-
comment: 'The sensitivity of the carousel dragging',
93-
prop: 'sensitivity',
94-
type: '{\n mouse?: number;\n touch?: number;\n }',
91+
"comment": "The sensitivity of the carousel dragging",
92+
"prop": "sensitivity",
93+
"type": "{\n mouse?: number;\n touch?: number;\n }"
9594
},
9695
{
97-
comment:
98-
'The amount of slides to move when hitting the next or previous button',
99-
prop: 'move',
100-
type: 'number',
96+
"comment": "The amount of slides to move when hitting the next or previous button",
97+
"prop": "move",
98+
"type": "number"
10199
},
102100
{
103-
comment: "The carousel's direction",
104-
prop: 'orientation',
105-
type: "'horizontal' | 'vertical'",
101+
"comment": "The carousel's direction",
102+
"prop": "orientation",
103+
"type": "'horizontal' | 'vertical'"
106104
},
107105
{
108-
comment: 'The maximum height of the slides. Needed in vertical carousels',
109-
prop: 'maxSlideHeight',
110-
type: 'number',
106+
"comment": "The maximum height of the slides. Needed in vertical carousels",
107+
"prop": "maxSlideHeight",
108+
"type": "number"
111109
},
112110
{
113-
comment: 'Whether the carousel should support mousewheel navigation',
114-
prop: 'mousewheel',
115-
type: 'boolean',
116-
},
117-
],
118-
},
119-
],
111+
"comment": "Whether the carousel should support mousewheel navigation",
112+
"prop": "mousewheel",
113+
"type": "boolean"
114+
}
115+
]
116+
}
117+
]
120118
},
121119
{
122-
scroller: [],
120+
"scroller": []
123121
},
124122
{
125-
slide: [],
123+
"slide": []
126124
},
127125
{
128-
step: [],
126+
"step": []
129127
},
130128
{
131-
stepper: [],
129+
"stepper": []
132130
},
133131
{
134-
title: [],
132+
"title": []
135133
},
136134
{
137-
'use-carousel': [],
135+
"use-carousel": []
138136
},
139137
{
140-
'use-scroller': [],
141-
},
142-
],
143-
};
138+
"use-scroller": []
139+
}
140+
]
141+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { component$ } from '@builder.io/qwik';
2+
import { Card, Carousel } from '@qwik-ui/styled';
3+
import { LuChevronDown } from '@qwikest/icons/lucide';
4+
import { LuChevronUp } from '@qwikest/icons/lucide';
5+
6+
export default component$(() => {
7+
return (
8+
<Carousel.Root
9+
class="w-full"
10+
orientation="vertical"
11+
maxSlideHeight={360}
12+
slidesPerView={3}
13+
>
14+
<Carousel.Scroller class="m-1">
15+
{Array.from({ length: 5 }).map((_, index) => (
16+
<Carousel.Slide key={index}>
17+
<div class="p-1">
18+
<Card.Root>
19+
<Card.Content class="flex w-full items-center justify-center pt-6">
20+
<span class="text-4xl font-semibold">{index + 1}</span>
21+
</Card.Content>
22+
</Card.Root>
23+
</div>
24+
</Carousel.Slide>
25+
))}
26+
</Carousel.Scroller>
27+
<Carousel.Previous>
28+
<LuChevronUp class="size-10" />
29+
</Carousel.Previous>
30+
<Carousel.Next>
31+
<LuChevronDown class="size-10" />
32+
</Carousel.Next>
33+
</Carousel.Root>
34+
);
35+
});
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { component$ } from '@builder.io/qwik';
2+
import { Card, Carousel } from '@qwik-ui/styled';
3+
4+
export default component$(() => {
5+
return (
6+
<Carousel.Root class="max-w-xs sm:max-w-sm">
7+
<Carousel.Scroller class="m-2">
8+
{Array.from({ length: 9 }).map((_, index) => (
9+
<Carousel.Slide key={index}>
10+
<div class="px-2 py-3">
11+
<Card.Root>
12+
<Card.Content class="flex aspect-square items-center justify-center">
13+
<span class="text-4xl font-semibold">{index + 1}</span>
14+
</Card.Content>
15+
</Card.Root>
16+
</div>
17+
</Carousel.Slide>
18+
))}
19+
</Carousel.Scroller>
20+
<Carousel.Previous />
21+
<Carousel.Next />
22+
</Carousel.Root>
23+
);
24+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { component$ } from '@builder.io/qwik';
2+
import { Card, Carousel } from '@qwik-ui/styled';
3+
4+
export default component$(() => {
5+
return (
6+
<Carousel.Root class="max-w-xs sm:max-w-sm">
7+
<Carousel.Scroller>
8+
{Array.from({ length: 5 }).map((_, index) => (
9+
<Carousel.Slide key={index}>
10+
<div class="p-1">
11+
<Card.Root>
12+
<Card.Content class="flex aspect-square items-center justify-center">
13+
<span class="text-4xl font-semibold">{index + 1}</span>
14+
</Card.Content>
15+
</Card.Root>
16+
</div>
17+
</Carousel.Slide>
18+
))}
19+
</Carousel.Scroller>
20+
<Carousel.Pagination>
21+
<Carousel.Bullet />
22+
<Carousel.Bullet />
23+
<Carousel.Bullet />
24+
<Carousel.Bullet />
25+
<Carousel.Bullet />
26+
</Carousel.Pagination>
27+
</Carousel.Root>
28+
);
29+
});
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { component$, useComputed$, useSignal } from '@builder.io/qwik';
2+
import { Card, Carousel, Separator } from '@qwik-ui/styled';
3+
import { cn } from '@qwik-ui/utils';
4+
5+
export default component$(() => {
6+
const steps = ['Address', 'Shipping', 'Payment'];
7+
const progress = useSignal(0);
8+
const progressIndex = useComputed$(() => Math.floor(progress.value / 50));
9+
return (
10+
<Carousel.Root class="w-full" bind:progress={progress}>
11+
<Carousel.Stepper class="pl-4">
12+
{steps.map((title, index) => (
13+
<>
14+
<Carousel.Step key={index}>
15+
<span
16+
class={cn(
17+
'flex size-8 items-center justify-center rounded-full bg-muted text-xl font-semibold',
18+
progressIndex.value >= index && 'bg-primary text-primary-foreground',
19+
)}
20+
>
21+
{index + 1}
22+
</span>
23+
<span class="font-semibold">{title}</span>
24+
</Carousel.Step>
25+
{index < steps.length - 1 && (
26+
<div class="mx-2 flex-grow">
27+
<Separator
28+
class={cn(progressIndex.value > index ? 'bg-foreground' : 'bg-muted')}
29+
/>
30+
</div>
31+
)}
32+
</>
33+
))}
34+
</Carousel.Stepper>
35+
{Array.from({ length: 3 }).map((_, index) => (
36+
<Carousel.Slide key={index}>
37+
<div class="p-1">
38+
<Card.Root>
39+
<Card.Content class="flex h-40 w-full items-center justify-center">
40+
<span class="text-4xl font-semibold">{index + 1}</span>
41+
</Card.Content>
42+
</Card.Root>
43+
</div>
44+
</Carousel.Slide>
45+
))}
46+
</Carousel.Root>
47+
);
48+
});

0 commit comments

Comments
 (0)