Skip to content

Commit

Permalink
feat(component): add carousel component (#258)
Browse files Browse the repository at this point in the history
* feat(component): add carousel component

Adds a carousel component using a hook for maximum headlessness.

124

* feat: export Carousel to headless index

* docs: add Carousel to docs

* fix: add unique keys

* docs: update docs of Carousel

* feat: make Carousel a11y frierndly

* fix: relocate use-methods into ts files

* feat: integrate Carousel with child components

* docs: update Carousel with child components pattern

* feat(Carousel): clean up css

* feat: improve aria keyboard navigation

* feat: pass axe tests

* feat: improve styling & keyboard supports

* docs: add parts of Carousel

* feat: add aria-current to Carousel Item

* feat: remove control prop

---------

Co-authored-by: Greg Ederer <[email protected]>
Co-authored-by: Giorgio Boa <[email protected]>
  • Loading branch information
3 people authored Apr 8, 2023
1 parent a52d865 commit d258189
Show file tree
Hide file tree
Showing 11 changed files with 1,034 additions and 0 deletions.
4 changes: 4 additions & 0 deletions apps/website/src/components/menu/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ export const Menu = component$<Props>(({ onClose$ }) => {
path: `/docs/${appState.theme.toLowerCase()}/button-group`,
},
{ label: 'Card', path: `/docs/${appState.theme.toLowerCase()}/card` },
{
label: 'Carousel',
path: `/docs/${appState.theme.toLowerCase()}/carousel`,
},
{
label: 'Collapse',
path: `/docs/${appState.theme.toLowerCase()}/collapse`,
Expand Down
137 changes: 137 additions & 0 deletions apps/website/src/routes/docs/headless/carousel/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import {
component$,
useId,
useSignal,
useStylesScoped$,
} from '@builder.io/qwik';
import { Carousel } from '@qwik-ui/headless';

const {
Controls,
Control,
Item,
Items,
Root,
ButtonNext,
ButtonPrevious,
IconNext,
IconPrevious,
} = Carousel;

export const ITEMS: { src: string; title: string }[] = Array.from({
length: 4,
}).map(() => ({
src: 'https://picsum.photos/1200/550',
title: 'My great image',
}));

export default component$(() => {
const { scopeId } = useStylesScoped$(`
h1 { margin: 2rem 0; padding-top: 1rem; font-weight: bold; border-top: 1px dotted #222}
h2 { margin-block: 1.15em 0.5em; font-size: xx-large; }
h3 { margin-block: 0.85em 0.35em; font-size: x-large; }
hr { margin-block: 2em; }
.form-item, hr { width: 35em; }
.outter {
display: grid;
}
.inner {
display: flex;
align-items: center;
}
.controls {
padding: 2em;
margin-inline: auto;
display: flex;
justify-content: center;
gap: 0.5em;
}
.control {
width: 2em;
aspect-ratio: 1/1;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: all .3s .1s ease-out;
cursor: pointer;
}
.control[aria-current="true"] {
font-weight: 900;
}
.item {
height: 500px;
width: 100%;
object-fit: cover;
}
`);

const items = useSignal(ITEMS);

return (
<>
<p>This is the documentation for the Carousel</p>

<h2>Carousel Example</h2>

<Root class="outter" startAt={1} loop={false}>
<div class="inner">
<ButtonPrevious>
<IconPrevious />
</ButtonPrevious>
<Items>
{items.value.map(({ src, title }, i) => (
<Item key={useId()} index={i} label={title}>
<img src={src} class="item" />
</Item>
))}
</Items>
<ButtonNext>
<IconNext />
</ButtonNext>
</div>
<Controls class={[scopeId, 'controls']}>
{items.value.map((_, i) => (
<Control key={useId()} index={i} class={[scopeId, 'control']}>
{i + 1}
</Control>
))}
</Controls>
</Root>

<hr />

<h3>Inputs</h3>

<ul>
<li>startAt: number, default 0</li>
<li>loop: boolean, default true</li>
</ul>

<h3>Parts</h3>

<ul>
<li>Root</li>
<li>Items & Item</li>
<li>ButtonPrevious</li>
<li>ButtonNext</li>
<li>Controls & Control</li>
</ul>

<hr />

<h3>Outputs</h3>

<ul>
<li></li>
</ul>
</>
);
});
Loading

0 comments on commit d258189

Please sign in to comment.