-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6c2af9a
commit 36ab417
Showing
5 changed files
with
181 additions
and
132 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// also exported from '@storybook/react' if you can deal with breaking changes in 6.1 | ||
import { Meta, Story } from '@storybook/react/types-6-0'; | ||
import React, { useState } from 'react'; | ||
import { ToggleButton, ToggleButtonProps } from '.'; | ||
import { colorOptions } from '../../prebuiltTailwindTheme'; | ||
import classnames from 'classnames'; | ||
import { puiColorClassnameMap } from '../../storybookMappers'; | ||
|
||
export default { | ||
title: 'Components/Inputs/ToggleButton', | ||
component: ToggleButton, | ||
argTypes: { | ||
offLabel: { defaultValue: 'Off' }, | ||
onLabel: { defaultValue: 'On' }, | ||
color: { | ||
defaultValue: 'pui-primary', | ||
control: { | ||
type: 'select', | ||
options: colorOptions | ||
} | ||
}, | ||
defaultChecked: { | ||
control: { | ||
type: 'boolean' | ||
} | ||
}, | ||
disabled: { | ||
control: { | ||
type: 'boolean' | ||
} | ||
}, | ||
className: { | ||
control: { | ||
type: 'text' | ||
} | ||
}, | ||
onChange: { action: 'onChange' }, | ||
onBlur: { action: 'onBlur' }, | ||
onFocus: { action: 'onFocus' } | ||
} | ||
} as Meta; | ||
|
||
/** | ||
* A story that displays a ToggleButton example | ||
* | ||
* @param props the story props | ||
* @param props.color User selected color | ||
*/ | ||
const Template: Story<ToggleButtonProps & { color?: string }> = ({ color, ...props }) => { | ||
const [checked, setChecked] = useState(false); | ||
|
||
return ( | ||
<ToggleButton | ||
{...props} | ||
className={classnames( | ||
{ [puiColorClassnameMap[color || 'transparent']]: color !== 'pui-primary' }, | ||
props.className | ||
)} | ||
checked={checked} | ||
onChange={(e) => { | ||
setChecked(e.target.checked); | ||
if (props.onChange) props.onChange(e); | ||
}} | ||
/> | ||
); | ||
}; | ||
|
||
export const Default = Template.bind({}); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import classnames from 'classnames'; | ||
import { motion } from 'framer-motion'; | ||
import React from 'react'; | ||
|
||
const spring = { | ||
type: 'spring', | ||
stiffness: 700, | ||
damping: 36 | ||
}; | ||
|
||
export type ToggleButtonProps = Omit< | ||
React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, | ||
'children' | 'type' | ||
> & { | ||
/** | ||
* Label text for the button's off state | ||
*/ | ||
offLabel: string; | ||
/** | ||
* Label text for the button's on state | ||
*/ | ||
onLabel: string; | ||
}; | ||
|
||
/** | ||
* A toggle input component | ||
* | ||
* @param props the component props | ||
* @param props.offLabel Label text for the button's off state | ||
* @param props.onLabel Label text for the button's on state | ||
*/ | ||
export const ToggleButton: React.FC<ToggleButtonProps> = ({ offLabel, onLabel, ...props }) => ( | ||
<motion.label | ||
layout | ||
layoutRoot | ||
className={classnames( | ||
'flex w-fit relative border rounded-full items-center justify-around overflow-hidden', | ||
{ 'cursor-pointer': !props.disabled && !props.readOnly, 'select-none': !props.readOnly }, | ||
!props.disabled ? 'border-black' : 'border-gray-300', | ||
props.className | ||
)} | ||
> | ||
{/* Hidden input so it fakes as a real html input and can be used with forms, it also gives us the full range of event inputs to listen to */} | ||
<input type="checkbox" {...props} className="hidden" /> | ||
|
||
{[offLabel, onLabel].map((label, index) => { | ||
const selected = (!props.checked && index === 0) || (props.checked && index === 1); | ||
return ( | ||
// This defines the sizing that the background will copy from | ||
<div key={index} className="relative w-fit flex items-center justify-center px-8 py-1"> | ||
{/* Label text */} | ||
<p className={classnames(selected ? (!props.disabled ? 'text-white' : 'text-gray-500') : 'text-gray-400')}> | ||
{label} | ||
</p> | ||
|
||
{/* This is the background that will get animated on toggle */} | ||
{selected ? ( | ||
<motion.div | ||
className={classnames( | ||
'absolute -z-10 inset-0 rounded-full', | ||
!props.disabled ? 'bg-pui-placeholder-color' : 'bg-gray-100' | ||
)} | ||
layoutId="underline" | ||
transition={spring} | ||
/> | ||
) : null} | ||
</div> | ||
); | ||
})} | ||
</motion.label> | ||
); |
Oops, something went wrong.