Skip to content

Commit

Permalink
feat: Assign id in a callback
Browse files Browse the repository at this point in the history
  • Loading branch information
Al-Dani committed Aug 1, 2023
1 parent bd5375b commit 6f0a5e8
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 38 deletions.
4 changes: 2 additions & 2 deletions src/__tests__/__snapshots__/documenter.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12478,12 +12478,12 @@ scroll parent scrolls to reveal the first row of the table.",
* \`allItemsSelectionLabel\` ((SelectionState) => string) - Specifies the alternative text for multi-selection column header.
* \`selectionGroupLabel\` (string) - Specifies the alternative text for the whole selection and single-selection column header.
It is prefixed to \`itemSelectionLabel\` and \`allItemsSelectionLabel\` when they are set.
* \`tableLabel\` (string) - Provides an alternative text for the table. If you use a header for this table, you may reuse the string
to provide a caption-like description. For example, tableLabel=Instances will be announced as 'Instances table'.
You can use the first argument of type \`SelectionState\` to access the current selection
state of the component (for example, the \`selectedItems\` list). The \`itemSelectionLabel\` for individual
items also receives the corresponding \`Item\` object. You can use the \`selectionGroupLabel\` to
add a meaningful description to the whole selection.
* \`tableLabel\` (string) - Provides an alternative text for the table. If you use a header for this table, you may reuse the string
to provide a caption-like description. For example, tableLabel=Instances will be announced as 'Instances table'.
* \`activateEditLabel\` (EditableColumnDefinition, Item) => string -
Specifies an alternative text for the edit button in editable cells.
* \`cancelEditLabel\` (EditableColumnDefinition) => string -
Expand Down
10 changes: 2 additions & 8 deletions src/box/internal.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useContext } from 'react';
import React from 'react';
import { getBaseProps } from '../internal/base-component';
import clsx from 'clsx';
import styles from './styles.css.js';
import { BoxProps } from './interfaces';
import { InternalBaseComponentProps } from '../internal/hooks/use-base-component';
import { ScrollbarLabelContext } from '../internal/context/scrollbar-label-context';

type InternalBoxProps = BoxProps & InternalBaseComponentProps;

Expand All @@ -25,12 +24,7 @@ export default function InternalBox({
__internalRootRef = null,
...props
}: InternalBoxProps) {
const wrapperHeadingId = useContext(ScrollbarLabelContext);
const elementId = props.id ?? wrapperHeadingId;
const baseProps = getBaseProps({
...props,
id: elementId,
});
const baseProps = getBaseProps(props);
const marginsClassNamesSuffices = getClassNamesSuffixes(margin);
const paddingsClassNamesSuffices = getClassNamesSuffixes(padding);
// This can be any arbitrary string if passed into tagOverride.
Expand Down
16 changes: 9 additions & 7 deletions src/cards/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import clsx from 'clsx';
import React, { FocusEventHandler, useImperativeHandle, useRef } from 'react';
import React, { FocusEventHandler, useCallback, useImperativeHandle, useRef } from 'react';
import { CardsForwardRefType, CardsProps } from './interfaces';
import styles from './styles.css.js';
import { getCardsPerRow } from './cards-layout-helper';
Expand All @@ -17,15 +17,14 @@ import stickyScrolling from '../table/sticky-scrolling';
import useBaseComponent from '../internal/hooks/use-base-component';
import { useVisualRefresh } from '../internal/hooks/use-visual-mode';
import { useMergeRefs } from '../internal/hooks/use-merge-refs';
import { useUniqueId } from '../internal/hooks/use-unique-id';
import LiveRegion from '../internal/components/live-region';
import useMouseDownTarget from '../internal/hooks/use-mouse-down-target';
import { useMobile } from '../internal/hooks/use-mobile';
import { supportsStickyPosition } from '../internal/utils/dom';
import { useInternalI18n } from '../i18n/context';
import { useContainerQuery } from '@cloudscape-design/component-toolkit';
import { AnalyticsFunnelSubStep } from '../internal/analytics/components/analytics-funnel';
import { ScrollbarLabelContext } from '../internal/context/scrollbar-label-context';
import { CollectionLabelContext } from '../internal/context/collection-label-context';

export { CardsProps };

Expand Down Expand Up @@ -65,7 +64,10 @@ const Cards = React.forwardRef(function <T = any>(

const computedVariant = isRefresh ? variant : 'container';

const headingId = useUniqueId('cards-heading');
const headerIdRef = useRef<string | undefined>(undefined);
const setHeaderRef = useCallback((id: string) => {
headerIdRef.current = id;
}, []);
const isLabelledByHeader = !ariaLabels?.cardsLabel && !!header;

const [columns, measureRef] = useContainerQuery<number>(
Expand Down Expand Up @@ -140,9 +142,9 @@ const Cards = React.forwardRef(function <T = any>(
styles[`header-variant-${computedVariant}`]
)}
>
<ScrollbarLabelContext.Provider value={headingId}>
<CollectionLabelContext.Provider value={{ assignId: setHeaderRef }}>
<ToolsHeader header={header} filter={filter} pagination={pagination} preferences={preferences} />
</ScrollbarLabelContext.Provider>
</CollectionLabelContext.Provider>
</div>
)
}
Expand Down Expand Up @@ -175,7 +177,7 @@ const Cards = React.forwardRef(function <T = any>(
updateShiftToggle={updateShiftToggle}
onFocus={onCardFocus}
ariaLabel={ariaLabels?.cardsLabel}
ariaLabelledby={isLabelledByHeader ? headingId : undefined}
ariaLabelledby={isLabelledByHeader && headerIdRef.current ? headerIdRef.current : undefined}
/>
)}
</div>
Expand Down
10 changes: 6 additions & 4 deletions src/header/internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import styles from './styles.css.js';
import { SomeRequired } from '../internal/types';
import { useMobile } from '../internal/hooks/use-mobile';
import { InfoLinkLabelContext } from '../internal/context/info-link-label-context';
import { ScrollbarLabelContext } from '../internal/context/scrollbar-label-context';
import { CollectionLabelContext } from '../internal/context/collection-label-context';
import { useUniqueId } from '../internal/hooks/use-unique-id';
import { DATA_ATTR_FUNNEL_KEY, FUNNEL_KEY_SUBSTEP_NAME } from '../internal/analytics/selectors';

Expand All @@ -36,9 +36,11 @@ export default function InternalHeader({
const { isStuck } = useContext(StickyHeaderContext);
const baseProps = getBaseProps(restProps);
const isRefresh = useVisualRefresh();
const wrapperHeadingId = useContext(ScrollbarLabelContext);
const uniqueHeadingId = useUniqueId('heading');
const headingId = wrapperHeadingId ? wrapperHeadingId : uniqueHeadingId;
const assignHeaderId = useContext(CollectionLabelContext).assignId;
const headingId = useUniqueId('heading');
if (assignHeaderId !== undefined) {
assignHeaderId(headingId);
}
// If is mobile there is no need to have the dynamic variant because it's scrolled out of view
const dynamicVariant = !isMobile && isStuck ? 'h2' : 'h1';
const variantOverride = variant === 'awsui-h1-sticky' ? (isRefresh ? dynamicVariant : 'h2') : variant;
Expand Down
9 changes: 9 additions & 0 deletions src/internal/context/collection-label-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { createContext } from 'react';

interface CollectionLabellingInterface {
assignId?: (id: string) => void;
}

export const CollectionLabelContext = createContext<CollectionLabellingInterface>({});
5 changes: 0 additions & 5 deletions src/internal/context/scrollbar-label-context.ts

This file was deleted.

5 changes: 2 additions & 3 deletions src/table/interfaces.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,12 @@ export interface TableProps<T = any> extends BaseComponentProps {
* * `allItemsSelectionLabel` ((SelectionState) => string) - Specifies the alternative text for multi-selection column header.
* * `selectionGroupLabel` (string) - Specifies the alternative text for the whole selection and single-selection column header.
* It is prefixed to `itemSelectionLabel` and `allItemsSelectionLabel` when they are set.
* * `tableLabel` (string) - Provides an alternative text for the table. If you use a header for this table, you may reuse the string
* to provide a caption-like description. For example, tableLabel=Instances will be announced as 'Instances table'.
* You can use the first argument of type `SelectionState` to access the current selection
* state of the component (for example, the `selectedItems` list). The `itemSelectionLabel` for individual
* items also receives the corresponding `Item` object. You can use the `selectionGroupLabel` to
* add a meaningful description to the whole selection.
*
* * `tableLabel` (string) - Provides an alternative text for the table. If you use a header for this table, you may reuse the string
* to provide a caption-like description. For example, tableLabel=Instances will be announced as 'Instances table'.
* * `activateEditLabel` (EditableColumnDefinition, Item) => string -
* Specifies an alternative text for the edit button in editable cells.
* * `cancelEditLabel` (EditableColumnDefinition) => string -
Expand Down
14 changes: 8 additions & 6 deletions src/table/internal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import clsx from 'clsx';
import React, { useImperativeHandle, useRef, useState } from 'react';
import React, { useCallback, useImperativeHandle, useRef, useState } from 'react';
import { TableForwardRefType, TableProps } from './interfaces';
import { getVisualContextClassname } from '../internal/components/visual-context';
import InternalContainer from '../container/internal';
Expand Down Expand Up @@ -37,8 +37,7 @@ import { checkColumnWidths } from './column-widths-utils';
import { useMobile } from '../internal/hooks/use-mobile';
import { useContainerQuery } from '@cloudscape-design/component-toolkit';
import { getTableRoleProps, getTableRowRoleProps } from './table-role';
import { ScrollbarLabelContext } from '../internal/context/scrollbar-label-context';
import { useUniqueId } from '../internal/hooks/use-unique-id';
import { CollectionLabelContext } from '../internal/context/collection-label-context';

const SELECTION_COLUMN_WIDTH = 54;
const selectionColumnId = Symbol('selection-column-id');
Expand Down Expand Up @@ -161,8 +160,11 @@ const InternalTable = React.forwardRef(
const hasFooterPagination = isMobile && variant === 'full-page' && !!pagination;
const hasFooter = !!footer || hasFooterPagination;

const headingId = useUniqueId('table-heading');
const headerIdRef = useRef<string | undefined>(undefined);
const isLabelledByHeader = !ariaLabels?.tableLabel && !!header;
const setHeaderRef = useCallback((id: string) => {
headerIdRef.current = id;
}, []);

const visibleColumnWidthsWithSelection: ColumnWidthDefinition[] = [];
const visibleColumnIdsWithSelection: PropertyKey[] = [];
Expand Down Expand Up @@ -263,9 +265,9 @@ const InternalTable = React.forwardRef(
ref={toolsHeaderWrapper}
className={clsx(styles['header-controls'], styles[`variant-${computedVariant}`])}
>
<ScrollbarLabelContext.Provider value={headingId}>
<CollectionLabelContext.Provider value={{ assignId: setHeaderRef }}>
<ToolsHeader header={header} filter={filter} pagination={pagination} preferences={preferences} />
</ScrollbarLabelContext.Provider>
</CollectionLabelContext.Provider>
</div>
</div>
)}
Expand Down
11 changes: 8 additions & 3 deletions src/table/tools-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import clsx from 'clsx';
import React, { useContext } from 'react';
import { useContainerBreakpoints } from '../internal/hooks/container-queries';
import styles from './styles.css.js';
import { ScrollbarLabelContext } from '../internal/context/scrollbar-label-context';
import { CollectionLabelContext } from '../internal/context/collection-label-context';
import { useUniqueId } from '../internal/hooks/use-unique-id';

interface ToolsHeaderProps {
header: React.ReactNode;
Expand All @@ -15,13 +16,17 @@ interface ToolsHeaderProps {

export default function ToolsHeader({ header, filter, pagination, preferences }: ToolsHeaderProps) {
const [breakpoint, ref] = useContainerBreakpoints(['xs']);
const headerId = useContext(ScrollbarLabelContext);
const isHeaderString = typeof header === 'string';
const assignHeaderId = useContext(CollectionLabelContext).assignId;
const headingId = useUniqueId('heading');
if (assignHeaderId !== undefined && isHeaderString) {
assignHeaderId(headingId);
}
const isSmall = breakpoint === 'default';
const hasTools = filter || pagination || preferences;
return (
<>
{isHeaderString ? <span id={headerId}>{header}</span> : header}
{isHeaderString ? <span id={headingId}>{header}</span> : header}
{hasTools && (
<div ref={ref} className={clsx(styles.tools, isSmall && styles['tools-small'])}>
{filter && <div className={styles['tools-filtering']}>{filter}</div>}
Expand Down

0 comments on commit 6f0a5e8

Please sign in to comment.