Skip to content

Commit

Permalink
feat: add theme for accordion and table (#195)
Browse files Browse the repository at this point in the history
Co-authored-by: bhenique <[email protected]>
  • Loading branch information
xmimiex and faire-des-economies-energie authored Sep 22, 2024
1 parent b8bbbf5 commit 6b6f712
Show file tree
Hide file tree
Showing 16 changed files with 180 additions and 54 deletions.
12 changes: 10 additions & 2 deletions apps/web/src/generated-examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ export const examples: Record<string, Example[]> = {
},
{
title: 'Styling accordion',
description: 'You can style accordion content and headers by passing tailwind classes into them.',
description: 'You can style accordion content and headers by passing tailwind classes into them or use a theme.',
url: '/examples/[theme-rtl]/accordion/05-styling-accordion',
content:
'import { component$ } from \'@builder.io/qwik\'\nimport { Accordion, Link } from \'flowbite-qwik\'\n\nexport default component$(() => {\n return (\n <Accordion>\n <Accordion.Panel>\n <Accordion.Header>Accordion 1</Accordion.Header>\n <Accordion.Content>\n <div>\n <p class="mb-2 text-gray-500 dark:text-gray-400">\n Flowbite is an open-source library of interactive components built on top of Tailwind CSS including buttons, dropdowns, modals, navbars,\n and more.\n </p>\n <p class="text-gray-500 dark:text-gray-400">\n Check out this guide to learn how to <Link href="/docs/getting-started/introduction/">get started</Link> and start developing websites\n even faster with components on top of Tailwind CSS.\n </p>\n </div>\n </Accordion.Content>\n </Accordion.Panel>\n <Accordion.Panel>\n <Accordion.Header class="bg-pink-200 dark:bg-pink-900 dark:text-gray-50">Accordion 2</Accordion.Header>\n <Accordion.Content>\n <div>\n <p class="mb-2 text-gray-500 dark:text-gray-400">\n Flowbite is an open-source library of interactive components built on top of Tailwind CSS including buttons, dropdowns, modals, navbars,\n and more.\n </p>\n <p class="text-gray-500 dark:text-gray-400">\n Check out this guide to learn how to <Link href="/docs/getting-started/introduction/">get started</Link> and start developing websites\n even faster with components on top of Tailwind CSS.\n </p>\n </div>\n </Accordion.Content>\n </Accordion.Panel>\n <Accordion.Panel>\n <Accordion.Header>Accordion 3</Accordion.Header>\n <Accordion.Content>\n <div>\n <p class="mb-2 text-gray-500 dark:text-gray-400">\n Flowbite is an open-source library of interactive components built on top of Tailwind CSS including buttons, dropdowns, modals, navbars,\n and more.\n </p>\n <p class="text-gray-500 dark:text-gray-400">\n Check out this guide to learn how to <Link href="/docs/getting-started/introduction/">get started</Link> and start developing websites\n even faster with components on top of Tailwind CSS.\n </p>\n </div>\n </Accordion.Content>\n </Accordion.Panel>\n </Accordion>\n )\n})',
'import { component$ } from \'@builder.io/qwik\'\nimport { Accordion, Link } from \'flowbite-qwik\'\n\nexport default component$(() => {\n return (\n <Accordion theme={{ header: { button: \'py-2\' } }}>\n <Accordion.Panel>\n <Accordion.Header>Accordion 1</Accordion.Header>\n <Accordion.Content>\n <div>\n <p class="mb-2 text-gray-500 dark:text-gray-400">\n Flowbite is an open-source library of interactive components built on top of Tailwind CSS including buttons, dropdowns, modals, navbars,\n and more.\n </p>\n <p class="text-gray-500 dark:text-gray-400">\n Check out this guide to learn how to <Link href="/docs/getting-started/introduction/">get started</Link> and start developing websites\n even faster with components on top of Tailwind CSS.\n </p>\n </div>\n </Accordion.Content>\n </Accordion.Panel>\n <Accordion.Panel>\n <Accordion.Header class="bg-pink-200 dark:bg-pink-900 dark:text-gray-50">Accordion 2</Accordion.Header>\n <Accordion.Content>\n <div>\n <p class="mb-2 text-gray-500 dark:text-gray-400">\n Flowbite is an open-source library of interactive components built on top of Tailwind CSS including buttons, dropdowns, modals, navbars,\n and more.\n </p>\n <p class="text-gray-500 dark:text-gray-400">\n Check out this guide to learn how to <Link href="/docs/getting-started/introduction/">get started</Link> and start developing websites\n even faster with components on top of Tailwind CSS.\n </p>\n </div>\n </Accordion.Content>\n </Accordion.Panel>\n <Accordion.Panel>\n <Accordion.Header>Accordion 3</Accordion.Header>\n <Accordion.Content>\n <div>\n <p class="mb-2 text-gray-500 dark:text-gray-400">\n Flowbite is an open-source library of interactive components built on top of Tailwind CSS including buttons, dropdowns, modals, navbars,\n and more.\n </p>\n <p class="text-gray-500 dark:text-gray-400">\n Check out this guide to learn how to <Link href="/docs/getting-started/introduction/">get started</Link> and start developing websites\n even faster with components on top of Tailwind CSS.\n </p>\n </div>\n </Accordion.Content>\n </Accordion.Panel>\n </Accordion>\n )\n})',
height: '300',
},
],
Expand Down Expand Up @@ -1939,6 +1939,14 @@ export const examples: Record<string, Example[]> = {
'import { component$ } from \'@builder.io/qwik\'\nimport { Link, Table } from \'flowbite-qwik\'\n\nexport default component$(() => {\n return (\n <div class="flex flex-col gap-8">\n <div class="overflow-x-auto">\n <Table>\n <Table.Head>\n <Table.HeadCell>Product name</Table.HeadCell>\n <Table.HeadCell>Color</Table.HeadCell>\n <Table.HeadCell>Category</Table.HeadCell>\n <Table.HeadCell>Price</Table.HeadCell>\n <Table.HeadCell>\n <span class="sr-only">Edit</span>\n </Table.HeadCell>\n </Table.Head>\n <Table.Body class="divide-y">\n <Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">\n <Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">{\'Apple MacBook Pro 17"\'}</Table.Cell>\n <Table.Cell>Sliver</Table.Cell>\n <Table.Cell>Laptop</Table.Cell>\n <Table.Cell>$2999</Table.Cell>\n <Table.Cell>\n <Link href="#">Edit</Link>\n </Table.Cell>\n </Table.Row>\n <Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">\n <Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">Microsoft Surface Pro</Table.Cell>\n <Table.Cell>White</Table.Cell>\n <Table.Cell>Laptop PC</Table.Cell>\n <Table.Cell>$1999</Table.Cell>\n <Table.Cell>\n <Link href="#">Edit</Link>\n </Table.Cell>\n </Table.Row>\n <Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">\n <Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">Magic Mouse 2</Table.Cell>\n <Table.Cell>Black</Table.Cell>\n <Table.Cell>Accessories</Table.Cell>\n <Table.Cell>$99</Table.Cell>\n <Table.Cell>\n <Link href="#">Edit</Link>\n </Table.Cell>\n </Table.Row>\n </Table.Body>\n </Table>\n </div>\n\n <div class="overflow-x-auto">\n <Table hoverable>\n <Table.Head>\n <Table.HeadCell>Product name</Table.HeadCell>\n <Table.HeadCell>Color</Table.HeadCell>\n <Table.HeadCell>Category</Table.HeadCell>\n <Table.HeadCell>Price</Table.HeadCell>\n <Table.HeadCell>\n <span class="sr-only">Edit</span>\n </Table.HeadCell>\n </Table.Head>\n <Table.Body class="divide-y">\n <Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">\n <Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">{\'Apple MacBook Pro 17"\'}</Table.Cell>\n <Table.Cell>Sliver</Table.Cell>\n <Table.Cell>Laptop</Table.Cell>\n <Table.Cell>$2999</Table.Cell>\n <Table.Cell>\n <Link href="#">Edit</Link>\n </Table.Cell>\n </Table.Row>\n <Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">\n <Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">Microsoft Surface Pro</Table.Cell>\n <Table.Cell>White</Table.Cell>\n <Table.Cell>Laptop PC</Table.Cell>\n <Table.Cell>$1999</Table.Cell>\n <Table.Cell>\n <Link href="#">Edit</Link>\n </Table.Cell>\n </Table.Row>\n <Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">\n <Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">Magic Mouse 2</Table.Cell>\n <Table.Cell>Black</Table.Cell>\n <Table.Cell>Accessories</Table.Cell>\n <Table.Cell>$99</Table.Cell>\n <Table.Cell>\n <Link href="#">Edit</Link>\n </Table.Cell>\n </Table.Row>\n </Table.Body>\n </Table>\n </div>\n </div>\n )\n})',
height: '500',
},
{
title: 'Table theme',
description: 'Use theme to customize styles of table',
url: '/examples/[theme-rtl]/table/06-table-theme',
content:
'import { component$ } from \'@builder.io/qwik\'\nimport { Link, Table } from \'flowbite-qwik\'\n\nexport default component$(() => {\n return (\n <div class="overflow-x-auto">\n <Table theme={{ cell: \'py-2\' }}>\n <Table.Head>\n <Table.HeadCell>Product name</Table.HeadCell>\n <Table.HeadCell>Color</Table.HeadCell>\n <Table.HeadCell>Category</Table.HeadCell>\n <Table.HeadCell>Price</Table.HeadCell>\n <Table.HeadCell>\n <span class="sr-only">Edit</span>\n </Table.HeadCell>\n </Table.Head>\n <Table.Body class="divide-y">\n <Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">\n <Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">{\'Apple MacBook Pro 17"\'}</Table.Cell>\n <Table.Cell>Sliver</Table.Cell>\n <Table.Cell>Laptop</Table.Cell>\n <Table.Cell>$2999</Table.Cell>\n <Table.Cell>\n <Link href="#">Edit</Link>\n </Table.Cell>\n </Table.Row>\n <Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">\n <Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">Microsoft Surface Pro</Table.Cell>\n <Table.Cell>White</Table.Cell>\n <Table.Cell>Laptop PC</Table.Cell>\n <Table.Cell>$1999</Table.Cell>\n <Table.Cell>\n <Link href="#">Edit</Link>\n </Table.Cell>\n </Table.Row>\n <Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">\n <Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">Magic Mouse 2</Table.Cell>\n <Table.Cell>Black</Table.Cell>\n <Table.Cell>Accessories</Table.Cell>\n <Table.Cell>$99</Table.Cell>\n <Table.Cell>\n <Link href="#">Edit</Link>\n </Table.Cell>\n </Table.Row>\n </Table.Body>\n </Table>\n </div>\n )\n})',
height: '300',
},
],
tabs: [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* title: Styling accordion
* description: You can style accordion content and headers by passing tailwind classes into them.
* description: You can style accordion content and headers by passing tailwind classes into them or use a theme.
* height: 300
*/

Expand All @@ -11,7 +11,7 @@ import { staticGenerateHandler } from '~/routes/examples/layout'

export default component$(() => {
return (
<Accordion>
<Accordion theme={{ header: { button: 'py-2' } }}>
<Accordion.Panel>
<Accordion.Header>Accordion 1</Accordion.Header>
<Accordion.Content>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* title: Table theme
* description: Use theme to customize styles of table
* height: 300
*/

import { component$ } from '@builder.io/qwik'
import { StaticGenerateHandler } from '@builder.io/qwik-city'
import { staticGenerateHandler } from '~/routes/examples/layout'
import { Link, Table } from 'flowbite-qwik'

export default component$(() => {
return (
<div class="overflow-x-auto">
<Table theme={{ cell: 'py-2' }}>
<Table.Head>
<Table.HeadCell>Product name</Table.HeadCell>
<Table.HeadCell>Color</Table.HeadCell>
<Table.HeadCell>Category</Table.HeadCell>
<Table.HeadCell>Price</Table.HeadCell>
<Table.HeadCell>
<span class="sr-only">Edit</span>
</Table.HeadCell>
</Table.Head>
<Table.Body class="divide-y">
<Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">
<Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">{'Apple MacBook Pro 17"'}</Table.Cell>
<Table.Cell>Sliver</Table.Cell>
<Table.Cell>Laptop</Table.Cell>
<Table.Cell>$2999</Table.Cell>
<Table.Cell>
<Link href="#">Edit</Link>
</Table.Cell>
</Table.Row>
<Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">
<Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">Microsoft Surface Pro</Table.Cell>
<Table.Cell>White</Table.Cell>
<Table.Cell>Laptop PC</Table.Cell>
<Table.Cell>$1999</Table.Cell>
<Table.Cell>
<Link href="#">Edit</Link>
</Table.Cell>
</Table.Row>
<Table.Row class="bg-white dark:border-gray-700 dark:bg-gray-800">
<Table.Cell class="whitespace-nowrap font-medium text-gray-900 dark:text-white">Magic Mouse 2</Table.Cell>
<Table.Cell>Black</Table.Cell>
<Table.Cell>Accessories</Table.Cell>
<Table.Cell>$99</Table.Cell>
<Table.Cell>
<Link href="#">Edit</Link>
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
</div>
)
})

export const onStaticGenerate: StaticGenerateHandler = async () => {
return staticGenerateHandler()
}
2 changes: 1 addition & 1 deletion packages/lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "flowbite-qwik",
"version": "0.37.2",
"version": "0.37.3",
"description": "Unofficial Qwik components built for Flowbite and Tailwind CSS",
"keywords": [
"design-system",
Expand Down
76 changes: 40 additions & 36 deletions packages/lib/src/components/Accordion/Accordion.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { JSXChildren, PropsOf, component$ } from '@builder.io/qwik'
import { JSXChildren, PropsOf, component$, useContextProvider, useStore } from '@builder.io/qwik'
import { AccordionHeaderProps, AccordionProps } from './accordion-types'

import { FunctionComponent } from '@builder.io/qwik/jsx-runtime'
import { AccordionPanel } from './AccordionPanel'
import uuid from '~/utils/uuid'
import { AccordionHeader } from './AccordionHeader'
import { AccordionContent } from './AccordionContent'
import { useAccordionState } from './composables/use-accordion-state'
import { getChild } from '~/utils/children-inspector'
import { AccordionContext } from '~/components/Accordion/composables/use-accordion-context'

type ChildrenType = {
header: {
Expand Down Expand Up @@ -86,38 +86,42 @@ type InnerAccordionProps = AccordionProps & {
components: ComponentType[]
}

export const InnerAccordion = component$<InnerAccordionProps>(({ components, alwaysOpen = false, openFirstItem = true, flush = false, ...attrs }) => {
const { toggle$, openedPanels } = useAccordionState(
{
alwaysOpen,
openFirstItem,
flush,
},
components,
)
export const InnerAccordion = component$<InnerAccordionProps>(
({ components, alwaysOpen = false, openFirstItem = true, flush = false, theme, ...attrs }) => {
useContextProvider(AccordionContext, useStore({ theme }))

const { toggle$, openedPanels } = useAccordionState(
{
alwaysOpen,
openFirstItem,
flush,
},
components,
)

return (
<div {...attrs}>
{components.map((component, i) => {
return (
<AccordionPanel>
<AccordionHeader
{...component.header.attrs}
id={component.id}
flush={flush}
isFirst={i === 0}
openedPanels={openedPanels.value}
isLast={i === components.length - 1}
onClick$={toggle$}
>
{component.header.children}
</AccordionHeader>
<AccordionContent id={component.id} isLast={i === components.length - 1} openedPanels={openedPanels.value} flush={flush}>
{component.content.children}
</AccordionContent>
</AccordionPanel>
)
})}
</div>
)
})
return (
<div {...attrs}>
{components.map((component, i) => {
return (
<AccordionPanel>
<AccordionHeader
{...component.header.attrs}
id={component.id}
flush={flush}
isFirst={i === 0}
openedPanels={openedPanels.value}
isLast={i === components.length - 1}
onClick$={toggle$}
>
{component.header.children}
</AccordionHeader>
<AccordionContent id={component.id} isLast={i === components.length - 1} openedPanels={openedPanels.value} flush={flush}>
{component.content.children}
</AccordionContent>
</AccordionPanel>
)
})}
</div>
)
},
)
7 changes: 6 additions & 1 deletion packages/lib/src/components/Accordion/AccordionHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ import { component$, Slot, useComputed$ } from '@builder.io/qwik'
import { useAccordionHeaderClasses } from './composables/use-accordion-header-class'
import { AccordionHeaderProps } from './accordion-types'
import { IconAngleDownOutline } from 'flowbite-qwik-icons'
import { useAccordionContext } from '~/components/Accordion/composables/use-accordion-context'
import { twMerge } from 'tailwind-merge'
import clsx from 'clsx'

export const AccordionHeader = component$<AccordionHeaderProps>(
({ id, openedPanels, flush = false, isLast = false, isFirst = false, onClick$, ...attrs }) => {
const { theme } = useAccordionContext()

const internalVisible = useComputed$(() => Boolean(id && openedPanels?.includes(id)) ?? false)
const internalFlush = useComputed$(() => flush)
const internalIsFirst = useComputed$(() => isFirst)
Expand All @@ -14,7 +19,7 @@ export const AccordionHeader = component$<AccordionHeaderProps>(

return (
<div class={attrs.class}>
<button type="button" class={headerClasses.value} onClick$={() => id && onClick$?.(id)}>
<button type="button" class={twMerge(headerClasses.value, clsx(theme.value?.header?.button))} onClick$={() => id && onClick$?.(id)}>
<span>
<Slot />
</span>
Expand Down
9 changes: 8 additions & 1 deletion packages/lib/src/components/Accordion/accordion-types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { PropsOf, QRL } from '@builder.io/qwik'
import { ClassList, PropsOf, QRL } from '@builder.io/qwik'

export type AccordionTheme = {
header?: {
button?: ClassList
}
}

export type AccordionProps = {
alwaysOpen?: boolean
openFirstItem?: boolean
flush?: boolean
theme?: AccordionTheme
}

export type AccordionHeaderProps = {
Expand Down
Loading

0 comments on commit 6b6f712

Please sign in to comment.