Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(DataTable): add support for actions and different layouts #2953

Merged
merged 15 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from 10 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
5 changes: 5 additions & 0 deletions .changeset/spotty-beers-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': minor
---

Add DataTable, Table to drafts entrypoint
7 changes: 6 additions & 1 deletion generated/components.json
Original file line number Diff line number Diff line change
Expand Up @@ -2451,7 +2451,12 @@
"name": "DataTable",
"status": "draft",
"a11yReviewed": false,
"stories": [],
"stories": [
{
"id": "components-datatable--default",
"code": "() => (\n <Table.Container>\n <Table.Title as=\"h2\" id=\"repositories\">\n Repositories\n </Table.Title>\n <Table.Subtitle as=\"p\" id=\"repositories-subtitle\">\n A subtitle could appear here to give extra context to the data.\n </Table.Subtitle>\n <DataTable\n aria-labelledby=\"repositories\"\n aria-describedby=\"repositories-subtitle\"\n data={data}\n columns={[\n {\n header: 'Repository',\n field: 'name',\n rowHeader: true,\n },\n {\n header: 'Type',\n field: 'type',\n renderCell: (row) => {\n return <Label>{uppercase(row.type)}</Label>\n },\n },\n {\n header: 'Updated',\n field: 'updatedAt',\n renderCell: (row) => {\n return <RelativeTime date={new Date(row.updatedAt)} />\n },\n },\n {\n header: 'Dependabot',\n field: 'securityFeatures.dependabot',\n renderCell: (row) => {\n return row.securityFeatures.dependabot.length > 0 ? (\n <LabelGroup>\n {row.securityFeatures.dependabot.map((feature) => {\n return <Label key={feature}>{uppercase(feature)}</Label>\n })}\n </LabelGroup>\n ) : null\n },\n },\n {\n header: 'Code scanning',\n field: 'securityFeatures.codeScanning',\n renderCell: (row) => {\n return row.securityFeatures.codeScanning.length > 0 ? (\n <LabelGroup>\n {row.securityFeatures.codeScanning.map((feature) => {\n return <Label key={feature}>{uppercase(feature)}</Label>\n })}\n </LabelGroup>\n ) : null\n },\n },\n ]}\n />\n </Table.Container>\n)"
}
],
"props": [
{
"name": "aria-describedby",
Expand Down
310 changes: 246 additions & 64 deletions src/DataTable/DataTable.features.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,16 @@
import {DownloadIcon, PlusIcon} from '@primer/octicons-react'
import {Meta} from '@storybook/react'
import React from 'react'
import {
DataTable,
Table,
TableHead,
TableBody,
TableRow,
TableHeader,
TableCell,
TableContainer,
TableTitle,
TableSubtitle,
} from '../DataTable'
import {Button, IconButton} from '../Button'
import {DataTable, Table} from '../DataTable'
import Heading from '../Heading'
import Label from '../Label'
import LabelGroup from '../LabelGroup'
import RelativeTime from '../RelativeTime'

export default {
title: 'Drafts/Components/DataTable/Features',
component: DataTable,
subcomponents: {
Table,
TableHead,
TableBody,
TableRow,
TableHeader,
TableCell,
TableContainer,
TableTitle,
TableSubtitle,
},
} as Meta<typeof DataTable>

const now = Date.now()
Expand Down Expand Up @@ -138,14 +119,74 @@ function uppercase(input: string): string {
return input[0].toUpperCase() + input.slice(1)
}

export const Default = () => (
<TableContainer>
<TableTitle as="h2" id="repositories">
export const WithTitle = () => (
<Table.Container>
<Table.Title as="h2" id="repositories">
Repositories
</TableTitle>
<TableSubtitle as="p" id="repositories-subtitle">
</Table.Title>
<DataTable
aria-labelledby="repositories"
aria-describedby="repositories-subtitle"
data={data}
columns={[
{
header: 'Repository',
field: 'name',
rowHeader: true,
},
{
header: 'Type',
field: 'type',
renderCell: row => {
return <Label>{uppercase(row.type)}</Label>
},
},
{
header: 'Updated',
field: 'updatedAt',
renderCell: row => {
return <RelativeTime date={new Date(row.updatedAt)} />
},
},
{
header: 'Dependabot',
field: 'securityFeatures.dependabot',
renderCell: row => {
return row.securityFeatures.dependabot.length > 0 ? (
<LabelGroup>
{row.securityFeatures.dependabot.map(feature => {
return <Label key={feature}>{uppercase(feature)}</Label>
})}
</LabelGroup>
) : null
},
},
{
header: 'Code scanning',
field: 'securityFeatures.codeScanning',
renderCell: row => {
return row.securityFeatures.codeScanning.length > 0 ? (
<LabelGroup>
{row.securityFeatures.codeScanning.map(feature => {
return <Label key={feature}>{uppercase(feature)}</Label>
})}
</LabelGroup>
) : null
},
},
]}
/>
</Table.Container>
)

export const WithTitleAndSubtitle = () => (
<Table.Container>
<Table.Title as="h2" id="repositories">
Repositories
</Table.Title>
<Table.Subtitle as="p" id="repositories-subtitle">
A subtitle could appear here to give extra context to the data.
</TableSubtitle>
</Table.Subtitle>
<DataTable
aria-labelledby="repositories"
aria-describedby="repositories-subtitle"
Expand Down Expand Up @@ -198,14 +239,93 @@ export const Default = () => (
},
]}
/>
</TableContainer>
</Table.Container>
)

export const WithTitle = () => (
<TableContainer>
<TableTitle as="h2" id="repositories">
export const WithSorting = () => {
const rows = Array.from(data).sort((a, b) => {
return b.updatedAt - a.updatedAt
})
return (
<Table.Container>
<Table.Title as="h2" id="repositories">
Repositories
</Table.Title>
<Table.Subtitle as="p" id="repositories-subtitle">
A subtitle could appear here to give extra context to the data.
</Table.Subtitle>
<DataTable
aria-labelledby="repositories"
aria-describedby="repositories-subtitle"
data={rows}
columns={[
{
header: 'Repository',
field: 'name',
rowHeader: true,
sortBy: true,
},
{
header: 'Type',
field: 'type',
renderCell: row => {
return <Label>{uppercase(row.type)}</Label>
},
},
{
header: 'Updated',
field: 'updatedAt',
sortBy: true,
renderCell: row => {
return <RelativeTime date={new Date(row.updatedAt)} />
},
},
{
header: 'Dependabot',
field: 'securityFeatures.dependabot',
renderCell: row => {
return row.securityFeatures.dependabot.length > 0 ? (
<LabelGroup>
{row.securityFeatures.dependabot.map(feature => {
return <Label key={feature}>{uppercase(feature)}</Label>
})}
</LabelGroup>
) : null
},
},
{
header: 'Code scanning',
field: 'securityFeatures.codeScanning',
renderCell: row => {
return row.securityFeatures.codeScanning.length > 0 ? (
<LabelGroup>
{row.securityFeatures.codeScanning.map(feature => {
return <Label key={feature}>{uppercase(feature)}</Label>
})}
</LabelGroup>
) : null
},
},
]}
initialSortColumn="updatedAt"
initialSortDirection="DESC"
/>
</Table.Container>
)
}

export const WithAction = () => (
<Table.Container>
<Table.Title as="h2" id="repositories">
Repositories
</TableTitle>
</Table.Title>
<Table.Actions>
<Button>Action</Button>
</Table.Actions>
<Table.Divider />
<Table.Subtitle as="p" id="repositories-subtitle">
A subtitle could appear here to give extra context to the data.
</Table.Subtitle>
<DataTable
aria-labelledby="repositories"
aria-describedby="repositories-subtitle"
Expand Down Expand Up @@ -258,17 +378,86 @@ export const WithTitle = () => (
},
]}
/>
</TableContainer>
</Table.Container>
)

