From eb87026b7bafbbbdecbbbcd5e546b37c6151a4a0 Mon Sep 17 00:00:00 2001 From: Adam Kudrna Date: Mon, 19 Apr 2021 21:35:18 +0200 Subject: [PATCH] Extend `FormLayoutCustomField` options to improve accessibility and design consistency (#174) New options: - `disabled` - `innerFieldSize` - `labelForId` - `required` - `validationState` --- .../FormLayout/FormLayoutCustomField.jsx | 82 ++++++++++-- .../FormLayout/FormLayoutCustomField.scss | 40 ++++++ .../components/layout/FormLayout/README.mdx | 126 +++++++++++++++++- .../__tests__/FormLayoutCustomField.test.jsx | 4 + .../FormLayoutCustomField.test.jsx.snap | 17 +-- src/lib/styles/settings/_form-fields.scss | 3 + webpack.config.js | 4 +- 7 files changed, 246 insertions(+), 30 deletions(-) diff --git a/src/lib/components/layout/FormLayout/FormLayoutCustomField.jsx b/src/lib/components/layout/FormLayout/FormLayoutCustomField.jsx index e82ab5f3..c0b6ef84 100644 --- a/src/lib/components/layout/FormLayout/FormLayoutCustomField.jsx +++ b/src/lib/components/layout/FormLayout/FormLayoutCustomField.jsx @@ -1,31 +1,62 @@ import PropTypes from 'prop-types'; import React from 'react'; +import getRootSizeClassName from '../../../helpers/getRootSizeClassName'; +import getRootValidationStateClassName from '../../../helpers/getRootValidationStateClassName'; import { withProviderContext } from '../../../provider'; import styles from './FormLayoutCustomField.scss'; +const renderLabel = (id, label, labelForId) => { + if (labelForId && label) { + return ( + + ); + } + + if (label) { + return ( +
+ {label} +
+ ); + } + + return null; +}; + export const FormLayoutCustomField = ({ children, fullWidth, id, + disabled, + innerFieldSize, label, + labelForId, layout, + required, + validationState, }) => (
- {label && ( -
- {label} -
- )} + {renderLabel(id, label, labelForId)}
- + - - Custom content + + Custom field content +👉 While you can set FormLayoutCustomField as `disabled`, `valid` or `required` +and its styles may affect contained form fields through CSS cascade, don't +forget to mirror the aforementioned properties to the contained form fields too +as API options as such are **not** inherited. + +### Label Alignment + +If you are in a situation with one or more box form fields inside your +FormLayoutCustomField, you may want to have its label aligned with the fields +inside. Since it's +[not quite possible to do this automatically](https://github.com/react-ui-org/react-ui/issues/265) +due to limited browser support, there is `innerFieldSize` option which accepts +any of existing box field sizes (small, medium, or large) and is intended right +for this task. + + + + + + + + + + + +### Validation States + +Custom fields support the same validation states as regular form fields to +provide labels with optional feedback style. + + + + + + Custom field content + + + + + +### Accessibility + +If possible, use the `labelForId` option to provide ID of contained form field +so the field remains accessible via custom field label. + +You can also specify size of contained form field so custom field label is +properly vertically aligned. + + + {() => { + const [isChecked, setIsChecked] = React.useState(false); + return ( + + + + + + + + + setIsChecked(!isChecked)} + checked={isChecked} + id="my-checkbox-field-custom-accessibility-1" + label="Another form field" + /> + + + + + + ) + }} + + ## Full Example This is a demo of all components supported by FormLayout. @@ -403,7 +511,7 @@ This is a demo of all components supported by FormLayout. -### FormLayoutCustomField +### FormLayoutCustomField API A place for custom content inside FormLayout. @@ -417,3 +525,13 @@ A place for custom content inside FormLayout. | `--rui-form-layout-horizontal-label-limited-width` | Label width in limited-width layout | | `--rui-form-layout-horizontal-label-default-width` | Label width in the default layout | | `--rui-form-layout-row-gap` | Gap between individual rows | + +### FormLayoutCustomField Theming + +FormLayoutCustomField can be styled using a small subset of +[other form fields theming options](/customize/theming/forms). + +| Custom Property | Description | +|------------------------------------------------------|--------------------------------------------------------------| +| `--rui-form-field-custom-default-surrounding-text-color` | Custom field label color in default state | +| `--rui-form-field-custom-disabled-surrounding-text-color` | Custom field label color in disabled-like state | diff --git a/src/lib/components/layout/FormLayout/__tests__/FormLayoutCustomField.test.jsx b/src/lib/components/layout/FormLayout/__tests__/FormLayoutCustomField.test.jsx index a5a4d135..ec306860 100644 --- a/src/lib/components/layout/FormLayout/__tests__/FormLayoutCustomField.test.jsx +++ b/src/lib/components/layout/FormLayout/__tests__/FormLayoutCustomField.test.jsx @@ -28,10 +28,14 @@ describe('rendering', () => { it('renders correctly with all props', () => { const tree = shallow(( Custom text in form 1 Custom text in form 2 diff --git a/src/lib/components/layout/FormLayout/__tests__/__snapshots__/FormLayoutCustomField.test.jsx.snap b/src/lib/components/layout/FormLayout/__tests__/__snapshots__/FormLayoutCustomField.test.jsx.snap index 2627acb1..84b40087 100644 --- a/src/lib/components/layout/FormLayout/__tests__/__snapshots__/FormLayoutCustomField.test.jsx.snap +++ b/src/lib/components/layout/FormLayout/__tests__/__snapshots__/FormLayoutCustomField.test.jsx.snap @@ -2,9 +2,7 @@ exports[`rendering renders correctly with a single child 1`] = `
-
Label -
+
({ devtool: argv.mode === 'production'