diff --git a/docs/development-guide/13-coding-standards.md b/docs/development-guide/13-coding-standards.md index 018c9e20953..1d542375d23 100644 --- a/docs/development-guide/13-coding-standards.md +++ b/docs/development-guide/13-coding-standards.md @@ -15,9 +15,28 @@ If you are using VSCode it is highly recommended to use the ESlint extension. Th ## React -- When conditionally rendering JSX, use ternaries instead of `&&`. - - Example: `condition ? : null` instead of `condition && ` - - This is to avoid hard-to-catch bugs ([read more](https://kentcdodds.com/blog/use-ternaries-rather-than-and-and-in-jsx)). +[Several new hooks were introduced with the release of React 18](https://react.dev/blog/2022/03/29/react-v18#new-hooks). + +It should be noted that the `useId()` hook is particularly useful for generating unique IDs for accessibility attributes. For this use case, `useId()` is preferred over hardcoding the ID because components may be rendered more than once on a page, but IDs must be unique. + +As an example from `DisplayLinodes.tsx`, early in the file we invoke the hook: `const displayViewDescriptionId = React.useId()` + +And make use of the unique ID by passing it as the value for a component's `aria-describedby` attribute in the `return` value: + +``` + + + +``` + +Per the [docs](https://react.dev/reference/react/useId#usage), the hook should not be used for generating keys in a list. ## Event Handler Naming Convention diff --git a/packages/manager/.changeset/pr-10261-tech-stories-1709842863706.md b/packages/manager/.changeset/pr-10261-tech-stories-1709842863706.md new file mode 100644 index 00000000000..df5885d23f5 --- /dev/null +++ b/packages/manager/.changeset/pr-10261-tech-stories-1709842863706.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Tech Stories +--- + +Implement new useId() hook in several components ([#10261](https://github.com/linode/manager/pull/10261)) diff --git a/packages/manager/src/components/GroupByTagToggle.tsx b/packages/manager/src/components/GroupByTagToggle.tsx index d298ec4313f..1193bb949ff 100644 --- a/packages/manager/src/components/GroupByTagToggle.tsx +++ b/packages/manager/src/components/GroupByTagToggle.tsx @@ -13,9 +13,11 @@ interface GroupByTagToggleProps { export const GroupByTagToggle = React.memo((props: GroupByTagToggleProps) => { const { isGroupedByTag, isLargeAccount, toggleGroupByTag } = props; + const groupByDescriptionId = React.useId(); + return ( <> -
+
{isGroupedByTag ? 'group by tag is currently enabled' : 'group by tag is currently disabled'} @@ -25,7 +27,7 @@ export const GroupByTagToggle = React.memo((props: GroupByTagToggleProps) => { title={`${isGroupedByTag ? 'Ungroup' : 'Group'} by tag`} > { const { enqueueSnackbar } = useSnackbar(); + const virtModeCaptionId = React.useId(); + const { data: kernels, error: kernelsError, @@ -721,7 +723,7 @@ export const LinodeConfigDialog = (props: Props) => { Virtual Machine @@ -745,7 +747,7 @@ export const LinodeConfigDialog = (props: Props) => { label="Full virtualization" value="fullvirt" /> - + Controls if devices inside your virtual machine are paravirtualized or fully virtualized. Paravirt is what you want, unless you’re doing weird things. diff --git a/packages/manager/src/features/Linodes/LinodesLanding/DisplayGroupedLinodes.tsx b/packages/manager/src/features/Linodes/LinodesLanding/DisplayGroupedLinodes.tsx index 00189df5834..dd14a72f8fd 100644 --- a/packages/manager/src/features/Linodes/LinodesLanding/DisplayGroupedLinodes.tsx +++ b/packages/manager/src/features/Linodes/LinodesLanding/DisplayGroupedLinodes.tsx @@ -71,6 +71,9 @@ export const DisplayGroupedLinodes = (props: CombinedProps) => { ...rest } = props; + const displayViewDescriptionId = React.useId(); + const groupByDescriptionId = React.useId(); + const dataLength = data.length; const orderedGroupedLinodes = compose(sortGroups, groupByTags)(data); @@ -96,12 +99,12 @@ export const DisplayGroupedLinodes = (props: CombinedProps) => { <> -
+
Currently in {linodeViewPreference} view
{ -
+
{linodesAreGrouped ? 'group by tag is currently enabled' : 'group by tag is currently disabled'}
{ ...rest } = props; + const displayViewDescriptionId = React.useId(); + const groupByDescriptionId = React.useId(); + const { infinitePageSize, setInfinitePageSize } = useInfinitePageSize(); const numberOfLinodesWithMaintenance = React.useMemo(() => { return data.reduce((acc, thisLinode) => { @@ -143,13 +146,13 @@ export const DisplayLinodes = React.memo((props: CombinedProps) => {
Currently in {linodeViewPreference} view
{ -
+
{linodesAreGrouped ? 'group by tag is currently enabled' : 'group by tag is currently disabled'}
( toggleLinodeView, } = props; + const displayViewDescriptionId = React.useId(); + const isActive = (label: string) => label.toLowerCase() === orderBy.toLowerCase(); @@ -167,12 +169,12 @@ export const SortableTableHead = ( justifyContent: 'flex-end', }} > -
+
Currently in {linodeViewPreference} view