export const WithTitleAndSubtitle = () => (
<TableContainer>
<TableTitle as="h2" id="repositories">
export const WithActionOnly = () => (
<>
<Heading as="h2" id="table-title">
Repositories
</Heading>
<Table.Container>
<Table.Actions>
<Button>Action</Button>
</Table.Actions>
<DataTable
aria-labelledby="table-title"
data={data}
columns={[
{
header: 'Repository',
field: 'name',
rowHeader: true,
},
{
header: 'Type',
field: 'type',
renderCell: row => {
return <Label>{uppercase(row.type)}</Label>
},
},
{
header: 'Updated',
field: 'updatedAt',
renderCell: row => {
return <RelativeTime date={new Date(row.updatedAt)} />
},
},
{
header: 'Dependabot',
field: 'securityFeatures.dependabot',
renderCell: row => {
return row.securityFeatures.dependabot.length > 0 ? (
<LabelGroup>
{row.securityFeatures.dependabot.map(feature => {
return <Label key={feature}>{uppercase(feature)}</Label>
})}
</LabelGroup>
) : null
},
},
{
header: 'Code scanning',
field: 'securityFeatures.codeScanning',
renderCell: row => {
return row.securityFeatures.codeScanning.length > 0 ? (
<LabelGroup>
{row.securityFeatures.codeScanning.map(feature => {
return <Label key={feature}>{uppercase(feature)}</Label>
})}
</LabelGroup>
) : null
},
},
]}
/>
</Table.Container>
</>
)

export const WithActions = () => (
<Table.Container>
<Table.Title as="h2" id="repositories">
Repositories
</TableTitle>
<TableSubtitle as="p" id="repositories-subtitle">
</Table.Title>
<Table.Actions>
<IconButton aria-label="Download" icon={DownloadIcon} variant="invisible" />
<IconButton aria-label="Add row" icon={PlusIcon} variant="invisible" />
</Table.Actions>
<Table.Divider />
<Table.Subtitle as="p" id="repositories-subtitle">
A subtitle could appear here to give extra context to the data.
</TableSubtitle>
</Table.Subtitle>
<DataTable
aria-labelledby="repositories"
aria-describedby="repositories-subtitle"
Expand Down Expand Up @@ -321,31 +510,27 @@ export const WithTitleAndSubtitle = () => (
},
]}
/>
</TableContainer>
</Table.Container>
)

