Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
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
49 changes: 47 additions & 2 deletions build-tools/tasks/docs.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,65 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
const fs = require('fs');
const path = require('path');
const { writeComponentsDocumentation, writeTestUtilsDocumentation } = require('@cloudscape-design/documenter');
const workspace = require('../utils/workspace');

// Dash-case names of the versioned beta components — the dirs matching the beta documenter glob
// (src/beta/<name>-<major.minor>/<component>/index.tsx). Used to flag their generated definitions.
function getBetaComponentNames(srcDir = 'src') {
const betaRoot = path.join(srcDir, 'beta');
if (!fs.existsSync(betaRoot)) {
return [];
}
const names = [];
for (const versionDir of fs.readdirSync(betaRoot)) {
const versionPath = path.join(betaRoot, versionDir);
if (!fs.statSync(versionPath).isDirectory()) {
continue;
}
for (const component of fs.readdirSync(versionPath)) {
if (fs.existsSync(path.join(versionPath, component, 'index.tsx'))) {
names.push(component);
}
}
}
return names;
}

module.exports = function docs() {
const componentsOutDir = path.join(workspace.apiDocsPath, 'components');

// Document the stable components AND the versioned beta components into the SINGLE `components`
// output (one combined glob → one index barrel; the documenter rewrites the index from its glob,
// so a second same-outDir pass would clobber it). Beta components are NOT shipped as a separate
// barrel; they live in `components` and are distinguished by the `releaseStatus: 'beta'` flag
// stamped below.
writeComponentsDocumentation({
outDir: path.join(workspace.apiDocsPath, 'components'),
outDir: componentsOutDir,
tsconfigPath: require.resolve('../../tsconfig.json'),
publicFilesGlob: 'src/*/index.tsx',
publicFilesGlob: 'src/{*/index.tsx,beta/*/*/index.tsx}',
extraExports: {
FileDropzone: ['useFilesDragging'],
IconProvider: ['defineIcons', 'IconRegistry', 'IconMap'],
TagEditor: ['getTagsDiff'],
},
});

// The documenter hard-codes `releaseStatus: 'stable'` with no tag override, so stamp the beta
// components' generated definitions as `beta`. The website derives `isBeta` from this (beta page
// header alert + nav badge), keeping the single components barrel with per-component flagging.
for (const name of getBetaComponentNames('src')) {
const definitionFile = path.join(componentsOutDir, `${name}.js`);
if (!fs.existsSync(definitionFile)) {
continue;
}

const definition = require(path.resolve(definitionFile));
definition.releaseStatus = 'beta';
fs.writeFileSync(definitionFile, `module.exports = ${JSON.stringify(definition, null, 2)};`);
}

writeTestUtilsDocumentation({
outDir: path.join(workspace.apiDocsPath, 'test-utils-doc'),
tsconfigPath: require.resolve('../../src/test-utils/tsconfig.json'),
Expand Down
9 changes: 8 additions & 1 deletion build-tools/tasks/package-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const { parallel } = require('gulp');
const path = require('path');
const fs = require('fs');
const { writeFile, listPublicItems } = require('../utils/files');
const { writeFile, listPublicItems, listBetaItems } = require('../utils/files');
const themes = require('../utils/themes');
const { task, copyTask } = require('../utils/gulp-utils');
const workspace = require('../utils/workspace');
Expand Down Expand Up @@ -51,6 +51,13 @@ function getComponentsExports() {
result[`./${component}`] = `./${component}/index.js`;
}

// Versioned beta components, published only at their explicit subpath (e.g.
// `@cloudscape-design/components/beta/basic-table-0.1`) — the versioning escape-hatch. Not added
// to the top-level barrel.
for (const betaItem of listBetaItems('src')) {
result[`./${betaItem}`] = `./${betaItem}/index.js`;
}

// Per-component test-utils wrappers, both DOM and selectors
// (e.g. `.../test-utils/dom/button` and `.../test-utils/selectors/button`).
for (const component of listPublicItems('src/test-utils/dom')) {
Expand Down
21 changes: 19 additions & 2 deletions build-tools/utils/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,25 @@ function listPublicItems(baseDir) {
elem !== 'i18n' &&
elem !== 'theming' &&
elem !== 'plugins' &&
elem !== 'contexts'
elem !== 'contexts' &&
// `beta` is not a component: it is a container for versioned, opt-in beta components
// (e.g. `beta/basic-table-0.1`) enumerated separately via `listBetaItems`.
elem !== 'beta'
);
}

module.exports = { writeFile, listPublicItems };
// Lists the versioned beta components as `beta/<name>` (e.g. `beta/basic-table-0.1`). Beta components
// are opt-in and published only at their versioned export subpath — they are intentionally excluded
// from the top-level barrel and treated as their own kind of public item elsewhere in the build.
function listBetaItems(srcDir = 'src') {
const betaDir = path.join(srcDir, 'beta');
if (!fs.existsSync(betaDir)) {
return [];
}
return fs
.readdirSync(betaDir)
.filter(elem => !elem.startsWith('__') && !elem.startsWith('.') && fs.statSync(path.join(betaDir, elem)).isDirectory())
.map(elem => `beta/${elem}`);
}

module.exports = { writeFile, listPublicItems, listBetaItems };
1 change: 1 addition & 0 deletions build-tools/utils/pluralize.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const pluralizationMap = {
Autosuggest: 'Autosuggests',
Badge: 'Badges',
BarChart: 'BarCharts',
BasicTable: 'BasicTables',
Box: 'Boxes',
BreadcrumbGroup: 'BreadcrumbGroups',
Button: 'Buttons',
Expand Down
68 changes: 68 additions & 0 deletions pages/basic-table/cell-permutations.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React from 'react';

import BasicTable, {
BasicTableBody,
BasicTableCell,
BasicTableHeader,
BasicTableHeaderCell,
BasicTableRow,
} from '~components/beta/basic-table-0.1';
import Box from '~components/box';
import SpaceBetween from '~components/space-between';

// Cell content permutations. `wrapText` is a CELL-scoped prop (per cell / per header cell), so wrap
// vs. truncate is chosen where the long content lives — not a table-global `wrapLines`. The
// `verticalAlign` axis from Table's cell-permutations is NOT built in BasicTable (Bucket A), so it
// is omitted here.
const LONG =
'A deliberately long cell value that exceeds the column width so truncation vs wrapping is visible';

const columns = [{ width: 160 }, { width: 200 }];

export default function BasicTableCellPermutationsPage() {
return (
<Box padding="l">
<SpaceBetween size="l">
<Box variant="h1">BasicTable — cell permutations (wrapText)</Box>

<SpaceBetween size="s">
<Box variant="h2">Default (truncate)</Box>
<BasicTable columns={columns} totalRowCount={2} i18nStrings={{ tableLabel: 'Truncate' }}>
<BasicTableHeader>
<BasicTableHeaderCell>Name</BasicTableHeaderCell>
<BasicTableHeaderCell>Description</BasicTableHeaderCell>
</BasicTableHeader>
<BasicTableBody>
{[0, 1].map(index => (
<BasicTableRow key={index} index={index} id={`t-${index}`}>
<BasicTableCell>Resource {index}</BasicTableCell>
<BasicTableCell>{LONG}</BasicTableCell>
</BasicTableRow>
))}
</BasicTableBody>
</BasicTable>
</SpaceBetween>

<SpaceBetween size="s">
<Box variant="h2">wrapText on the description cells + header</Box>
<BasicTable columns={columns} totalRowCount={2} i18nStrings={{ tableLabel: 'Wrap' }}>
<BasicTableHeader>
<BasicTableHeaderCell>Name</BasicTableHeaderCell>
<BasicTableHeaderCell wrapText={true}>Description that itself wraps onto lines</BasicTableHeaderCell>
</BasicTableHeader>
<BasicTableBody>
{[0, 1].map(index => (
<BasicTableRow key={index} index={index} id={`w-${index}`}>
<BasicTableCell>Resource {index}</BasicTableCell>
<BasicTableCell wrapText={true}>{LONG}</BasicTableCell>
</BasicTableRow>
))}
</BasicTableBody>
</BasicTable>
</SpaceBetween>
</SpaceBetween>
</Box>
);
}
58 changes: 58 additions & 0 deletions pages/basic-table/common.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React from 'react';

import {
BasicTableBody,
BasicTableCell,
BasicTableHeader,
BasicTableHeaderCell,
BasicTableRow,
} from '~components/beta/basic-table-0.1';

export interface Item {
id: string;
name: string;
type: string;
size: string;
status: string;
}

export const makeItems = (n: number): Item[] =>
Array.from({ length: n }, (_, index) => ({
id: `resource-${index}`,
name: `Resource ${index}`,
type: index % 3 === 0 ? 'Compute' : index % 3 === 1 ? 'Storage' : 'Network',
size: `${(index % 8) + 1} GiB`,
status: index % 2 === 0 ? 'Available' : 'Pending',
}));

// A 4-column data layout (no control column): Name fixed, Type/Size flexible-with-min, Status flexible.
export const DATA_COLUMNS = [{ width: 220 }, { minWidth: 140 }, { minWidth: 120 }, {}];

// Renders the standard header row + body for the shared 4-column item shape.
export function DataHeader() {
return (
<BasicTableHeader>
<BasicTableHeaderCell>Name</BasicTableHeaderCell>
<BasicTableHeaderCell>Type</BasicTableHeaderCell>
<BasicTableHeaderCell>Size</BasicTableHeaderCell>
<BasicTableHeaderCell>Status</BasicTableHeaderCell>
</BasicTableHeader>
);
}

export function DataBody({ items }: { items: Item[] }) {
return (
<BasicTableBody>
{items.map((item, index) => (
<BasicTableRow key={item.id} index={index} id={item.id}>
<BasicTableCell>{item.name}</BasicTableCell>
<BasicTableCell>{item.type}</BasicTableCell>
<BasicTableCell>{item.size}</BasicTableCell>
<BasicTableCell>{item.status}</BasicTableCell>
</BasicTableRow>
))}
</BasicTableBody>
);
}
45 changes: 45 additions & 0 deletions pages/basic-table/compact-mode.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React from 'react';

import BasicTable from '~components/beta/basic-table-0.1';
import Box from '~components/box';
import Header from '~components/header';
import SpaceBetween from '~components/space-between';

import { DataBody, DataHeader, DATA_COLUMNS, makeItems } from './common';

// Compact density is a table-global visual concern (shared Cloudscape compact-table context), so it
// is the root `contentDensity` prop — not composable per row. Rendered alongside a comfortable table
// so the reduced cell padding / row height is directly comparable.
export default function BasicTableCompactModePage() {
const items = makeItems(6);
return (
<Box padding="l">
<SpaceBetween size="l">
<Box variant="h1">BasicTable — content density</Box>

<SpaceBetween size="s">
<Header counter={`(${items.length})`}>Comfortable (default)</Header>
<BasicTable columns={DATA_COLUMNS} totalRowCount={items.length} i18nStrings={{ tableLabel: 'Comfortable' }}>
<DataHeader />
<DataBody items={items} />
</BasicTable>
</SpaceBetween>

<SpaceBetween size="s">
<Header counter={`(${items.length})`}>Compact</Header>
<BasicTable
columns={DATA_COLUMNS}
totalRowCount={items.length}
contentDensity="compact"
i18nStrings={{ tableLabel: 'Compact' }}
>
<DataHeader />
<DataBody items={items} />
</BasicTable>
</SpaceBetween>
</SpaceBetween>
</Box>
);
}
Loading
Loading