Skip to content

Commit 15f5328

Browse files
committed
feat(carousel): add dot-appearance attribute
1 parent f2e2cb3 commit 15f5328

File tree

3 files changed

+63
-12
lines changed

3 files changed

+63
-12
lines changed

src/components/carousel/carousel.component.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { dispatchEvent } from '../../internals/event.js';
2222
* @csspart button-dot - Any dot navigation button.
2323
* @csspart footer - The footer of the carousel.
2424
*
25-
* @cssproperty --button-background-color - The background color of next/prev buttons.
25+
* @cssproperty --button-background-color - The background color of next/previous buttons.
2626
* @customElement cb-carousel
2727
*
2828
* Resources:
@@ -151,7 +151,10 @@ export default class Carousel extends LitElement {
151151
@property({ type: Boolean, attribute: 'with-fullscreen' })
152152
withFullscreen = false;
153153

154-
@query('.button-prev') previousBtn!: HTMLButtonElement;
154+
@property({ type: String, attribute: 'dot-appearance' })
155+
dotAppearance: 'circle' | 'bar' = 'bar';
156+
157+
@query('.button-previous') previousBtn!: HTMLButtonElement;
155158
@query('.button-next') nextBtn!: HTMLButtonElement;
156159
@query('.container') container!: HTMLSlotElement;
157160
@queryAll('.dot') dotNodes!: HTMLButtonElement[];
@@ -249,7 +252,9 @@ export default class Carousel extends LitElement {
249252
const previous = this.embla.previousScrollSnap();
250253
const selected = this.embla.selectedScrollSnap();
251254
this.dotNodes[previous]?.classList.remove('dot--selected');
255+
this.dotNodes[previous]?.removeAttribute('aria-selected');
252256
this.dotNodes[selected]?.classList.add('dot--selected');
257+
this.dotNodes[selected]?.setAttribute('aria-selected', 'true');
253258
}
254259
}
255260

@@ -363,12 +368,12 @@ export default class Carousel extends LitElement {
363368

364369
renderNextPrevButtons() {
365370
return html`<div class="buttons">
366-
<button part="button button-prev" class="button button-prev" type="button">
371+
<button part="button button-previous" class="button button-previous" type="button">
367372
<svg
368373
xmlns="http://www.w3.org/2000/svg"
369374
viewBox="0 0 512 512"
370375
fill="currentColor"
371-
part="button-icon button-icon-prev"
376+
part="button-icon button-icon-previous"
372377
>
373378
<path
374379
d="M7 239c-9.4 9.4-9.4 24.6 0 33.9L175 441c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9L81.9 280 488 280c13.3 0 24-10.7 24-24s-10.7-24-24-24L81.9 232 209 105c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0L7 239z"
@@ -399,13 +404,14 @@ export default class Carousel extends LitElement {
399404
</div>
400405
${this.withFullscreen ? this.renderFullscreenButton() : ''} ${this.renderNextPrevButtons()}
401406
${this.withDots
402-
? html`<div class="dots">
407+
? html`<div class="dots" part="dots" role="tablist">
403408
${map(this.embla.scrollSnapList(), (_, index) => {
404409
return html`<button
405410
part="button-dot"
406411
type="button"
407-
class="dot"
408-
aria-label="${index + 1}"
412+
role="tab"
413+
class="dot dot--${this.dotAppearance}"
414+
aria-label="Go to slide ${index + 1}"
409415
data-index="${index}"
410416
@click=${this.handleDotClick}
411417
>

src/components/carousel/carousel.stories.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,21 @@ export const WithDots: Story = {
137137
`,
138138
)}
139139
</zx-carousel>
140+
141+
<zx-carousel single with-dots dot-appearance="circle">
142+
${repeat(
143+
Array.from({ length: 3 }),
144+
(_, index) => html`
145+
<zx-carousel-item>
146+
<img
147+
class="object-cover w-full h-96"
148+
src="https://picsum.photos/id/${index + 17}/1200/700"
149+
height="400"
150+
/>
151+
</zx-carousel-item>
152+
`,
153+
)}
154+
</zx-carousel>
140155
`,
141156
};
142157

src/components/carousel/carousel.styles.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@ export default css`
3939
--dot-color-active: #111827;
4040
--dot-margin: 0.5rem 0;
4141
42-
--scrollbar-color: oklch(70.7% 0.022 261.325) transparent;
42+
--scrollbar-color: #d1d5db transparent;
4343
4444
display: block;
4545
/* Note: moving this elsewhere (e.g wrapper) may bug the container translate position */
4646
position: relative;
47+
container-type: inline-size;
4748
}
4849
4950
:host([single]) {
@@ -65,8 +66,9 @@ export default css`
6566
}
6667
6768
:host([with-scrollbar]) .viewport {
68-
overflow: auto;
69+
overflow-x: scroll;
6970
scrollbar-color: var(--scrollbar-color); /* progress / track */
71+
scrollbar-gutter: stable both-edges;
7072
scrollbar-width: thin;
7173
}
7274
@@ -96,7 +98,7 @@ export default css`
9698
}
9799
98100
.button-next,
99-
.button-prev,
101+
.button-previous,
100102
.button-fullscreen {
101103
position: absolute;
102104
top: calc(50% - (var(--button-size) / 2));
@@ -118,7 +120,7 @@ export default css`
118120
-webkit-appearance: none;
119121
}
120122
121-
.button-prev {
123+
.button-previous {
122124
left: var(--button-offset);
123125
}
124126
@@ -127,8 +129,18 @@ export default css`
127129
}
128130
129131
.button-fullscreen {
132+
border-radius: 4px;
130133
right: var(--button-offset);
131134
top: var(--button-offset);
135+
width: calc(var(--button-size) * 0.75);
136+
height: calc(var(--button-size) * 0.75);
137+
}
138+
139+
@container (min-width: 640px) {
140+
.button-fullscreen {
141+
width: var(--button-size);
142+
height: var(--button-size);
143+
}
132144
}
133145
134146
@media (hover: hover) {
@@ -147,6 +159,12 @@ export default css`
147159
color: var(--button-arrow-color);
148160
}
149161
162+
/*
163+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
164+
🅳🅾🆃🆂
165+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
166+
*/
167+
150168
.dots {
151169
display: flex;
152170
justify-content: center;
@@ -167,7 +185,7 @@ export default css`
167185
cursor: pointer;
168186
}
169187
170-
.dot i {
188+
.dot--bar i {
171189
background: var(--dot-color);
172190
height: 0.125rem;
173191
width: 1rem;
@@ -176,4 +194,16 @@ export default css`
176194
.dot--selected i {
177195
background: var(--dot-color-active);
178196
}
197+
198+
.dot--circle i {
199+
display: inline-block;
200+
width: 10px;
201+
height: 10px;
202+
border-radius: 8px;
203+
border: 2px solid var(--dot-color-active);
204+
}
205+
206+
.dot--circle.dot--selected i {
207+
width: 30px;
208+
}
179209
`;

0 commit comments

Comments
 (0)