Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build-tools/utils/pluralize.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const pluralizationMap = {
TableHeaderCell: 'TableHeaderCells',
TableRoot: 'TableRoots',
TableRow: 'TableRows',
TableSortButton: 'TableSortButtons',
Tabs: 'Tabs',
TagEditor: 'TagEditors',
TextContent: 'TextContents',
Expand Down
67 changes: 25 additions & 42 deletions pages/table-root/sorting.page.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useMemo, useState } from 'react';
import React, { useMemo } from 'react';

import Header from '~components/header';
import Icon from '~components/icon';
import SpaceBetween from '~components/space-between';
import TableBody from '~components/table-body';
import TableBodyCell from '~components/table-body-cell';
import TableHead from '~components/table-head';
import TableHeaderCell from '~components/table-header-cell';
import TableRoot from '~components/table-root';
import TableRow from '~components/table-row';
import TableSortButton from '~components/table-sort-button';

import { useAppContext } from '../app/app-context';
import { SimplePage } from '../app/templates';
import { Item, makeItems } from './common';

import styles from './styles.scss';

type SortKey = 'name' | 'type' | 'size' | 'status';
type SortDirection = 'ascending' | 'descending';

const COLUMNS: ReadonlyArray<{ key: SortKey; label: string }> = [
// Status can't be sorted, to show the disabled state.
const COLUMNS: ReadonlyArray<{ key: SortKey; label: string; disabled?: boolean }> = [
{ key: 'name', label: 'Name' },
{ key: 'type', label: 'Type' },
{ key: 'size', label: 'Size' },
{ key: 'status', label: 'Status' },
{ key: 'status', label: 'Status', disabled: true },
];

function compare(key: SortKey, a: Item, b: Item): number {
Expand All @@ -35,23 +34,15 @@ function compare(key: SortKey, a: Item, b: Item): number {
}

export default function TableSortingPage() {
const items = makeItems(12);
const [sortKey, setSortKey] = useState<SortKey>('name');
const [direction, setDirection] = useState<SortDirection>('ascending');
const { urlParams, setUrlParams } = useAppContext<'sortKey' | 'sortDescending'>();
const sortKey = (urlParams.sortKey as SortKey | undefined) ?? 'name';
const descending = !!urlParams.sortDescending;

const items = useMemo(() => makeItems(12), []);
const rows = useMemo(() => {
const sorted = [...items].sort((a, b) => compare(sortKey, a, b));
return direction === 'ascending' ? sorted : sorted.reverse();
}, [items, sortKey, direction]);

const handleSort = (key: SortKey) => {
if (key === sortKey) {
setDirection(prev => (prev === 'ascending' ? 'descending' : 'ascending'));
} else {
setSortKey(key);
setDirection('ascending');
}
};
return descending ? sorted.reverse() : sorted;
}, [items, sortKey, descending]);

return (
<SimplePage title="Table atomics — sorting (auto layout)" screenshotArea={{}}>
Expand All @@ -60,27 +51,19 @@ export default function TableSortingPage() {
<TableRoot ariaLabel="Resources">
<TableHead>
<TableRow>
{COLUMNS.map(({ key, label }) => {
const active = key === sortKey;
return (
<TableHeaderCell key={key} ariaSort={active ? direction : 'none'}>
<button type="button" className={styles['sort-button']} onClick={() => handleSort(key)}>
<span>{label}</span>
<span className={styles['sort-indicator']}>
<Icon
name={
active
? direction === 'ascending'
? 'caret-up-filled'
: 'caret-down-filled'
: 'caret-down'
}
/>
</span>
</button>
</TableHeaderCell>
);
})}
{COLUMNS.map(({ key, label, disabled }) => (
<TableHeaderCell key={key}>
<TableSortButton
sortingState={key !== sortKey ? 'sortable' : descending ? 'descending' : 'ascending'}
disabled={disabled}
onSortingChange={({ detail }) =>
setUrlParams({ sortKey: key, sortDescending: detail.sortingState === 'descending' })
}
>
{label}
</TableSortButton>
</TableHeaderCell>
))}
</TableRow>
</TableHead>
<TableBody>
Expand Down
28 changes: 0 additions & 28 deletions pages/table-root/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,6 @@
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
@use '~design-tokens' as tokens;

// A minimal sort control for the demo: a native button that inherits the header cell's colour and
// typography (so the label stays the column-header colour, not link blue). It fills the cell and
// pushes the caret to the end, so the label stays left-aligned with the column while the sort
// indicator sits at the right.
.sort-button {
display: flex;
align-items: center;
justify-content: space-between;
inline-size: 100%;
gap: tokens.$space-static-xxs;
padding-block: 0;
padding-inline: 0;
border-block: none;
border-inline: none;
background: none;
color: inherit;
font: inherit;
cursor: pointer;
}

// Centres the selection control within a disablePaddings control cell, matching classic Table.
// The Cloudscape checkbox/radio control carries an intrinsic 2px top margin (it aligns the box with
Expand All @@ -36,13 +15,6 @@
padding-block-end: 2px;
}

// Sort affordance at the right of a sortable header (the caret icon).
.sort-indicator {
display: inline-flex;
align-items: center;
gap: tokens.$space-static-xxs;
}

// A fixed-height region that scrolls its table in both directions.
.scroll-container {
block-size: 400px;
Expand Down
168 changes: 168 additions & 0 deletions src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -31085,6 +31085,101 @@ assistive technologies via the selection control in a leading cell.",
}
`;

exports[`Components definition for table-sort-button matches the snapshot: table-sort-button 1`] = `
{
"dashCaseName": "table-sort-button",
"events": [
{
"cancelable": false,
"description": "Called when the user activates the button. The event \`detail\` contains the requested \`sortingState\`:
\`ascending\` for an unsorted or descending column, \`descending\` for an ascending column.",
"detailInlineType": {
"name": "TableSortButtonProps.SortingChangeDetail",
"properties": [
{
"inlineType": {
"name": ""ascending" | "descending"",
"type": "union",
"values": [
"ascending",
"descending",
],
},
"name": "sortingState",
"optional": false,
"type": "string",
},
],
"type": "object",
},
"detailType": "TableSortButtonProps.SortingChangeDetail",
"name": "onSortingChange",
},
],
"functions": [],
"name": "TableSortButton",
"properties": [
{
"description": "Provides an accessible name for the button. Use it when the visible label isn't enough, for example to
include the sort direction for assistive technologies that don't announce \`aria-sort\`.",
"name": "ariaLabel",
"optional": true,
"type": "string",
},
{
"deprecatedTag": "Custom CSS is not supported. For testing and other use cases, use [data attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes).",
"description": "Adds the specified classes to the root element of the component.",
"name": "className",
"optional": true,
"type": "string",
},
{
"description": "Prevents the column from being sorted. When the column is currently sorted, the sort indicator stays
visible in a disabled style.",
"name": "disabled",
"optional": true,
"type": "boolean",
},
{
"deprecatedTag": "The usage of the \`id\` attribute is reserved for internal use cases. For testing and other use cases,
use [data attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes). If you must
use the \`id\` attribute, consider setting it on a parent element instead.",
"description": "Adds the specified ID to the root element of the component.",
"name": "id",
"optional": true,
"type": "string",
},
{
"description": "The column's current sort state:
* \`sortable\` - The column can be sorted but isn't currently.
* \`ascending\` - The column is sorted in ascending order.
* \`descending\` - The column is sorted in descending order.",
"inlineType": {
"name": "TableSortButtonProps.SortingState",
"type": "union",
"values": [
"ascending",
"descending",
"sortable",
],
},
"name": "sortingState",
"optional": true,
"type": "string",
},
],
"regions": [
{
"description": "The column label.",
"displayName": "label",
"isDefault": true,
"name": "children",
},
],
"releaseStatus": "stable",
}
`;

exports[`Components definition for tabs matches the snapshot: tabs 1`] = `
{
"dashCaseName": "tabs",
Expand Down Expand Up @@ -47889,6 +47984,56 @@ Returns the current value of the input.",
"methods": [],
"name": "TableRowWrapper",
},
{
"methods": [
{
"description": "Returns the column label.",
"name": "findLabel",
"parameters": [],
"returnType": {
"isNullable": false,
"name": "ElementWrapper",
"typeArguments": [
{
"name": "HTMLElement",
},
],
},
},
{
"description": "Returns the sort indicator icon, or \`null\` for a disabled column that isn't sorted.",
"name": "findSortingIcon",
"parameters": [],
"returnType": {
"isNullable": true,
"name": "ElementWrapper",
"typeArguments": [
{
"name": "HTMLElement",
},
],
},
},
{
"description": "Returns the current sort state.",
"name": "getSortingState",
"parameters": [],
"returnType": {
"isNullable": false,
"name": ""ascending" | "descending" | "sortable"",
},
},
{
"name": "isDisabled",
"parameters": [],
"returnType": {
"isNullable": false,
"name": "boolean",
},
},
],
"name": "TableSortButtonWrapper",
},
{
"methods": [
{
Expand Down Expand Up @@ -58115,6 +58260,29 @@ This utility does not open the dropdown. To find dropdown items, call \`openDrop
"methods": [],
"name": "TableRowWrapper",
},
{
"methods": [
{
"description": "Returns the column label.",
"name": "findLabel",
"parameters": [],
"returnType": {
"isNullable": false,
"name": "ElementWrapper",
},
},
{
"description": "Returns the sort indicator icon, or \`null\` for a disabled column that isn't sorted.",
"name": "findSortingIcon",
"parameters": [],
"returnType": {
"isNullable": false,
"name": "ElementWrapper",
},
},
],
"name": "TableSortButtonWrapper",
},
{
"methods": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,11 @@ exports[`test-utils selectors 1`] = `
"table-row": [
"awsui_row_3yyds",
],
"table-sort-button": [
"awsui_label_1ssy0",
"awsui_root_1ssy0",
"awsui_sorting-icon_1ssy0",
],
"tabs": [
"awsui_actions-container_14rmt",
"awsui_disabled-reason-tooltip_14rmt",
Expand Down
Loading
Loading