Last active
December 19, 2022 10:03
-
-
Save stephent/2ddacd523d14fa53eaa3324fe1d64669 to your computer and use it in GitHub Desktop.
General purpose switch component using headlessui, tailwind and react-hook-form
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useController, UseControllerProps } from "react-hook-form"; | |
import { Switch } from '@headlessui/react' | |
type Props = { | |
label?: string; | |
enabledLabel?: string; | |
disabledLabel?: string; | |
title?: string; | |
}; | |
function classNames(...classes) { | |
return classes.filter(Boolean).join(' ') | |
} | |
export const ControlledSwitch = (props: Props & UseControllerProps) => { | |
const { enabledLabel, disabledLabel, label, title } = props; | |
const { field: { value, onChange } } = useController(props); | |
return ( | |
<Switch.Group as="div" className="flex items-center"> | |
<>{(disabledLabel || label) && | |
<Switch.Label as="span" className="mr-3"> | |
<span className="text-sm font-medium text-gray-900">{disabledLabel || label}</span> | |
</Switch.Label> | |
}</> | |
<Switch | |
checked={value} | |
onChange={onChange} | |
title={title || ''} | |
className={classNames( | |
value ? 'bg-gray-700 hover:bg-gray-500' : 'bg-gray-200 hover:bg-gray-400', | |
'relative p-0 inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-100 focus:outline-none focus:ring-1 focus:ring-offset-2 focus:ring-gray-500' | |
)} | |
> | |
<span | |
aria-hidden="true" | |
className={classNames( | |
value ? 'translate-x-5' : 'translate-x-0', | |
'pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-100' | |
)} | |
/> | |
{title && | |
<span className="sr-only">{title}</span> | |
} | |
</Switch> | |
{enabledLabel && | |
<Switch.Label as="span" className="ml-3"> | |
<span className="text-sm font-medium text-gray-900">{enabledLabel}</span> | |
</Switch.Label> | |
} | |
</Switch.Group> | |
) | |
}; |
Thanks for creating this! 💪 Was just wondering how it's going to register the input element for the Switch
component?
Looking at the docs here (https://headlessui.com/react/switch#using-with-html-forms), headlessui states that we should pass in a name
prop so that it renders a hidden input element which acts as a form control.
Does this work without needing this additional input element (?)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Inspired by @jasonabullard 's List example. Refer to this for an example of how to use the component in a form.
Set
label
if you want a single label to the left of the switch. Set bothenabledLabel
anddisabledLabel
if you want value specific labels either side of the switch.