diff --git a/apps/element-storybook/src/bs4-migration/MigrationExamples.tsx b/apps/element-storybook/src/bs4-migration/MigrationExamples.tsx new file mode 100644 index 000000000..b84123b6a --- /dev/null +++ b/apps/element-storybook/src/bs4-migration/MigrationExamples.tsx @@ -0,0 +1,134 @@ +import { useEffect, useRef, useState } from 'react'; +import { + Badge, + Button, + Chip, + Dialog, + DialogActions, + DialogContent, + DialogContentText, + DialogTitle, + Grid, + IconButton, + MailIcon, + Menu, + MenuItem, + MoreVerticalIcon, + Tab, + Tabs, + ThemeProvider, +} from '@availity/element'; + +export const BadgeExample = () => ( + + + + + +); + +export const ChipExample = () => ( + + + +); + +export const GridExample = () => ( + + 8 + 4 + 4 + 8 + +); + +export const MenuExample = () => { + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + const handleClose = () => { + setAnchorEl(null); + }; + + return ( + + + + + + Action 1 + Action 2 + Action 3 + + + ); +}; + +export const DialogExample = () => { + const [open, setOpen] = useState(false); + + const handleOpen = () => { + setOpen(true); + }; + + const handleClose = () => { + setOpen(false); + }; + + return ( + + + + + Availity Dialog + + + Dialog Text + + + + + + + + ); +}; + +export const TabExample = () => { + const [value, setValue] = useState(0); + + const handleChange = (event: React.SyntheticEvent, newValue: number) => { + setValue(newValue); + }; + + return ( + + + + + + + + ); +}; diff --git a/apps/element-storybook/src/bs4-migration/form-migration.stories.mdx b/apps/element-storybook/src/bs4-migration/form-migration.stories.mdx new file mode 100644 index 000000000..4d31ac31e --- /dev/null +++ b/apps/element-storybook/src/bs4-migration/form-migration.stories.mdx @@ -0,0 +1,418 @@ +import { Meta, Source } from '@storybook/blocks'; + + + +# Form Migration + +For the `@availity/element` components we have chosen to move away from any +built-in form management. While there's flexibility to use your library of +choice, internally we have replaced `formik` with `react-hook-form`. +For existing forms utilizing `@availity/react` and `formik`, +some refactor is required. + +## Why the change? + +The future of `formik` is looking questionable - The current major version released +in 2019 with sparse feature work and dependency updates since. +We were faced with the question of what to replace it with, but also if it +_should_ be replaced at all. + +We have chosen the middle ground. Our form components are no longer tied to +one library for validation and state management. However, after a successful +internal implementation of an extremely long and complicated form using +`react-hook-form`, we decided to move forward with it for any internal form +components, like the feedback component, and recommend it for use with `@availity/element`. + +`react-hook-form` is very lightweight and flexible. It also boasts a +large community and is actively and regularly supported. `react-hook-form` +utilizes it's own internal rules engine for validation, but can be used +with schema-based validation libraries like `yup`, `zod`, and `joi` +when used with the corresponding resolver package. See the +[react-hook-form docs](https://react-hook-form.com/get-started#SchemaValidation) +for more. + +We've included examples using only `react-hook-form` as well as +using it with `yup`+`@hookform/resolvers/yup` (don't worry, +`@hookform/resolvers` is an official part of `react-hook-form`) + +## react-hook-form Installation + + + +OR + + + +## Form Examples + +- Form with `@availity/react`, `formik`, and `yup` +- Form with `@availity/element`, `react-hook-form`, `yup` and `@hookform/resolvers/yup` +- Form with `@availity/element`, `formik`, and `yup` (Not Recommended) +- Form with `@availity/element`, `react-hook-form`, and `react-hook-form` Internal Rules + + +At the moment, @availity/element does not export a `
` component. +Instead, use the native `` element. You can then use +`react-hook-form`'s `useForm` hook to manage your form. + +### Form with `@availity/react`, `formik`, and `yup` + + { + const ref = useRef(); + return ( + key === 'Escape' && onClose()} + initialValues={{ + textField: "", + selectField: undefined, + radio: "", + }} + validationSchema={yup.object().shape({ + textField: yup + .string() + .max(200, 'Text Field cannot exceed 200 characters.') + .required('This field is required.'), + selectField: yup + .string() + .required('This Field is required.') + .nullable(), + radio: yup + .string() + .required('A selection is required'), + })} + {...formProps} + onSubmit={(values) => sendValues(values)} + > + + + + + + + + + + ); +}; +`}/> + +### Form with `@availity/element`, `react-hook-form`, `yup` and `@hookform/resolvers/yup` + + { + const { + register, + handleSubmit, + formState: { errors }, + control, + reset, + getValues, + } = useForm({ + defaultValues: { + textField: "", + selectField: undefined, + radio: "", + }, + mode: 'onTouched', + resolver: yupResolver(yup.object().shape({ + textField: yup + .string() + .max(200, 'Text Field cannot exceed 200 characters.') + .required('This field is required.'), + selectField: yup + .string() + .required('This Field is required.') + .nullable(), + radio: yup + .string() + .required('A selection is required'), + })), + }); + return ( +
+ + + { + return ( + { + if (reason === 'clear') { + onChange(null); + } + onChange(value); + }} + onBlur={onBlur} + FieldProps={{ + margin:"normal", + label: 'Select Field', + placeholder: 'Value', + required: true, + error: !!errors.selectField?.message, + helperText: errors.selectField?.message, + }} + options={dropdownOptions} + value={value || null} + /> + ); + }} + /> + + + Radio Group + + ( + + } value="1" label="Option 1" /> + } value="2" label="Option 2" /> + + )} + /> + {errors.radio ? {errors.radio?.message} : null } + + + + ) +} +`}/> + +You can find more working examples of react-hook-form [here](/docs/layouts-form--docs). + +### Form with `@availity/element`, `formik`, and `yup` (Not Recommended) + +It does not save much time/effort reformatting to keep `formik` versus switching +over to `react-hook-form`, therefore we don't recommend this approach to migrate. + + ( + console.log(values)} + > + {formik => ( + + + + { + formik.setFieldValue("selectField", value !== null ? value.value : formik.initialValues.selectField) + }} + onBlur={formik.handleBlur} + FieldProps={{ + margin:"normal", + label: 'Select Field', + placeholder: 'Value', + required: true, + error: formik.touched.selectField && Boolean(formik.errors.selectField), + helperText: formik.touched.selectField && formik.errors.selectField, + }} + options={[{label:"Option 1", value: "1"}, {label:"Option 2", value: "2"}]} + value={formik.values.selectField} + /> + + Radio 1 + + } label="Radio 1" value="1" /> + } label="Radio 2" value="2" /> + + {formik.touched.radio && Boolean(formik.errors.radio) ? + {formik.errors.radio} + : null + } + + + + + )} + +); +`}/> + +### Form with `@availity/element`, `react-hook-form`, and `react-hook-form` Internal Rules + + { + const { + register, + handleSubmit, + formState: { errors }, + control, + reset, + getValues, + } = useForm({defaultValues: { textField: "", selectField: "", radio: ""}}); + return ( +
+ + + { + return ( + { + if (reason === 'clear') { + onChange(null); + } + onChange(value); + }} + onBlur={onBlur} + FieldProps={{ + margin:"normal", + label: 'Select Field', + placeholder: 'Value', + required: true, + error: !!errors.selectField?.message, + helperText: errors.selectField?.message, + }} + options={dropdownOptions} + value={value || null} + /> + ); + }} + /> + + + Radio Group + + ( + + } value="1" label="Option 1" /> + } value="2" label="Option 2" /> + + )} + /> + {errors.radio ? {errors.radio?.message} : null } + + + Submit + + + ) +} +`}/> diff --git a/apps/element-storybook/src/bs4-migration/migration.stories.mdx b/apps/element-storybook/src/bs4-migration/migration.stories.mdx new file mode 100644 index 000000000..bd04869dc --- /dev/null +++ b/apps/element-storybook/src/bs4-migration/migration.stories.mdx @@ -0,0 +1,169 @@ +import { Markdown } from '@storybook/blocks'; +import { Meta, Source } from '@storybook/blocks'; +import { BadgeExample, ChipExample, DialogExample, GridExample, MenuExample, TabExample } from './MigrationExamples'; + + + +# Getting Started + +
+ +## Planning and Strategy + +_Our guide is written assuming you're planning migration one component swap at a time. However, if you're doing whole sections at a time pay extra attention to the [Components Without a Drop-in Option](#components-without-a-drop-in-option) section to plan accordingly._ + +### Drop-in Components and the Migration Theme + +To help break up the work needed for migration, we have created a bootstrap migration theme. The migration theme should allow you to slowly start replacing components without disrupting your design until you are ready to upgrade to the new theme. + +The migration theme is accessible by passing `theme='legacyBS'` to the `ThemeProvider` + +#### Recommended Early Component Swaps + +- layout (`Box`, `Grid`, `Container`) +- `Typography` (semantic html swaps, see Native HTML Replacements section) +- `BlockUI` +- `Menu` +- `Alert` +- `Card` + +### Form + +Where you're coming from will determine your strategy for form migration. We have moved away from `formik` (used by `@availity/form`) in favor of `react-hook-form`. We have also provided the base components to utilize with your own logic/libraries. + +See the [Form migration](/?path=/docs/bs4-migration-form-migration) docs for more information. + +### Components Without a Drop-in Option + +There are many bootstrap elements and other design guidelines that will not be making it into the new Element Design System. These components we recommend saving for last so the changes will be introduced as you are switching to the new theme. + +For all Design Patterns and UX Guidelines, visit the [Zeroheight Docs](https://zeroheight.com/2e36e50c7/n/53a73e) + +#### Required UX changes + +- button + - button patterns, placement, and allowed colors have changed. Will need to follow new patterns even for v0. +- buttongroup + - Element is moving away from a typical buttongroup in favor of a collection of non-connected buttons. (buttons can still be placed within a form group or component with aria role of _group_, but there will not be visually attached buttons when grouped.) +- chip (previously badge) + - Colors for chips are now reserved exclusively for statuses, otherwise the Chip must be grey. +- icon + - icon sizing is more logical in MUI, but very different. If using large icons, it may be easier to go straight to phase 1 patterns. +- list-group + - does not exist in Mui. UX to provide new design guidelines for how to change this component. +- jumbotron + - bootstrap got rid of this in bootstrap 5 and there are no plans on making an equivalent in Element. + +
+ +## Element Installation + +To install the library in your project, you can use either NPM or Yarn: + + + +OR + + + +
+ +## Element Usage + +The [@availity/element](https://availity.github.io/element/?path=/docs/element--docs) package contains all of the components and hooks for the design system. We recommend using this package when you want to use multiple components. + +To use the components in your project, you will need to import them first: + + + +Make sure all of the components you use are inside the `ThemeProvider` component. We recommend placing it in your root `index.{js|tsx}` file. + + { + return {/* Application code. Most likely a router. */}; +}; +`}/> + +
+ +## Pattern Differences: MUI vs Reactstrap/Bootstrap + +### Composition and Custom Components + +There are a few gotchas when creating components. This is a brief overview taken from the [Mui Composition Docs](https://mui.com/material-ui/guides/composition). Visit the Mui docs for more details and code examples. + +- Refs (most common issue so far) + - When using a custom component for `children` or `component` make sure it can take a ref. This means for function components to wrap it in a `forwardRef`. +- Wrapping Components that have `muiName` property + - If you're wrapping a component that has the `muiName` property, be sure to also assign it to the wrapped component. +- Using the `component` property to replace the root element + - avoid inline functions and pass a static component instead + - be aware of prop name collisions when prop forwarding + - with Typescript: the type of the props should be used with type arguments + +### Common Props + +- `tag`: While Reactstrap uses `tag` to change the root element, Mui uses `component`. See [Composition](#composition-and-custom-components) notes above. +- `pill`/`outline`/etc: Different styling variations are now contained within the `variant` prop. + +### Styling: Bootstrap Utility Classes -> Mui System Properties + +> **NOTE** +> Avoid overwriting theme styles when possible as this may cause issues or rework when switching off the legacy theme. Always first try using the default styling for a component vs immediately migrating the bootstrap styles of the component that's being replaced. + +Instead of the utility classes used by Bootstrap, MUI uses the [System Properties](https://mui.com/system/properties/) prop. + +`
...` becomes `...` + +While there's the css properties that you'd expect, MUI also uses similar shorthand notations to bootstrap + +| Bootstrap Class | MUI Sx Value | +| :-- | :-- | +| `margin-left-1` | `marginLeft: '4px'` | +| `ml-1` | `ml: .5` | +| `ml-2` | `ml: 1` | +| `ml-3` | `ml: 2` | +| `mx-1` | `mx: .5` | +| `m-1` | `m: .5` | +| `d-flex` | `display: 'flex'` | +| `text-primary` | `color: 'text.link'` | + +Many system properties can access styles from the theme, like colors and spacings. i.e. `bgColor: 'background.canvas'` or `bgColor: 'action.hover'`. + +### Native HTML Replacements + +Without the bootstrap utility classes, it's important to know which MUI components can be used to take advantage of MUI styling + +| Usage | HTML | MUI | +| ----- | ---- | --- | +| layout | `div`, `span` | `Box`unstyled element, most versatile. The go-to when styling any element, i.e. pass `form` to `component` to add styles to your form.`Container`fixed width based on screensize, generally used on top level of app`Grid`two dimensional layouts`Stack`one dimensional layouts | +| semantic/structure | headers(`h1`, `h2`, etc), `body`, `caption`, etc | `Typography``variant` prop sets tag and styling, tag can be overwritten with `component` to keep the styling of a different variant. i.e. an `h2` with the styling of an `h5` | +| tables | `table`, `thead`, `tr`, `th`, `td`, etc | Semantic replacements (`Table`, `TableHead`, `TableRow`, `TableCell`, etc) along with additional common components (`TablePagination`, `TableSortLabel`, etc) | + +### Component Equivalents + +Not all classes/components from Bootstrap/Reactstrap have a similar name or 1:1 equivalent in MUI. Listed below are some notable changes + +| Bootstrap | MUI | Description | Sample | +| ------------------- | ---------- | ------------------------------------------ | :------------------: | +| `Badge`1 | `Badge` | Small corner overlay of base element | | +| `Badge`2 | `Chip` | Inline colored label/descriptor | | +| `Column`/`Row` | `Grid` | Horizontal and Vertical layout | | +| `Dropdown` | `Menu` | Display a list on temporary surface | +| `Modal` | `Dialog` | Popover Dialog (Blocking and Non-Blocking) | | +| `Nav` | `Tab` | Tab Navigation | | +| `Navbar` | `AppBar` | Navigation Header | | +| `Toast` | `Snackbar` | Brief Notifications | | diff --git a/apps/element-storybook/src/form-migration.stories.mdx b/apps/element-storybook/src/form-migration.stories.mdx deleted file mode 100644 index bef32c6cb..000000000 --- a/apps/element-storybook/src/form-migration.stories.mdx +++ /dev/null @@ -1,118 +0,0 @@ -import { Meta, Source } from '@storybook/blocks'; - - - -# Form Migration - -For the `@availity/element` components, we have chosen to move away from -`formik` in favor of `react-hook-form`. For exiting forms utilizing -`@availity/react` and `formik`, some refactor is required. - -## Why `react-hook-form`? - -After a successful internal implementation of an extremely long and -complicated form using `react-hook-form`, we decided to move forward with -it. `react-hook-form` is very lightweight and flexible. It also boasts a -large community and is actively and regularly supported. - -## Installation - - - -OR - - - -## Usage - -At the moment, @availity/element does not export a `
` component. -Instead, use the native `` element. You can then use -`react-hook-form`'s `useForm` hook to manage your form. Below is the same -form implemented in `formik` and rewritten in react-hook-form. - -### Example: Form component with `formik` and `@availity/react` - - { - const ref = useRef(); - return ( - key === 'Escape' && onClose()} - initialValues={{ - textField1: undefined, - }} - validationSchema={yup.object().shape({ - textField1: yup - .string() - .max(200, 'Text Field cannot exceed 200 characters.') - .required('This field is required.'), - })} - {...formProps} - onSubmit={(values) => sendValues(values)} - > - - - - ); -}; -`}/> - -### Example: form component with `react-hook-form` and `@availity/element` - - { - const { - formState: { errors }, - handleSubmit, - register, - } = useForm({ - defaultValues: { textField1: "" } - }); - return ( -
- - - Submit - - - ) -} -`}/> - -You can find more working examples of react-hook-form [here](/docs/layouts-form--docs). diff --git a/apps/element-storybook/src/introduction.stories.mdx b/apps/element-storybook/src/introduction.stories.mdx deleted file mode 100644 index 14a50e812..000000000 --- a/apps/element-storybook/src/introduction.stories.mdx +++ /dev/null @@ -1,41 +0,0 @@ -import { Meta } from '@storybook/addon-docs'; - - - -# What is `@availity/element`? - -The vision behind `@availity/element` is to build a wholistic design system -rather than simply a collection of components. The components are built in -collaboration with the UX team and based on larger patterns. This helps -create a cohesive experience across applications and frees up developers to -focus on rapid innovation. - -## Why MUI? - -Basing `@availity/element` on MUI allows us to streamline processes across -the development cycle. - -- MUI integrates with Figma enabling UX to quickly produce designs that - closely match the actual components. - -- MUI's components allow for greater flexibility and less abstraction. - This enables developers to focus on business logic and innovation rather - than component limitations. - -- MUI handles a lot of baseline accessibility logic such as tab and - keyboard interactions. - -- MUI's theming engine makes it easy to implement global updates to the - look and feel. - -## Current State - -The goals of the current version of `@availity/element` include building a -cohesive design system with an eye on easing the migration process. The -initial release will provide a solid path towards 508 compliance and -baseline component-level telemetry. - -## Future Plans - -In upcoming versions of the design system, internationalization will be a -focus. diff --git a/apps/element-storybook/src/migration.stories.mdx b/apps/element-storybook/src/migration.stories.mdx deleted file mode 100644 index c640d5554..000000000 --- a/apps/element-storybook/src/migration.stories.mdx +++ /dev/null @@ -1,112 +0,0 @@ -import { Meta, Source } from '@storybook/blocks'; -import { Badge, Chip, MailIcon, ThemeProvider } from '@availity/element'; - - - -## Installation - -To install the library in your project, you can use either NPM or Yarn: - - - -OR - - - -## Usage - -The [@availity/element](https://availity.github.io/element/?path=/docs/element--docs) package contains all of the components and hooks for the design system. We recommend using this package when you want to use multiple components. - -To use the components in your project, you will need to import them first: - - - -Make sure all of the components you use are inside the `ThemeProvider` component. We recommend placing it in your root `index.{js|tsx}` file. - - { - return {/* Application code. Most likely a router. */}; -}; -`}/> - -## Pattern Differences - -### Composition and Custom Components - -There are a few gotchas when creating components. This is a brief overview taken from the [Mui Composition Docs](https://mui.com/material-ui/guides/composition). Visit the Mui docs for more details and code examples. - -- Refs (most common issue so far) - - When using a custom component for `children` or `component` make sure it can take a ref. This means for function components to wrap it in a `forwardRef`. -- Wrapping Components that have `muiName` property - - If you're wrapping a component that has the `muiName` property, be sure to also assign it to the wrapped component. -- Using the `component` property to replace the root element - - avoid inline functions and pass a static component instead - - be aware of prop name collisions when prop forwarding - - with Typescript: the type of the props should be used with type arguments - -### Common Props - -- `tag`: While Reactstrap uses `tag` to change the root element, Mui uses `component`. See [Composition](#composition-and-custom-components) notes above. -- `pill`/`outline`/etc: Different styling variations are now contained within the `variant` prop. - -### Component Equivalents - -Not all classes/components from Bootstrap/Reactstrap have a similar name or 1:1 equivalent in MUI. Listed below are some notable changes - -| Bootstrap | MUI | Description | Example Use | Sample | -| ------------------- | ------- | ------------------------------------ | ----------- | :-----------------------------------------------------------------------------------------------------------------------: | -| `Badge`1 | `Badge` | Small corner overlay of base element | Counters | | -| `Badge`2 | `Chip` | Inline colored label/descriptor | Status | | -| `Column`/`Row` | `Grid` | Horizontal and Vertical layout | | - -## Migration Strategy - -### Drop-in Components and the Migration Theme - -To help break up the work needed for migration, we have created a bootstrap migration theme. The migration theme should allow you to slowly start replacing components without disrupting your design until you are ready to upgrade to the new theme. - -The migration theme is accessible by passing `theme='legacyBS'` to the `ThemeProvider` - -> **NOTE** -> Be careful not to deviate from the provided Mui migration styles. Otherwise it may cause issues once you have finished migration and switch to the new Mui theme. - -#### Recommended Early Component Swaps - -- layout (`Box`, `Grid`, `Container`) -- table -- menu -- list (excluding list-group) -- alert -- card - -### Form - -Where you're coming from will determine your strategy for form migration. We have moved away from `formik` (used by `@availity/form`) in favor of `react-hook-form`. We have also provided the base components to utilize with your own logic/libraries. - -See the [Form migration](./form-migration.mdx) docs for more information. - -### Components Without a Drop-in Option - -There are many bootstrap elements and other design guidelines that will not be making it into the new Mui theme. These components we recommend saving for last so the changes will be introduced as you are switching to the new theme. - -#### Required UX changes - -- button - - some props have changed. See the [button README](/docs/components-button-introduction--docs). -- icon - - icon sizing is more logical in MUI, but very different. If using large icons, it may be easier to go straight to v1. -- list-group - - does not exist in Mui. UX to provide new design guidelines for how to change this component. diff --git a/packages/button/src/lib/bs4migration.stories.mdx b/packages/button/src/lib/bs4migration.stories.mdx new file mode 100644 index 000000000..3ce9d01e8 --- /dev/null +++ b/packages/button/src/lib/bs4migration.stories.mdx @@ -0,0 +1,55 @@ +import { Meta, Source } from '@storybook/blocks'; + + + +# Component Migration + +This migration guide is just an overview. For more in depth component information, visit: +- [Availity Usage Guide](https://zeroheight.com/2e36e50c7/p/54f663-button) +- [MUI Documentation](https://mui.com/material-ui/react-button/) + + +## Key Differences (not exhaustive list) + +- Changed + - Per UX, the available colors for a button have changed, notably the removal of success and error colors. +- Removed + - `outline` while mui moves this option into the `variant` prop, per UX this variant has also been removed going forward. +- Other + - UX has updated the guidelines for when to use which color. Refer to zeroheight docs for more information. + +## Code Examples + +`reactstrap`/`availity-react` Example: + + ( + +); +`}/> + +`@availity/element` Example: + + ( + +); +`}/> diff --git a/packages/element/introduction.stories.mdx b/packages/element/introduction.stories.mdx index a3650c41f..063c24792 100644 --- a/packages/element/introduction.stories.mdx +++ b/packages/element/introduction.stories.mdx @@ -4,4 +4,49 @@ import ReadMe from './README.md?raw'; +## What is `@availity/element`? + +The vision behind `@availity/element` is to build a wholistic design system +rather than simply a collection of components. The components are built in +collaboration with the UX team and based on larger patterns. This helps +create a cohesive experience across applications and frees up developers to +focus on rapid innovation. + +## Why MUI? + +The official decision process for where Availity would go after Bootstrap 4 started +in 2020. It was decided early on to not upgrade to Bootstrap 5 and instead leave +Bootstrap behind. When determining where to go next the primary contenders were +Material and TailwindCSS. Material is a set of design guidelines started by Google +with an accompanying React component library. TailwindCSS is a "utility-first +CSS framework", with pre-defined classes similar to Bootstrap but going all in +with utility vs the component styles of Bootstrap. + +We did POCs for both frameworks in 2021/2022, with Material ultimately coming out +on top for a few reasons: + +- MUI integrates with Figma enabling UX to quickly produce designs that + closely match the actual components. +- MUI's components allow for greater flexibility and less abstraction. + This enables developers to focus on business logic and innovation rather + than component limitations. +- MUI handles a lot of baseline accessibility logic for simple components, as + well as complex accessibility patterns, like keyboard interactions for tabs. +- MUI's theming engine makes it easy to implement global and targeted updates to the + look and feel. + +## Current State + +The goals of the current version of `@availity/element` include building a +cohesive design system with an eye on easing the migration process. The +initial release will provide a solid path towards 508 compliance and +baseline component-level telemetry. + +## Future Plans + +- Internationalization (Material already supports this on the component level) +- Consolidation across Availity Platforms in future themes + +## README + {ReadMe}