Skip to content

Commit

Permalink
feat(common): toggle (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
kyechan99 committed Feb 16, 2024
1 parent bace2a8 commit 4e68586
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 0 deletions.
97 changes: 97 additions & 0 deletions src/components/common/Toggle/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { css } from '@emotion/react';
import styled from '@emotion/styled';
import * as React from 'react';

import { composeEventHandlers } from '@/libs/event';
import { SizeType } from '@/types/size';

export interface ToggleProps extends React.ComponentPropsWithoutRef<'button'> {
size?: SizeType;
selected?: boolean;
}

const ButtonSizeStyles = ({ size }: { size: SizeType }) => {
switch (size) {
case 'sm':
return css`
padding: 0.25rem;
`;
case 'lg':
return css`
padding: 0.75rem;
`;
case 'md':
default:
return css`
padding: 0.5rem;
`;
}
};

const StyledToggle = styled.button<ToggleProps>`
display: inline-flex;
padding: 0.5rem;
outline: none;
border-radius: 0.375rem;
font-weight: 500;
justify-content: center;
align-items: center;
white-space: nowrap;
cursor: pointer;
background-color: transparent;
border: 1px solid transparent;
&:focus {
box-shadow: 0 0 5px ${({ theme }) => theme.colors.gray['200']};
}
${({ disabled, theme }) =>
disabled &&
css`
opacity: 0.7;
background-color: ${theme.colors.gray['100']};
cursor: not-allowed;
`}
${({ selected, theme }) =>
selected
? css`
border: 1px solid ${theme.colors.gray['300']};
background-color: ${theme.colors.gray['200']};
`
: css`
&:hover {
opacity: 0.5;
background-color: ${theme.colors.gray['200']};
}
`}
${({ size }) => size && ButtonSizeStyles({ size })}
`;

export const Toggle = React.forwardRef<HTMLButtonElement, ToggleProps>(
({ className, selected = false, size, disabled = false, ...props }, ref) => {
const [sel, setSel] = React.useState<boolean>(selected);

React.useEffect(() => {
setSel(selected);
}, [selected]);

return (
<StyledToggle
type="button"
className={className}
ref={ref}
disabled={disabled}
size={size}
selected={sel}
onClick={composeEventHandlers(props.onClick, () => {
setSel(prev => !prev);
})}
{...props}
/>
);
},
);
Toggle.displayName = 'Input';
1 change: 1 addition & 0 deletions src/components/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ export * from './Label';
export * from './Switch';
export * from './Textarea';
export * from './Toast';
export * from './Toggle';
export * from './Tooltip';
export * from './Checkbox';
85 changes: 85 additions & 0 deletions src/stories/common/Toggle.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';

// import React from 'react';
import { Toggle, Tooltip } from '../..';

const meta = {
title: 'common/Toggle',
component: Toggle,
tags: ['autodocs'],
args: {
children: 'Toggle',
},
argTypes: {},
parameters: {
layout: 'centered',
componentSubtitle: 'Base Toggle',
docs: {
description: {
component: `Base Toggle of Everything.`,
},
},
},
} satisfies Meta<typeof Toggle>;

export default meta;

type Story = StoryObj<typeof Toggle>;

export const Default: Story = {
args: {
children: (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"></path>
<path d="M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"></path>
</svg>
),
},
};

export const Small: Story = {
args: {
size: 'sm',
...Default.args,
},
};

export const Large: Story = {
args: {
size: 'lg',
...Default.args,
},
};

export const WithTooltip: Story = {
args: {
...Default.args,
},
decorators: [
Story => {
return (
<Tooltip message="bold">
<Story />
</Tooltip>
);
},
],
};

export const Disabled: Story = {
args: {
disabled: true,
...Default.args,
},
};

0 comments on commit 4e68586

Please sign in to comment.