export const WithSorting = () => {
const rows = Array.from(data).sort((a, b) => {
return b.updatedAt - a.updatedAt
})
return (
<TableContainer>
<TableTitle as="h2" id="repositories">
Repositories
</TableTitle>
<TableSubtitle as="p" id="repositories-subtitle">
A subtitle could appear here to give extra context to the data.
</TableSubtitle>
export const WithActionsOnly = () => (
<>
<Heading as="h2" id="table-title">
Repositories
</Heading>
<Table.Container>
<Table.Actions>
<IconButton aria-label="Download" icon={DownloadIcon} variant="invisible" />
<IconButton aria-label="Add row" icon={PlusIcon} variant="invisible" />
</Table.Actions>
<DataTable
aria-labelledby="repositories"
aria-describedby="repositories-subtitle"
data={rows}
aria-labelledby="table-title"
data={data}
columns={[
{
header: 'Repository',
field: 'name',
rowHeader: true,
sortBy: true,
},
{
header: 'Type',
Expand All @@ -357,7 +542,6 @@ export const WithSorting = () => {
{
header: 'Updated',
field: 'updatedAt',
sortBy: true,
renderCell: row => {
return <RelativeTime date={new Date(row.updatedAt)} />
},
Expand Down Expand Up @@ -389,9 +573,7 @@ export const WithSorting = () => {
},
},
]}
initialSortColumn="updatedAt"
initialSortDirection="DESC"
/>
</TableContainer>
)
}
</Table.Container>
</>
)
Loading