Skip to content

Commit

Permalink
:feat: Accordion asChild
Browse files Browse the repository at this point in the history
  • Loading branch information
lerte committed Dec 11, 2023
1 parent 0b0b332 commit 43d6c10
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,67 @@
import { tv, VariantProps } from 'tailwind-variants'
import { AccordionContext } from '../AccordionContext'

import React, {
useContext,
forwardRef,
cloneElement,
isValidElement
} from 'react'
import React, { useMemo, useContext, forwardRef } from 'react'

import { Slot } from '@actify/Slot'

const variants = tv({
base: 'transition-all duration-300 ease-in-out grid',
variants: {
open: {
active: {
true: 'grid-rows-[1fr]',
false: 'grid-rows-[0fr]',
undefined: 'grid-rows-[0fr]'
}
}
})

export interface AccordionContentProps
extends VariantProps<typeof variants>,
React.HTMLAttributes<HTMLDivElement> {
export type AccordionContentProps = {
index?: number
asChild?: boolean
children: React.ReactNode
}
children?: ((_?: any) => React.ReactNode) | React.ReactNode
} & VariantProps<typeof variants> &
React.HTMLAttributes<HTMLDivElement>

const AccordionContent: React.FC<AccordionContentProps> = forwardRef(
(props, ref?: React.Ref<HTMLDivElement>) => {
const { index, style, className, asChild, children, ...rest } = props
const { index, style, className, asChild, ...rest } = props
const { open } = useContext(AccordionContext)

// `asChild` allows the user to pass any element as the content
if (asChild && isValidElement(children)) {
return cloneElement(children, {
ref,
...rest,
...children.props,
className: variants({ className: children.props.className })
})
}
const active = useMemo(() => {
if (open !== undefined) {
return open[index as number]
}
}, [open, index])

return (
<div
{...rest}
ref={ref}
style={style}
className={variants({ className, open: open[index] })}
>
<p className="overflow-hidden">{children}</p>
</div>
)
if (asChild) {
return (
<Slot
ref={ref}
style={style}
{...{
active,
...rest
}}
className={variants({ className })}
>
{typeof rest.children === 'function'
? rest.children({ active })
: rest.children}
</Slot>
)
} else {
return (
<div
{...rest}
ref={ref}
style={style}
className={variants({ className, active })}
>
<p className="overflow-hidden">{rest.children}</p>
</div>
)
}
}
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const variants = tv({
export type AccordionHeaderProps = {
index?: number
asChild?: boolean
children?: ((_?: any) => React.ReactNode) | React.ReactNode
} & React.HTMLAttributes<HTMLElement>

const AccordionHeader: React.FC<AccordionHeaderProps> = forwardRef(
Expand Down Expand Up @@ -58,8 +59,7 @@ const AccordionHeader: React.FC<AccordionHeaderProps> = forwardRef(
className={variants({ className })}
>
{typeof rest.children === 'function'
? // @ts-expect-error
rest.children({ active })
? rest.children({ active })
: rest.children}
</Slot>
)
Expand Down

0 comments on commit 43d6c10

Please sign in to comment.