mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Added separator to checkbox and radio buttons
refs. https://github.com/TryGhost/Team/issues/3150
This commit is contained in:
parent
462f7a402b
commit
8f6d94cd5d
4 changed files with 67 additions and 38 deletions
|
@ -32,3 +32,13 @@ export const WithTitleAndHint: Story = {
|
|||
checked: true
|
||||
}
|
||||
};
|
||||
|
||||
export const WithSeparator: Story = {
|
||||
args: {
|
||||
title: 'Title',
|
||||
label: 'Checkbox 1',
|
||||
hint: 'Here\'s some hint',
|
||||
checked: true,
|
||||
separator: true
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Heading from './Heading';
|
||||
import Hint from './Hint';
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import Separator from './Separator';
|
||||
|
||||
interface CheckboxProps {
|
||||
id: string;
|
||||
|
@ -11,9 +12,10 @@ interface CheckboxProps {
|
|||
error?:boolean;
|
||||
hint?: React.ReactNode;
|
||||
checked?: boolean;
|
||||
separator?: boolean;
|
||||
}
|
||||
|
||||
const Checkbox: React.FC<CheckboxProps> = ({id, title, label, value, onChange, error, hint, checked}) => {
|
||||
const Checkbox: React.FC<CheckboxProps> = ({id, title, label, value, onChange, error, hint, checked, separator}) => {
|
||||
const [isChecked, setIsChecked] = useState(checked);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -27,22 +29,25 @@ const Checkbox: React.FC<CheckboxProps> = ({id, title, label, value, onChange, e
|
|||
};
|
||||
|
||||
return (
|
||||
<div className='flex flex-col gap-1'>
|
||||
{title && <Heading grey={true} level={6}>{title}</Heading>}
|
||||
<label className={`flex cursor-pointer items-start ${title && '-mb-1 mt-1'}`} htmlFor={id}>
|
||||
<input
|
||||
checked={isChecked}
|
||||
className="relative float-left mt-[3px] h-4 w-4 appearance-none border-2 border-solid border-grey-300 outline-none checked:border-green checked:bg-green checked:after:absolute checked:after:-mt-px checked:after:ml-[3px] checked:after:block checked:after:h-[11px] checked:after:w-[6px] checked:after:rotate-45 checked:after:border-[2px] checked:after:border-l-0 checked:after:border-t-0 checked:after:border-solid checked:after:border-white checked:after:bg-transparent checked:after:content-[''] hover:cursor-pointer focus:shadow-none focus:transition-[border-color_0.2s] dark:border-grey-600 dark:checked:border-green dark:checked:bg-green"
|
||||
id={id}
|
||||
type='checkbox'
|
||||
value={value}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
<div className={`ml-2 flex flex-col ${hint && 'mb-2'}`}>
|
||||
<span className={`inline-block text-md ${hint && '-mb-1'}`}>{label}</span>
|
||||
{hint && <Hint color={error ? 'red' : ''}>{hint}</Hint>}
|
||||
</div>
|
||||
</label>
|
||||
<div>
|
||||
<div className={`flex flex-col gap-1 ${separator && 'pb-2'}`}>
|
||||
{title && <Heading grey={true} level={6}>{title}</Heading>}
|
||||
<label className={`flex cursor-pointer items-start ${title && '-mb-1 mt-1'}`} htmlFor={id}>
|
||||
<input
|
||||
checked={isChecked}
|
||||
className="relative float-left mt-[3px] h-4 w-4 appearance-none border-2 border-solid border-grey-300 outline-none checked:border-green checked:bg-green checked:after:absolute checked:after:-mt-px checked:after:ml-[3px] checked:after:block checked:after:h-[11px] checked:after:w-[6px] checked:after:rotate-45 checked:after:border-[2px] checked:after:border-l-0 checked:after:border-t-0 checked:after:border-solid checked:after:border-white checked:after:bg-transparent checked:after:content-[''] hover:cursor-pointer focus:shadow-none focus:transition-[border-color_0.2s] dark:border-grey-600 dark:checked:border-green dark:checked:bg-green"
|
||||
id={id}
|
||||
type='checkbox'
|
||||
value={value}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
<div className={`ml-2 flex flex-col ${hint && 'mb-2'}`}>
|
||||
<span className={`inline-block text-md ${hint && '-mb-1'}`}>{label}</span>
|
||||
{hint && <Hint color={error ? 'red' : ''}>{hint}</Hint>}
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
{(separator || error) && <Separator color={error ? 'red' : ''} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -55,3 +55,12 @@ export const OptionHints: Story = {
|
|||
defaultSelectedOption: 'option-1'
|
||||
}
|
||||
};
|
||||
|
||||
export const WithSeparator: Story = {
|
||||
args: {
|
||||
title: 'Title',
|
||||
options: radioOptionsWithHints,
|
||||
defaultSelectedOption: 'option-1',
|
||||
separator: true
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Heading from './Heading';
|
||||
import Hint from './Hint';
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import Separator from './Separator';
|
||||
|
||||
export interface RadioOption {
|
||||
value: string;
|
||||
|
@ -16,9 +17,10 @@ interface RadioProps {
|
|||
error?:boolean;
|
||||
hint?: React.ReactNode;
|
||||
defaultSelectedOption?: string;
|
||||
separator?: boolean;
|
||||
}
|
||||
|
||||
const Radio: React.FC<RadioProps> = ({id, title, options, onSelect, error, hint, defaultSelectedOption}) => {
|
||||
const Radio: React.FC<RadioProps> = ({id, title, options, onSelect, error, hint, defaultSelectedOption, separator}) => {
|
||||
const [selectedOption, setSelectedOption] = useState(defaultSelectedOption);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -34,26 +36,29 @@ const Radio: React.FC<RadioProps> = ({id, title, options, onSelect, error, hint,
|
|||
};
|
||||
|
||||
return (
|
||||
<div className='flex flex-col gap-1'>
|
||||
{title && <Heading grey={true} level={6}>{title}</Heading>}
|
||||
{options.map(option => (
|
||||
<label key={option.value} className={`flex cursor-pointer items-start ${title && '-mb-1 mt-1'}`} htmlFor={option.value}>
|
||||
<input
|
||||
checked={selectedOption === option.value}
|
||||
className="relative float-left mt-[3px] h-4 w-4 appearance-none rounded-full border-2 border-solid border-grey-300 after:absolute after:z-[1] after:block after:h-3 after:w-3 after:rounded-full after:content-[''] checked:border-green checked:after:absolute checked:after:left-1/2 checked:after:top-1/2 checked:after:h-[0.625rem] checked:after:w-[0.625rem] checked:after:rounded-full checked:after:border-green checked:after:bg-green checked:after:content-[''] checked:after:[transform:translate(-50%,-50%)] hover:cursor-pointer focus:shadow-none focus:outline-none focus:ring-0 checked:focus:border-green dark:border-grey-600 dark:checked:border-green dark:checked:after:border-green dark:checked:after:bg-green dark:checked:focus:border-green"
|
||||
id={option.value}
|
||||
name={id}
|
||||
type='radio'
|
||||
value={option.value}
|
||||
onChange={handleOptionChange}
|
||||
/>
|
||||
<div className={`ml-2 flex flex-col ${option.hint && 'mb-2'}`}>
|
||||
<span className={`inline-block text-md ${option.hint && '-mb-1'}`}>{option.label}</span>
|
||||
{option.hint && <Hint>{option.hint}</Hint>}
|
||||
</div>
|
||||
</label>
|
||||
))}
|
||||
{hint && <Hint color={error ? 'red' : ''}>{hint}</Hint>}
|
||||
<div>
|
||||
<div className={`flex flex-col gap-1 ${separator && 'pb-2'}`}>
|
||||
{title && <Heading grey={true} level={6}>{title}</Heading>}
|
||||
{options.map(option => (
|
||||
<label key={option.value} className={`flex cursor-pointer items-start ${title && '-mb-1 mt-1'}`} htmlFor={option.value}>
|
||||
<input
|
||||
checked={selectedOption === option.value}
|
||||
className="relative float-left mt-[3px] h-4 w-4 appearance-none rounded-full border-2 border-solid border-grey-300 after:absolute after:z-[1] after:block after:h-3 after:w-3 after:rounded-full after:content-[''] checked:border-green checked:after:absolute checked:after:left-1/2 checked:after:top-1/2 checked:after:h-[0.625rem] checked:after:w-[0.625rem] checked:after:rounded-full checked:after:border-green checked:after:bg-green checked:after:content-[''] checked:after:[transform:translate(-50%,-50%)] hover:cursor-pointer focus:shadow-none focus:outline-none focus:ring-0 checked:focus:border-green dark:border-grey-600 dark:checked:border-green dark:checked:after:border-green dark:checked:after:bg-green dark:checked:focus:border-green"
|
||||
id={option.value}
|
||||
name={id}
|
||||
type='radio'
|
||||
value={option.value}
|
||||
onChange={handleOptionChange}
|
||||
/>
|
||||
<div className={`ml-2 flex flex-col ${option.hint && 'mb-2'}`}>
|
||||
<span className={`inline-block text-md ${option.hint && '-mb-1'}`}>{option.label}</span>
|
||||
{option.hint && <Hint>{option.hint}</Hint>}
|
||||
</div>
|
||||
</label>
|
||||
))}
|
||||
{hint && <Hint color={error ? 'red' : ''}>{hint}</Hint>}
|
||||
</div>
|
||||
{(separator || error) && <Separator color={error ? 'red' : ''} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue