Skip to content

Commit

Permalink
feat: adds toggle input
Browse files Browse the repository at this point in the history
  • Loading branch information
AssisrMatheus committed Apr 11, 2023
1 parent b81fe30 commit 6c2af9a
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Added examples for time picker on `DatePickerInput`
- Added `ToggleInput` component

### Fixed

Expand Down
82 changes: 82 additions & 0 deletions src/components/ToggleInput/ToggleInput.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 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 { ToggleInput, ToggleInputProps } from '.';
import { colorOptions } from '../../prebuiltTailwindTheme';

export default {
title: 'Components/Inputs/Toggle',
component: ToggleInput,
argTypes: {
label: { defaultValue: 'Input' },
color: {
defaultValue: 'pui-primary',
control: {
type: 'select',
options: colorOptions
}
},
defaultChecked: {
control: {
type: 'boolean'
}
},
placeholder: {
defaultValue: 'Type here...',
control: {
type: 'text'
}
},
defaultValue: {
control: {
type: 'boolean'
}
},
disabled: {
control: {
type: 'boolean'
}
},
readOnly: {
control: {
type: 'boolean'
}
},
className: {
control: {
type: 'text'
}
},
onChange: { action: 'onChange' },
onBlur: { action: 'onBlur' },
onFocus: { action: 'onFocus' }
}
} as Meta;

/**
* A story that displays a ToggleInput example
*
* @param props the story props
*/
const Template: Story<ToggleInputProps> = (props) => {
const [checked, setChecked] = useState(false);

return <ToggleInput {...props} checked={checked} onChange={(e) => setChecked(e.target.checked)} />;
};

export const WithLabel = Template.bind({});

export const NoLabel = Template.bind({});
NoLabel.args = {
label: undefined
};

export const WithHelp = Template.bind({});
WithHelp.args = {
help: 'You can also have a help text'
};

export const WithError = Template.bind({});
WithError.args = {
error: 'Input is required'
};
64 changes: 64 additions & 0 deletions src/components/ToggleInput/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import classnames from 'classnames';
import { motion } from 'framer-motion';
import React from 'react';
import { HTMLParsedContent } from '../HTMLParsedContent';

const spring = {
type: 'spring',
stiffness: 700,
damping: 30
};

export type ToggleInputProps = Omit<
React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>,
'children' | 'type'
> & {
label?: string | React.ReactNode;
error?: string;
help?: string;
};

/**
* A toggle input component
*
* @param props the component props
* @param props.label the label of the input
* @param props.error the error message
* @param props.help help message if any
*/
export const ToggleInput: React.FC<ToggleInputProps> = ({ label, error, help, ...props }) => (
<div>
<label
className={classnames(props.className, {
'cursor-pointer': !props.disabled && !props.readOnly
})}
>
<input type="checkbox" {...props} className="hidden" />
<div className="flex items-center gap-2">
<div
className={classnames(
'h-6.5 flex w-10 rounded-xl border-2 border-solid bg-white p-0.5 transition-colors',
props.checked ? 'justify-end' : 'justify-start',
!props.disabled ? (error ? 'border-pui-error' : 'border-pui-placeholder-color') : 'border-gray-300'
)}
>
<motion.div
layout
className={classnames(
'h-4 w-4 rounded-lg transition-colors',
!props.disabled ? 'bg-pui-placeholder-color' : 'bg-gray-300'
)}
transition={spring}
/>
</div>
<span className="select-none">
{typeof label === 'string' ? <HTMLParsedContent content={label} className="max-w-none" /> : label}
</span>
</div>
</label>
<div>
{help && !error && <p className="pui-help-text-input">{help}</p>}
{error && <p className="pui-animate-fadeDown pui-help-text-input text-pui-error">{error}</p>}
</div>
</div>
);

0 comments on commit 6c2af9a

Please sign in to comment.