diff --git a/apps/website/src/components/menu/menu.tsx b/apps/website/src/components/menu/menu.tsx index 98bd15f75..77eec60c5 100644 --- a/apps/website/src/components/menu/menu.tsx +++ b/apps/website/src/components/menu/menu.tsx @@ -11,6 +11,10 @@ type Props = { export const Menu = component$(({ onClose$ }) => { const appState = useContext(APP_STATE); const menu = [ + { + label: 'Accordion', + path: `/docs/${appState.theme.toLowerCase()}/accordion`, + }, { label: 'Button', path: `/docs/${appState.theme.toLowerCase()}/button` }, { label: 'ButtonGroup', diff --git a/apps/website/src/routes/docs/daisy/accordion/index.tsx b/apps/website/src/routes/docs/daisy/accordion/index.tsx new file mode 100644 index 000000000..9c251bdca --- /dev/null +++ b/apps/website/src/routes/docs/daisy/accordion/index.tsx @@ -0,0 +1,56 @@ +import { component$, useStylesScoped$ } from '@builder.io/qwik'; +import { Accordion, AccordionItem } from '@qwik-ui/theme-daisy'; + +export default component$(() => { + useStylesScoped$(` + h1 { margin: 2rem 0; padding-top: 1rem; font-weight: bold; border-top: 1px dotted #222} + .container { width: 300px } Accordion {border: 1px solid white} + `); + return ( + <> +
+

This is the documentation for the Accordion

+ +

Accordion Example

+ + +
+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. + Accusamus aliquid architecto delectus deleniti dolor +

+
+
+ +
+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. + Accusamus aliquid architecto delectus deleniti dolor +

+
+
+
+ +

Accordion with Disabled Item Example

+ + +
+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. + Accusamus aliquid architecto delectus deleniti dolor +

+
+
+ +
+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. + Accusamus aliquid architecto delectus deleniti dolor +

+
+
+
+
+ + ); +}); diff --git a/apps/website/src/routes/docs/headless/accordion/index.tsx b/apps/website/src/routes/docs/headless/accordion/index.tsx new file mode 100644 index 000000000..f90e66c0e --- /dev/null +++ b/apps/website/src/routes/docs/headless/accordion/index.tsx @@ -0,0 +1,51 @@ +import { component$, useStylesScoped$ } from '@builder.io/qwik'; +import { Accordion, AccordionItem } from '@qwik-ui/headless'; + +export default component$(() => { + useStylesScoped$(` + h1 { margin: 2rem 0; padding-top: 1rem; font-weight: bold; border-top: 1px dotted #222} + .container { width: 300px } + `); + return ( +
+

This is the documentation for the Accordion

+ +

Accordion Example

+ + + +

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus + aliquid architecto delectus deleniti dolor +

+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus + aliquid architecto delectus deleniti dolor +

+
+
+ +

Accordion with Disabled Item Example

+ + +
+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. + Accusamus aliquid architecto delectus deleniti dolor +

+
+
+ +
+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. + Accusamus aliquid architecto delectus deleniti dolor +

+
+
+
+
+ ); +}); diff --git a/packages/daisy/src/components/accordion/accordion.tsx b/packages/daisy/src/components/accordion/accordion.tsx new file mode 100644 index 000000000..cd9ba55f1 --- /dev/null +++ b/packages/daisy/src/components/accordion/accordion.tsx @@ -0,0 +1,45 @@ +import { + component$, + HTMLAttributes, + PropFunction, + Slot, +} from '@builder.io/qwik'; + +import { + Accordion as HeadlessAccordion, + AccordionItem as HeadlessAccordionItem, +} from '@qwik-ui/headless'; +import { clsq } from '@qwik-ui/shared'; + +export type AccordionProps = HTMLAttributes; +export interface AccordionItemProps { + label: string; + disabled?: boolean; + class?: string; + style?: string; + onClick$?: PropFunction<() => void>; +} + +export const Accordion = component$((props: AccordionProps) => { + const { class: classNames, ...rest } = props; + return ( + + + + ); +}); + +export const AccordionItem = component$((props: AccordionItemProps) => { + const { class: classNames, ...rest } = props; + return ( + + + + ); +}); diff --git a/packages/daisy/src/index.ts b/packages/daisy/src/index.ts index fffdc8485..a752d328d 100644 --- a/packages/daisy/src/index.ts +++ b/packages/daisy/src/index.ts @@ -1,3 +1,4 @@ +export * from './components/accordion/accordion'; export * from './components/button/button'; export * from './components/progress/progress'; export * from './components/button-group/button-group'; diff --git a/packages/headless/src/components/accordion/accordion.tsx b/packages/headless/src/components/accordion/accordion.tsx new file mode 100644 index 000000000..4f720a761 --- /dev/null +++ b/packages/headless/src/components/accordion/accordion.tsx @@ -0,0 +1,100 @@ +import { + $, + component$, + createContextId, + HTMLAttributes, + PropFunction, + QRL, + Signal, + Slot, + useBrowserVisibleTask$, + useContext, + useContextProvider, + useSignal, + useStore, + useStylesScoped$, +} from '@builder.io/qwik'; + +export type AccordionProps = HTMLAttributes; + +export const accordionContext = + createContextId('accordion'); + +interface AccordionContextService { + items: HTMLElement[]; + setItemsBoxRef$: QRL<(ref: Signal) => void>; +} + +interface AccordionItemProps { + label: string; + disabled?: boolean; + class?: string; + style?: string; + onClick$?: PropFunction<() => void>; +} + +export const Accordion = component$((props: AccordionProps) => { + const items = useStore([]); + const itemsBoxRef = useSignal(); + const setItemsBoxRef$ = $((ref: Signal) => { + if (ref) { + itemsBoxRef.value = ref.value; + } + }); + const contextService: AccordionContextService = { + items, + setItemsBoxRef$, + }; + + useContextProvider(accordionContext, contextService); + + useBrowserVisibleTask$(() => { + contextService.setItemsBoxRef$(itemsBoxRef); + const items = itemsBoxRef.value?.querySelectorAll('div.item'); + if (items?.length) { + items.forEach((item) => contextService.items.push(item)); + } + }); + + return ( +
+ +
+ ); +}); + +export const AccordionItem = component$((props: AccordionItemProps) => { + useStylesScoped$(` + div.item .content { + display: none; + } + div.item[open] .content { + display: block; + } + `); + const contextService = useContext(accordionContext); + return ( +
+ +
+ +
+
+ ); +}); diff --git a/packages/headless/src/index.ts b/packages/headless/src/index.ts index 050dc6168..272160f47 100644 --- a/packages/headless/src/index.ts +++ b/packages/headless/src/index.ts @@ -1,3 +1,4 @@ +export * from './components/accordion/accordion'; export * from './components/button/button'; export * from './components/progress/progress'; export * from './components/button-group/button-group';