Skip to content

Commit

Permalink
[docs] Create the FormControl page (#32073)
Browse files Browse the repository at this point in the history
Co-authored-by: Benny Joo <[email protected]>
  • Loading branch information
michaldudak and hbjORbj authored Apr 1, 2022
1 parent 4974e73 commit a8f62b6
Show file tree
Hide file tree
Showing 14 changed files with 438 additions and 8 deletions.
123 changes: 123 additions & 0 deletions docs/data/base/components/form-control/BasicFormControl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import * as React from 'react';
import FormControlUnstyled, {
useFormControlUnstyled,
} from '@mui/base/FormControlUnstyled';
import InputUnstyled from '@mui/base/InputUnstyled';
import { styled } from '@mui/system';
import clsx from 'clsx';

const blue = {
100: '#DAECFF',
200: '#80BFFF',
400: '#3399FF',
600: '#0072E5',
};

const grey = {
50: '#F3F6F9',
100: '#E7EBF0',
200: '#E0E3E7',
300: '#CDD2D7',
400: '#B2BAC2',
500: '#A0AAB4',
600: '#6F7E8C',
700: '#3E5060',
800: '#2D3843',
900: '#1A2027',
};

const StyledInputElement = styled('input')(
({ theme }) => `
width: 320px;
font-size: 0.875rem;
font-family: IBM Plex Sans, sans-serif;
font-weight: 400;
line-height: 1.5;
color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]};
background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]};
border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]};
border-radius: 8px;
padding: 12px 12px;
&:hover {
background: ${theme.palette.mode === 'dark' ? '' : grey[100]};
border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]};
}
&:focus {
outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]};
}
`,
);

const Input = React.forwardRef(function CustomInput(props, ref) {
return (
<InputUnstyled components={{ Input: StyledInputElement }} {...props} ref={ref} />
);
});

const Label = styled(({ children, className }) => {
const formControlContext = useFormControlUnstyled();
const [dirty, setDirty] = React.useState(false);

React.useEffect(() => {
if (formControlContext?.filled) {
setDirty(true);
}
}, [formControlContext]);

if (formControlContext === undefined) {
return <p>{children}</p>;
}

const { error, required, filled } = formControlContext;
const showRequiredError = dirty && required && !filled;

return (
<p className={clsx(className, error || showRequiredError ? 'invalid' : '')}>
{children}
{required ? ' *' : ''}
</p>
);
})`
font-family: IBM Plex Sans, sans-serif;
font-size: 0.875rem;
margin-bottom: 4px;
&.invalid {
color: red;
}
`;

const HelperText = styled((props) => {
const formControlContext = useFormControlUnstyled();
const [dirty, setDirty] = React.useState(false);

React.useEffect(() => {
if (formControlContext?.filled) {
setDirty(true);
}
}, [formControlContext]);

if (formControlContext === undefined) {
return null;
}

const { required, filled } = formControlContext;
const showRequiredError = dirty && required && !filled;

return showRequiredError ? <p {...props}>This field is required.</p> : null;
})`
font-family: IBM Plex Sans, sans-serif;
font-size: 0.875rem;
`;

export default function UseFormControl() {
return (
<FormControlUnstyled defaultValue="" required>
<Label>Name</Label>
<Input />
<HelperText />
</FormControlUnstyled>
);
}
128 changes: 128 additions & 0 deletions docs/data/base/components/form-control/BasicFormControl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import * as React from 'react';
import FormControlUnstyled, {
useFormControlUnstyled,
} from '@mui/base/FormControlUnstyled';
import InputUnstyled, { InputUnstyledProps } from '@mui/base/InputUnstyled';
import { styled } from '@mui/system';
import clsx from 'clsx';

const blue = {
100: '#DAECFF',
200: '#80BFFF',
400: '#3399FF',
600: '#0072E5',
};

const grey = {
50: '#F3F6F9',
100: '#E7EBF0',
200: '#E0E3E7',
300: '#CDD2D7',
400: '#B2BAC2',
500: '#A0AAB4',
600: '#6F7E8C',
700: '#3E5060',
800: '#2D3843',
900: '#1A2027',
};

const StyledInputElement = styled('input')(
({ theme }) => `
width: 320px;
font-size: 0.875rem;
font-family: IBM Plex Sans, sans-serif;
font-weight: 400;
line-height: 1.5;
color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]};
background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]};
border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]};
border-radius: 8px;
padding: 12px 12px;
&:hover {
background: ${theme.palette.mode === 'dark' ? '' : grey[100]};
border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]};
}
&:focus {
outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]};
}
`,
);

const Input = React.forwardRef(function CustomInput(
props: InputUnstyledProps,
ref: React.ForwardedRef<HTMLDivElement>,
) {
return (
<InputUnstyled components={{ Input: StyledInputElement }} {...props} ref={ref} />
);
});

const Label = styled(
({ children, className }: { children?: React.ReactNode; className?: string }) => {
const formControlContext = useFormControlUnstyled();
const [dirty, setDirty] = React.useState(false);

React.useEffect(() => {
if (formControlContext?.filled) {
setDirty(true);
}
}, [formControlContext]);

if (formControlContext === undefined) {
return <p>{children}</p>;
}

const { error, required, filled } = formControlContext;
const showRequiredError = dirty && required && !filled;

return (
<p className={clsx(className, error || showRequiredError ? 'invalid' : '')}>
{children}
{required ? ' *' : ''}
</p>
);
},
)`
font-family: IBM Plex Sans, sans-serif;
font-size: 0.875rem;
margin-bottom: 4px;
&.invalid {
color: red;
}
`;

const HelperText = styled((props: {}) => {
const formControlContext = useFormControlUnstyled();
const [dirty, setDirty] = React.useState(false);

React.useEffect(() => {
if (formControlContext?.filled) {
setDirty(true);
}
}, [formControlContext]);

if (formControlContext === undefined) {
return null;
}

const { required, filled } = formControlContext;
const showRequiredError = dirty && required && !filled;

return showRequiredError ? <p {...props}>This field is required.</p> : null;
})`
font-family: IBM Plex Sans, sans-serif;
font-size: 0.875rem;
`;

export default function UseFormControl() {
return (
<FormControlUnstyled defaultValue="" required>
<Label>Name</Label>
<Input />
<HelperText />
</FormControlUnstyled>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<FormControlUnstyled defaultValue="" required>
<Label>Name</Label>
<Input />
<HelperText />
</FormControlUnstyled>
51 changes: 51 additions & 0 deletions docs/data/base/components/form-control/UseFormControl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as React from 'react';
import FormControlUnstyled, {
useFormControlUnstyled,
} from '@mui/base/FormControlUnstyled';

function CustomInput() {
const formControlContext = useFormControlUnstyled();

if (formControlContext === undefined) {
return null;
}

const { value, required, onChange, disabled, onFocus, onBlur } =
formControlContext;

return (
<input
value={value}
required={required}
onChange={onChange}
disabled={disabled}
onFocus={onFocus}
onBlur={onBlur}
/>
);
}

function ControlStateDisplay() {
const formControlContext = useFormControlUnstyled();
if (formControlContext === undefined) {
return null;
}

const { filled, focused } = formControlContext;

return (
<p>
{filled ? 'filled' : 'empty'}&nbsp;|&nbsp;
{focused ? 'focused' : 'not focused'}
</p>
);
}

export default function UseFormControl() {
return (
<FormControlUnstyled defaultValue="" required>
<CustomInput />
<ControlStateDisplay />
</FormControlUnstyled>
);
}
51 changes: 51 additions & 0 deletions docs/data/base/components/form-control/UseFormControl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as React from 'react';
import FormControlUnstyled, {
useFormControlUnstyled,
} from '@mui/base/FormControlUnstyled';

function CustomInput() {
const formControlContext = useFormControlUnstyled();

if (formControlContext === undefined) {
return null;
}

const { value, required, onChange, disabled, onFocus, onBlur } =
formControlContext;

return (
<input
value={value as string}
required={required}
onChange={onChange}
disabled={disabled}
onFocus={onFocus}
onBlur={onBlur}
/>
);
}

function ControlStateDisplay() {
const formControlContext = useFormControlUnstyled();
if (formControlContext === undefined) {
return null;
}

const { filled, focused } = formControlContext;

return (
<p>
{filled ? 'filled' : 'empty'}&nbsp;|&nbsp;
{focused ? 'focused' : 'not focused'}
</p>
);
}

export default function UseFormControl() {
return (
<FormControlUnstyled defaultValue="" required>
<CustomInput />
<ControlStateDisplay />
</FormControlUnstyled>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<FormControlUnstyled defaultValue="" required>
<CustomInput />
<ControlStateDisplay />
</FormControlUnstyled>
Loading

0 comments on commit a8f62b6

Please sign in to comment.