Skip to content

Commit fa0fae1

Browse files
committed
feat(carousel): add with-scrollbar and with-fullscreen attributes
1 parent 38037f9 commit fa0fae1

File tree

6 files changed

+126
-18
lines changed

6 files changed

+126
-18
lines changed

.storybook/tailwind.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
11
@import 'tailwindcss';
2+
3+
@layer base {
4+
*,
5+
::after,
6+
::before,
7+
::backdrop,
8+
::file-selector-button {
9+
border-color: var(--color-gray-200, currentColor);
10+
}
11+
}

src/components/carousel/carousel.component.ts

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ export default class Carousel extends LitElement {
145145
@property({ type: Boolean, attribute: 'with-dots' })
146146
withDots = false;
147147

148+
@property({ type: Boolean, attribute: 'with-scrollbar' })
149+
withScrollbar = false;
150+
151+
@property({ type: Boolean, attribute: 'with-fullscreen' })
152+
withFullscreen = false;
153+
148154
@query('.button-prev') previousBtn!: HTMLButtonElement;
149155
@query('.button-next') nextBtn!: HTMLButtonElement;
150156
@query('.container') container!: HTMLSlotElement;
@@ -335,23 +341,51 @@ export default class Carousel extends LitElement {
335341
return this.embla?.internalEngine().options.active;
336342
}
337343

344+
renderFullscreenButton() {
345+
return html`<button
346+
type="button"
347+
part="button button-fullscreen"
348+
class="button button-fullscreen"
349+
@click=${dispatchEvent(this, 'fullscreen')}
350+
>
351+
<svg
352+
xmlns="http://www.w3.org/2000/svg"
353+
viewBox="0 0 512 512"
354+
fill="currentColor"
355+
part="button-icon button-icon-fullscreen"
356+
>
357+
<path
358+
d="M295 183c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l135-135 0 86.1c0 13.3 10.7 24 24 24s24-10.7 24-24l0-144c0-13.3-10.7-24-24-24L344 0c-13.3 0-24 10.7-24 24s10.7 24 24 24l86.1 0-135 135zM217 329c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0L48 430.1 48 344c0-13.3-10.7-24-24-24S0 330.7 0 344L0 488c0 13.3 10.7 24 24 24l144 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-86.1 0 135-135z"
359+
/>
360+
</svg>
361+
</button>`;
362+
}
363+
338364
renderNextPrevButtons() {
339365
return html`<div class="buttons">
340366
<button part="button button-prev" class="button button-prev" type="button">
341-
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16" part="svg">
367+
<svg
368+
xmlns="http://www.w3.org/2000/svg"
369+
viewBox="0 0 512 512"
370+
fill="currentColor"
371+
part="button-icon button-icon-prev"
372+
>
342373
<path
343-
fill-rule="evenodd"
344-
d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"
345-
></path>
374+
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"
375+
/>
346376
</svg>
347377
</button>
348378
349379
<button part="button button-next" class="button button-next" type="button">
350-
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16" part="svg">
380+
<svg
381+
xmlns="http://www.w3.org/2000/svg"
382+
viewBox="0 0 512 512"
383+
fill="currentColor"
384+
part="button-icon button-icon-next"
385+
>
351386
<path
352-
fill-rule="evenodd"
353-
d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"
354-
></path>
387+
d="M505 273c9.4-9.4 9.4-24.6 0-33.9L337 71c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l127 127-406.1 0c-13.3 0-24 10.7-24 24s10.7 24 24 24l406.1 0-127 127c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0L505 273z"
388+
/>
355389
</svg>
356390
</button>
357391
</div>`;
@@ -363,7 +397,7 @@ export default class Carousel extends LitElement {
363397
<div part="viewport" class="viewport">
364398
<slot part="container" class="container" @slotchange=${this.handleSlotChange}></slot>
365399
</div>
366-
${this.renderNextPrevButtons()}
400+
${this.withFullscreen ? this.renderFullscreenButton() : ''} ${this.renderNextPrevButtons()}
367401
${this.withDots
368402
? html`<div class="dots">
369403
${map(this.embla.scrollSnapList(), (_, index) => {

src/components/carousel/carousel.stories.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,44 @@ export const WithDots: Story = {
140140
`,
141141
};
142142

143+
export const Product: Story = {
144+
render: () => html`
145+
<zx-carousel single with-dots with-fullscreen>
146+
${repeat(
147+
Array.from({ length: 3 }),
148+
() => html`
149+
<zx-carousel-item>
150+
<img
151+
class="object-cover w-full h-96"
152+
src="https://cdn.laredoute.com/cdn-cgi/image/width=1200,height=1200,fit=pad,dpr=1/products/2/7/7/2771002a81df04419ccc3cd5c839e479.jpg"
153+
height="400"
154+
/>
155+
</zx-carousel-item>
156+
`,
157+
)}
158+
</zx-carousel>
159+
`,
160+
};
161+
162+
export const MoreProducts: Story = {
163+
render: () => html`
164+
<zx-carousel drag-free with-scrollbar style="--slide-size: calc(100% / 3); --slide-gap: 1rem;">
165+
${repeat(
166+
Array.from({ length: 10 }),
167+
() => html`
168+
<zx-carousel-item>
169+
<img
170+
class="object-cover w-full h-96"
171+
src="https://cdn.laredoute.com/cdn-cgi/image/width=1200,height=1200,fit=pad,dpr=1/products/2/7/7/2771002a81df04419ccc3cd5c839e479.jpg"
172+
height="400"
173+
/>
174+
</zx-carousel-item>
175+
`,
176+
)}
177+
</zx-carousel>
178+
`,
179+
};
180+
143181
export const WithAutoplay: Story = {
144182
render: () => html`
145183
<zx-carousel

src/components/carousel/carousel.styles.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default css`
2020
--slide-size: 100%;
2121
--slide-gap: 0;
2222
23-
--button-size: 40px;
23+
--button-size: 48px;
2424
--button-arrow-size: 20px;
2525
--button-arrow-color: #4b5563;
2626
--button-offset: 8px;
@@ -39,6 +39,8 @@ 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;
43+
4244
display: block;
4345
/* Note: moving this elsewhere (e.g wrapper) may bug the container translate position */
4446
position: relative;
@@ -62,6 +64,12 @@ export default css`
6264
overflow: hidden;
6365
}
6466
67+
:host([with-scrollbar]) .viewport {
68+
overflow: auto;
69+
scrollbar-color: var(--scrollbar-color); /* progress / track */
70+
scrollbar-width: thin;
71+
}
72+
6573
.container {
6674
backface-visibility: hidden;
6775
display: flex;
@@ -88,7 +96,8 @@ export default css`
8896
}
8997
9098
.button-next,
91-
.button-prev {
99+
.button-prev,
100+
.button-fullscreen {
92101
position: absolute;
93102
top: calc(50% - (var(--button-size) / 2));
94103
z-index: 1;
@@ -117,6 +126,11 @@ export default css`
117126
right: var(--button-offset);
118127
}
119128
129+
.button-fullscreen {
130+
right: var(--button-offset);
131+
top: var(--button-offset);
132+
}
133+
120134
@media (hover: hover) {
121135
.button:hover:not(:disabled) {
122136
box-shadow: var(--button-box-shadow-hover);

src/components/tooltip/tooltip.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,10 @@ export default class Tooltip extends LitElement {
145145

146146
render() {
147147
return html`
148-
${this.noArrow ? null : html`<i part="arrow" role="presentation"></i>`}
149-
<slot></slot>
148+
<div part="body" class="body">
149+
${this.noArrow ? null : html`<i part="arrow" role="presentation"></i>`}
150+
<slot></slot>
151+
</div>
150152
`;
151153
}
152154
}

src/components/tooltip/tooltip.styles.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,36 @@ import { css } from 'lit';
22

33
export default css`
44
:host {
5-
--background-color: #1f2937;
65
--arrow-size: 8px;
76
--arrow-color: var(--background-color);
7+
--background-color: #1f2937;
8+
--border-radius: 4px;
9+
--color: #fff;
10+
--font-size: 13px;
11+
--padding: 4px 8px;
812
--shadow: 0 1px 2px rgba(0, 0, 0, 0.16);
913
1014
position: absolute;
1115
isolation: isolate;
1216
display: block;
1317
box-sizing: border-box;
14-
padding: 4px 8px;
18+
19+
/* Customizable with CSS class */
1520
width: max-content;
1621
max-width: 180px;
17-
border-radius: 4px;
22+
border-radius: var(--border-radius);
1823
background-color: var(--background-color);
19-
color: #fff;
20-
font-size: 13px;
24+
color: var(--color);
25+
font-size: var(--font-size);
2126
filter: drop-shadow(var(--shadow));
2227
z-index: 10;
2328
}
2429
30+
.body {
31+
/* Avoid padding reset from tailwindcss */
32+
padding: var(--padding);
33+
}
34+
2535
i {
2636
position: absolute;
2737
display: block;

0 commit comments

Comments
 (0)