Skip to content

Commit

Permalink
Merge pull request #15 from mynamesleon/v0.3.9
Browse files Browse the repository at this point in the history
V0.3.9
  • Loading branch information
mynamesleon authored Aug 29, 2024
2 parents d60da27 + 685a815 commit 9404d05
Show file tree
Hide file tree
Showing 47 changed files with 763 additions and 492 deletions.
5 changes: 4 additions & 1 deletion ACCESSIBILITY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Accessibility When Developing and Testing

![Author: Leon Slater](https://img.shields.io/badge/Author-Leon_Slater-blue)
![Last update: 2024/08/05](https://img.shields.io/badge/Last_updated-2024/08/25-blue)

Accessibility is a core part of this library and the components it contains. So, at a minimum, all components should be tested with the following document in mind.

## Automated testing
Expand Down Expand Up @@ -27,7 +30,7 @@ These considerations will cover most scenarios, particularly at a component leve
- does any essential complex functionality have keyboard-only alternatives? (e.g. drag and drop)
3. **Is it clear and functional for users without vision?**
- points (1) and (2) above will do most of this for you
- **test using at least NVDA** as it is one of the most widely used screen-readers (bonus points for also testing with other screen-readers, such as TalkBack, Windows Narrator, and VoiceOver)
- **test using at least NVDA** as it is one of the most widely used screen-readers (bonus points for also testing with other screen-readers, such as TalkBack, Windows Narrator, and VoiceOver). In particular, **test with a screen-reader using only your keyboard**: does everything you can tab to have an announcement that clearly indicates what it's for?
- Consider if there are elements that need additional text (e.g. icon buttons), or if there are elements that a screen-reader can ignore (e.g. purely presentation iconography that you could set `aria-hidden="true"` for)
4. **Does it work at a viewport width of 320px?**
- This is to account for the "reflow" criterion: no loss of content or functionality occurs, and horizontal scrolling is avoided
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

![License: MIT](https://img.shields.io/npm/l/rea11y-easy-form)
![NPM version](https://img.shields.io/npm/v/rea11y-easy-form.svg)
![Types](https://img.shields.io/npm/types/rea11y-easy-form)
![Tree Shaking](https://flat.badgen.net/bundlephobia/tree-shaking/rea11y-easy-form)
![Types: TypeScript](https://img.shields.io/npm/types/rea11y-easy-form)
![Tree Shaking: Supported](https://badgen.net/bundlephobia/tree-shaking/rea11y-easy-form)

![React](https://img.shields.io/badge/React-%2320232a.svg?logo=React&logoColor=%2361DAFB)
![React Final Form](https://img.shields.io/badge/React%20Final%20Form-%23333639.svg?logo=react&logoColor=white)
Expand Down
411 changes: 170 additions & 241 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"@babel/preset-env": "^7.25.4",
"@babel/preset-typescript": "^7.24.7",
"@chromatic-com/storybook": "^1.7.0",
"@rollup/plugin-commonjs": "^26.0.1",
Expand All @@ -83,7 +83,7 @@
"@storybook/react-webpack5": "^8.2.9",
"@storybook/test": "^8.2.9",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.0",
"@types/dompurify": "^3.0.5",
"@types/jest": "^29.5.12",
Expand Down Expand Up @@ -116,7 +116,7 @@
"rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-typescript2": "^0.36.0",
"storybook": "^8.2.9",
"ts-jest": "^29.2.4",
"ts-jest": "^29.2.5",
"typescript": "^5.5.4"
},
"dependencies": {
Expand Down
99 changes: 51 additions & 48 deletions src/Roadmap.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,80 +4,83 @@ import { Meta } from '@storybook/blocks';

# Roadmap

![Author: Leon Slater](https://img.shields.io/badge/Author-Leon_Slater-blue)

## For 1.0

### Core component exports

* `EasyForm`
* `EasyField`
- `EasyForm`
- `EasyField`

### Form field components

* `Input`
* `Textarea`
* `Checkbox`
* `CheckboxList`
* `ColorInput`
* `Radio`
* `RadioList`
* `Select`
* `Switch`
* `SwitchList`
* `AutoComplete` ✓ (supports multi-select)
- `Input`
- `Textarea`
- `Checkbox`
- `CheckboxList`
- `ColorInput`
- `Radio`
- `RadioList`
- `Select`
- `Switch`
- `SwitchList`
- `AutoComplete` ✓ (supports multi-select)

### Util components (used by form components, and exported)

* `Fieldset` ✓ (also a container)
* `ErrorMessage`
* `Label`
* `Notice` ✓ (looks like an alert, but not a `role='alert'` element by default)
* `Skeleton` ✓ (for loading states)
* `ValidationSummary`
* `VisuallyHidden`
- `Fieldset` ✓ (also a container)
- `ErrorMessage`
- `Label`
- `MutatedFormSpy`
- `Notice` ✓ (looks like an alert, but not a `role='alert'` element by default)
- `Skeleton` ✓ (for loading states)
- `ValidationSummary`
- `VisuallyHidden`

### Container/unique components

* `AsHtml`
* `Disclosure`
* `Fieldset` ✓ (also a util)
* `FieldRepeater` ✓ (unit tests and thorough manual testing ongoing)
* `FieldConditional`
- `AsHtml`
- `Disclosure`
- `Fieldset` ✓ (also a util)
- `FieldRepeater` ✓ (unit tests and thorough manual testing ongoing)
- `FieldConditional`

### Utility/Form functionality hooks

* `useAnnounce` ✓ (for easy screen-reader announcements)
* `useFieldValue` ✓ (for easy form field value fetching)
* `useCheckFieldValue` ✓ (for confirming a field (or fields) has the desired value(s))
* `useMutatedField` ✓ (for correcting async validation state issues)
* `useMutatedFormState` ✓ (for correcting async validation state issues)
- `useAnnounce` ✓ (for easy screen-reader announcements)
- `useFieldValue` ✓ (for easy form field value fetching)
- `useCheckFieldValue` ✓ (for confirming a field (or fields) has the desired value(s))
- `useMutatedField` ✓ (for correcting async validation state issues)
- `useMutatedFormState` ✓ (for correcting async validation state issues)

### Built-in validation functions

Only the most basic built-in rules to be included. We do not want to bloat the package.

* `isAlpha`
* `isAlphaNumeric`
* `isDate`
* `isEmail`
* `isEmpty` ✓ (reversed for `required` rule)
* `isHexColor`
* `isInteger`
* `isLowerCase`
* `isNumber`
* `isUpperCase`
* `isUrl`
- `isAlpha`
- `isAlphaNumeric`
- `isDate`
- `isEmail`
- `isEmpty` ✓ (reversed for `required` rule)
- `isHexColor`
- `isInteger`
- `isLowerCase`
- `isNumber`
- `isUpperCase`
- `isUrl`

### Miscellaneous / Chore

* Wide-spread CSS variables for easier theming? (not strictly necessary)
* Proper Generics handling for components that take an `as` prop
- Wide-spread CSS variables for easier theming? (not strictly necessary)
- Proper Generics handling for components that take an `as` prop

## Beyond 1.0 ideas

### Form field components

* `StarRating` (how granular? E.g. can it display 3.5 out of 5, but only allow selecting full values?)
* `RichTextEditor` (do we want this as part of the core code? Will be big!)
* `Datepicker` (do we want this? Can use native, and custom can be added)
* `Timepicker` (do we want this? Can use native, and custom can be added)
* `Telephone` (do we want this? Is complex. Can use native, and custom can be added)
- `StarRating` (how granular? E.g. can it display 3.5 out of 5, but only allow selecting full values?)
- `RichTextEditor` (do we want this as part of the core code? Will be big!)
- `Datepicker` (do we want this? Can use native, and custom can be added)
- `Timepicker` (do we want this? Can use native, and custom can be added)
- `Telephone` (do we want this? Is complex. Can use native, and custom can be added)
4 changes: 2 additions & 2 deletions src/components/CheckboxList/CheckboxList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react';
import { render } from '@testing-library/react';
import CheckboxList from './CheckboxList';
import SwitchList, { SWITCH_LIST_TYPE } from '../SwitchList';
import { CheckboxListProps } from './CheckboxList.types';
import { fieldClassName } from '../../utils';
import type { SwitchListProps } from '../SwitchList/SwitchList.types';

jest.mock('../SwitchList', () => ({
__esModule: true,
Expand All @@ -12,7 +12,7 @@ jest.mock('../SwitchList', () => ({
}));

describe('<CheckboxList />', () => {
let props: CheckboxListProps;
let props: Omit<SwitchListProps, 'type'>;

beforeEach(() => {
props = {
Expand Down
33 changes: 16 additions & 17 deletions src/components/CheckboxList/CheckboxList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,25 @@ import clsx from 'clsx';
import { isEqual } from '@react-hookz/deep-equal';
import { useFieldClassName } from '../../utils';
import SwitchList, { SWITCH_LIST_TYPE } from '../SwitchList';
import { CheckboxListProps } from './CheckboxList.types';
import type { SwitchListProps } from '../SwitchList/SwitchList.types';

const CheckboxList = forwardRef<HTMLFieldSetElement, CheckboxListProps>(
({ className, ...other }, ref) => {
const classPrefix = useFieldClassName('checkbox-list');
return (
<SwitchList
{...other}
ref={ref}
type={SWITCH_LIST_TYPE.CHECKBOX}
className={clsx(className, classPrefix)}
/>
);
}
);
const CheckboxList = forwardRef<
HTMLFieldSetElement,
Omit<SwitchListProps, 'type'>
>(({ className, ...other }, ref) => {
const classPrefix = useFieldClassName('checkbox-list');
return (
<SwitchList
{...other}
ref={ref}
type={SWITCH_LIST_TYPE.CHECKBOX}
className={clsx(className, classPrefix)}
/>
);
});

// do a deep equal comparison in this case,
// to account for lazy use of the `options` prop
// @todo: confirm if there is any performance benefit by memoising here,
// as the base SwitchList already does a deepEqual props comparison
// to account for the `options` prop being an inline array
const MemoisedCheckboxList = memo(CheckboxList, isEqual);
MemoisedCheckboxList.displayName = 'CheckboxList';
export default MemoisedCheckboxList;
3 changes: 0 additions & 3 deletions src/components/CheckboxList/CheckboxList.types.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/EasyField/EasyFieldField/EasyFieldField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ const EasyFieldField = ({

// @todo: setting classes based on meta state could cause a lot of DOM updates
// e.g. from the `validating` state on each keypress;
// if `validateFields` is also used, then this could
// if `validateFields` is also used, then this could
// cause a lot of extra DOM updates on the page.
// So we should test the impact of this, and maybe put this behind a prop
const metaClassNames = useDeepCompareMemo(
Expand Down
99 changes: 0 additions & 99 deletions src/components/EasyField/useEasyFieldValidator.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { capitaliseFirstLetter } from '../../../utils';

const handleValidatorOutcome = (
result?: any,
key?: string,
val?: any
): string | undefined => {
if (result) {
return typeof result === 'string'
? result
: typeof val === 'string'
? val
: capitaliseFirstLetter(key);
}
};

export default handleValidatorOutcome;
Loading

0 comments on commit 9404d05

Please sign in to comment.