0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-18 02:21:47 -05:00

Added toggle component to AdminX design system

refs. https://github.com/TryGhost/Team/issues/3150
This commit is contained in:
Peter Zimon 2023-05-19 12:28:43 +02:00
parent f6e7f15c84
commit cce150d04e
4 changed files with 157 additions and 3 deletions

View file

@ -1,7 +1,11 @@
import React from 'react';
const Separator: React.FC = () => {
return <hr className='border-grey-300' />;
interface SeparatorProps {
color?: string;
}
const Separator: React.FC<SeparatorProps> = ({color}) => {
return <hr className={`border-${color ? color : 'grey-300'}`} />;
};
export default Separator;

View file

@ -19,7 +19,7 @@ const TextField: React.FC<ITextField> = ({inputRef, title, value, error, placeho
{title && <Heading grey={true} useLabelTag={true}>{title}</Heading>}
<input
ref={inputRef}
className={`-mx-1 h-10 border-b ${error ? `border-red` : `border-grey-300 hover:border-grey-500 focus:border-grey-900`} px-1 py-2 ${title && `mt-0`}`}
className={`-mx-1 h-10 border-b ${error ? `border-red` : `border-grey-500 hover:border-grey-600 focus:border-grey-900`} px-1 py-2 ${title && `mt-0`}`}
defaultValue={value}
placeholder={placeholder}
type='text'

View file

@ -0,0 +1,85 @@
import type {Meta, StoryObj} from '@storybook/react';
import Toggle from './Toggle';
const meta = {
title: 'Global / Toggle',
component: Toggle,
tags: ['autodocs'],
decorators: [(_story: any) => (<div style={{maxWidth: '400px'}}>{_story()}</div>)]
} satisfies Meta<typeof Toggle>;
export default meta;
type Story = StoryObj<typeof Toggle>;
export const Default: Story = {
args: {
id: 'default-toggle'
}
};
export const Checked: Story = {
args: {
id: 'default-toggle',
checked: true
}
};
export const Small: Story = {
args: {
id: 'default-toggle',
size: 'sm'
}
};
export const Large: Story = {
args: {
id: 'default-toggle',
size: 'lg'
}
};
export const WithLabel: Story = {
args: {
id: 'default-toggle',
label: 'Check me'
}
};
export const WithLabelAndHint: Story = {
args: {
id: 'default-toggle',
label: 'Check me',
hint: 'But only if you dare'
}
};
export const LeftToRight: Story = {
args: {
id: 'default-toggle',
label: 'Check me',
hint: 'But only if you dare',
direction: 'rtl'
}
};
export const WithSeparator: Story = {
args: {
id: 'default-toggle',
label: 'Check me',
hint: 'But only if you dare',
direction: 'rtl',
separator: true
}
};
export const Error: Story = {
args: {
id: 'default-toggle',
label: 'Check me',
hint: 'But only if you dare',
direction: 'rtl',
error: true,
separator: true
}
};

View file

@ -0,0 +1,65 @@
import React from 'react';
import Separator from './Separator';
type ToggleSizes = 'sm' | 'md' | 'lg';
type ToggleDirections = 'ltr' | 'rtl';
interface ToggleProps {
id: string;
color?: string;
checked?: boolean;
disabled?: boolean;
error?: boolean;
size?: ToggleSizes;
label?: React.ReactNode;
separator?: boolean;
direction?: ToggleDirections;
hint?: React.ReactNode;
}
const Toggle: React.FC<ToggleProps> = ({id, size, direction, label, hint, separator, error, checked}) => {
let sizeStyles = '';
let labelStyles = '';
switch (size) {
case 'sm':
sizeStyles = ' h-3 w-5 after:h-2 after:w-2 checked:after:ml-[1.0rem]';
labelStyles = 'mt-[-5.5px]';
break;
case 'lg':
sizeStyles = ' h-5 w-8 after:h-4 after:w-4 checked:after:ml-[1.4rem]';
labelStyles = 'mt-[-1px]';
break;
default:
sizeStyles = ' min-w-[28px] h-4 w-7 after:h-3 after:w-3 checked:after:ml-[1.4rem]';
labelStyles = 'mt-[-3px]';
break;
}
return (
<>
<div className={`flex items-start gap-2 ${direction === 'rtl' && 'justify-between'} ${separator && 'pb-2'}`}>
<input checked={checked}
className={`appearance-none rounded-full bg-grey-300 after:absolute after:z-[2] after:ml-0.5 after:mt-0.5 after:rounded-full after:border-none after:bg-white after:transition-[background-color_0.2s,transform_0.2s] after:content-[''] checked:bg-green checked:after:absolute checked:after:z-[2] checked:after:rounded-full checked:after:border-none checked:after:bg-white checked:after:transition-[background-color_0.2s,transform_0.2s] checked:after:content-[''] hover:cursor-pointer focus:outline-none focus:ring-0 focus:after:absolute focus:after:z-[1] focus:after:block focus:after:rounded-full focus:after:content-[''] checked:focus:border-green checked:focus:bg-green dark:bg-grey-600 dark:after:bg-grey-400 dark:checked:bg-green dark:checked:after:bg-green ${sizeStyles} ${direction === 'rtl' && ' order-2'}`}
id={id}
role="switch"
type="checkbox" />
{label &&
<div className={`flex flex-col ${direction === 'rtl' && 'order-1'} ${labelStyles}`}>
<label
className={`inline-block hover:cursor-pointer`}
htmlFor={id}
>
{label}
</label>
{hint && <span className={`text-xs ${error ? 'text-red' : 'text-grey-700'}`}>{hint}</span>}
</div>
}
</div>
{(separator || error) && <Separator color={error ? 'red' : ''} />}
</>
);
};
export default Toggle;