Extend 'FormGroup' to support Checkbox
This commit is contained in:
parent
d2e4be0776
commit
f4aa3fed77
4 changed files with 68 additions and 8 deletions
16
app/soapbox/components/ui/checkbox/checkbox.tsx
Normal file
16
app/soapbox/components/ui/checkbox/checkbox.tsx
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface ICheckbox extends Pick<React.InputHTMLAttributes<HTMLInputElement>, 'disabled' | 'id' | 'name' | 'onChange' | 'checked' | 'required'> { }
|
||||||
|
|
||||||
|
const Checkbox = React.forwardRef<HTMLInputElement, ICheckbox>((props, ref) => {
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
{...props}
|
||||||
|
ref={ref}
|
||||||
|
type='checkbox'
|
||||||
|
className='focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Checkbox;
|
|
@ -1,6 +1,10 @@
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
import Checkbox from '../checkbox/checkbox';
|
||||||
|
import HStack from '../hstack/hstack';
|
||||||
|
import Stack from '../stack/stack';
|
||||||
|
|
||||||
interface IFormGroup {
|
interface IFormGroup {
|
||||||
/** Input label message. */
|
/** Input label message. */
|
||||||
labelText?: React.ReactNode,
|
labelText?: React.ReactNode,
|
||||||
|
@ -23,6 +27,44 @@ const FormGroup: React.FC<IFormGroup> = (props) => {
|
||||||
{ id: formFieldId },
|
{ id: formFieldId },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const isCheckboxFormGroup = firstChild?.type === Checkbox;
|
||||||
|
|
||||||
|
if (isCheckboxFormGroup) {
|
||||||
|
return (
|
||||||
|
<HStack alignItems='start' space={2}>
|
||||||
|
{firstChild}
|
||||||
|
|
||||||
|
<Stack>
|
||||||
|
{labelText && (
|
||||||
|
<label
|
||||||
|
htmlFor={formFieldId}
|
||||||
|
data-testid='form-group-label'
|
||||||
|
className='-mt-0.5 block text-sm font-medium text-gray-700 dark:text-gray-400'
|
||||||
|
>
|
||||||
|
{labelText}
|
||||||
|
</label>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{errors?.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<p
|
||||||
|
data-testid='form-group-error'
|
||||||
|
className='mt-0.5 text-xs text-danger-900 bg-danger-200 rounded-md inline-block px-2 py-1 relative form-error'
|
||||||
|
>
|
||||||
|
{errors.join(', ')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{hintText && (
|
||||||
|
<p data-testid='form-group-hint' className='mt-0.5 text-xs text-gray-400'>
|
||||||
|
{hintText}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</HStack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
export { default as Avatar } from './avatar/avatar';
|
export { default as Avatar } from './avatar/avatar';
|
||||||
export { default as Button } from './button/button';
|
export { default as Button } from './button/button';
|
||||||
export { Card, CardBody, CardHeader, CardTitle } from './card/card';
|
export { Card, CardBody, CardHeader, CardTitle } from './card/card';
|
||||||
|
export { default as Checkbox } from './checkbox/checkbox';
|
||||||
export { default as Column } from './column/column';
|
export { default as Column } from './column/column';
|
||||||
export { default as Counter } from './counter/counter';
|
export { default as Counter } from './counter/counter';
|
||||||
export { default as Emoji } from './emoji/emoji';
|
export { default as Emoji } from './emoji/emoji';
|
||||||
|
|
|
@ -10,9 +10,8 @@ import { accountLookup } from 'soapbox/actions/accounts';
|
||||||
import { register, verifyCredentials } from 'soapbox/actions/auth';
|
import { register, verifyCredentials } from 'soapbox/actions/auth';
|
||||||
import { openModal } from 'soapbox/actions/modals';
|
import { openModal } from 'soapbox/actions/modals';
|
||||||
import BirthdayInput from 'soapbox/components/birthday_input';
|
import BirthdayInput from 'soapbox/components/birthday_input';
|
||||||
import { Form, FormGroup, FormActions, Button, Input, Textarea, Text } from 'soapbox/components/ui';
|
import { Checkbox, Form, FormGroup, FormActions, Button, Input, Textarea, Text } from 'soapbox/components/ui';
|
||||||
import CaptchaField from 'soapbox/features/auth_login/components/captcha';
|
import CaptchaField from 'soapbox/features/auth_login/components/captcha';
|
||||||
import { Checkbox } from 'soapbox/features/forms';
|
|
||||||
import { useAppSelector, useAppDispatch, useSettings, useFeatures } from 'soapbox/hooks';
|
import { useAppSelector, useAppDispatch, useSettings, useFeatures } from 'soapbox/hooks';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -328,24 +327,26 @@ const RegistrationForm: React.FC<IRegistrationForm> = ({ inviteToken }) => {
|
||||||
value={params.get('captcha_solution', '')}
|
value={params.get('captcha_solution', '')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='simple_form space-y-3'>
|
<FormGroup
|
||||||
|
labelText={intl.formatMessage(messages.agreement, { tos: <Link to='/about/tos' target='_blank' key={0}>{intl.formatMessage(messages.tos)}</Link> })}
|
||||||
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label={intl.formatMessage(messages.agreement, { tos: <Link to='/about/tos' target='_blank' key={0}>{intl.formatMessage(messages.tos)}</Link> })}
|
|
||||||
name='agreement'
|
name='agreement'
|
||||||
onChange={onCheckboxChange}
|
onChange={onCheckboxChange}
|
||||||
checked={params.get('agreement', false)}
|
checked={params.get('agreement', false)}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
{supportsEmailList && (
|
{supportsEmailList && (
|
||||||
|
<FormGroup labelText={intl.formatMessage(messages.newsletter)}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label={intl.formatMessage(messages.newsletter)}
|
|
||||||
name='accepts_email_list'
|
name='accepts_email_list'
|
||||||
onChange={onCheckboxChange}
|
onChange={onCheckboxChange}
|
||||||
checked={params.get('accepts_email_list', false)}
|
checked={params.get('accepts_email_list', false)}
|
||||||
/>
|
/>
|
||||||
)}
|
</FormGroup>
|
||||||
</div>
|
)}
|
||||||
|
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<Button type='submit'>
|
<Button type='submit'>
|
||||||
|
|
Loading…
Reference in a new issue