@swrve/core
Version:
Core set of Swrve UI Components
59 lines (49 loc) • 1.58 kB
JSX
import React, { useRef, useState } from 'react'
import { bool, func, string } from 'prop-types'
import { Icon } from '@swrve/icons'
const CollapsibleButton = ({ label = 'Toggle content', onChange, open }) => {
const itemIcon = open ? 'minus' : 'plus'
return (
<button
aria-expanded={open}
className="flex items-center text-sm select-none text-secondary-100 hover:text-secondary-120 focus:outline-none ml-auto py-2 mr-1"
onClick={onChange}
>
<span className="flex items-center justify-center w-4 h-4 mr-2 rounded-full bg-secondary-10">
<Icon name={itemIcon} size="xsmall" />
</span>
{label}
</button>
)
}
const Collapsible = ({ defaultIsOpen = false, children, isOpen, label, onChange, ...props }) => {
const { current: isControlled } = useRef(isOpen != null)
const [open, toggleOpen] = useState(() => (isControlled ? isOpen : defaultIsOpen))
function handleToggle(e) {
e.preventDefault()
onChange && onChange()
if (!isControlled) {
toggleOpen(!open)
}
}
if (isControlled && isOpen !== open) {
toggleOpen(isOpen)
}
return (
<div {...props}>
{open && children}
<CollapsibleButton label={label} open={open} onChange={handleToggle} />
</div>
)
}
export default Collapsible
Collapsible.propTypes = {
// Used to set initial state for uncontrolled version
defaultIsOpen: bool,
// isOpen & onChange used for controlled version
isOpen: bool,
onChange: func,
// Text to show on toggle button
label: string
}
Collapsible.displayName = 'Collapsible'