Skip to content

Commit

Permalink
docs: improvements in table docs
Browse files Browse the repository at this point in the history
  • Loading branch information
tibuurcio committed Oct 18, 2024
1 parent 044d572 commit f6aba2c
Show file tree
Hide file tree
Showing 12 changed files with 349 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const preview: Preview = {
],
'Candidate Components',
'UX Patterns',
['Table', ['Documentation', 'Filters'], 'Observability', 'Directory'],
['Table', ['Table', 'Filters']],
'Contributing',
['Introduction', 'Commits', 'Testing in the platforms', 'Release Process', 'Maintainers'],
],
Expand Down
3 changes: 0 additions & 3 deletions docs/UX Patterns/Directory.mdx

This file was deleted.

6 changes: 6 additions & 0 deletions docs/UX Patterns/Table/Cell Badge.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
import { Meta, Story } from '@storybook/blocks'

import * as TableStories from './Table.stories'

<Meta of={TableStories} />

# Cell Badge
8 changes: 7 additions & 1 deletion docs/UX Patterns/Table/Cell Link.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
![](../../assets/test.png)
import { Meta, Story } from '@storybook/blocks'

import * as TableStories from './Table.stories'

<Meta of={TableStories} />

# Cell Link
21 changes: 16 additions & 5 deletions docs/UX Patterns/Table/Cell More Actions.mdx
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
### More Actions Menu
import { Meta, Story } from '@storybook/blocks'

#### Overview
The Actions Menu provides a consolidated interface for row-specific operations, such as delete, duplicate, download, and archive, all grouped within a single menu.
import * as TableStories from './Table.stories'

<iframe width="1143" height="8208" src="https://www.figma.com/embed?embed_host=your-site.com&url=https://www.figma.com/design/yCPszaTtkCFxRHaSkkJFR9/Eames-Templates-%5BInternal%5D?node-id=2146-40220" allowfullscreen></iframe>
<Meta of={TableStories} />

# Cell Tag

### More Actions Menu

#### Overview

The Actions Menu provides a consolidated interface for row-specific operations, such as delete, duplicate, download, and archive, all grouped within a single menu.

<iframe
width="1143"
height="8208"
src="https://www.figma.com/embed?embed_host=your-site.com&url=https://www.figma.com/design/yCPszaTtkCFxRHaSkkJFR9/Eames-Templates-%5BInternal%5D?node-id=2146-40220"
allowfullscreen></iframe>

#### Usage Guidelines

- Highlight destructive actions in red to ensure emphasis and user caution.
- Omit icons from menu items to maintain a clean, easy-to-read menu.
- Display the "More Actions" menu even when only one option is available.

Examples:
- Disabled menu item (Coming Soon)

- Disabled menu item (Coming Soon)
6 changes: 6 additions & 0 deletions docs/UX Patterns/Table/Cell Tag.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
import { Meta, Story } from '@storybook/blocks'

import * as TableStories from './Table.stories'

<Meta of={TableStories} />

# Cell Tag
29 changes: 23 additions & 6 deletions docs/UX Patterns/Table/Filters.mdx
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
import { Meta, Story } from '@storybook/blocks'

import * as FiltersStories from './Filters.stories'

<Meta of={FiltersStories} />

# Filters

*Note: This section covers filters specifically for tables. For query-related filters, please refer to the [Analytics Filters - Coming Soon](#coming).*
<br />

_Note: This section covers filters specifically for tables. For query-related filters, please refer to the [Analytics Filters - Coming Soon](#coming)._

#### **Simple Filters**

#### **Simple Filters**
Simple filters are ideal when there are only a few filter options. These are straightforward and quick to use, often appearing as dropdowns above the table. For implementation, refer to the [Select Component](https://mparticle.github.io/aquarium/?path=/docs/components-data-entry-select--documentation).

Examples:
- Coming Soon
- Coming Soon

#### **Filters with Apply Button**
<Story of={FiltersStories.WithBasicFilters} />

#### **Filters with Apply Button**

Complex filters provide more advanced filtering options, allowing users to apply multiple criteria at once. These filters often include dropdowns, checkboxes, and text fields. Complex filters are particularly useful when multiple filters need to be applied simultaneously or when load times might be a concern.

#### **Date Range Filters**
- daterange
- modal: sorting, filters: one of each input type: checkboxes, input, tree select and placeholder for tags

<Story of={FiltersStories.WithComplexFilters} />

#### **Date Range Filters**

Date range filters allow users to specify a range of dates to narrow down the data displayed in the table. Typically, these filters include a start date and an end date, with options for common ranges like “Last 7 days” or “Last 30 days.” User presets are also available for frequently used date ranges.

Examples:

- [Basic Date Picker](https://mparticle.github.io/aquarium/?path=/docs/components-data-entry-date-picker--documentation)
- [Date Range Filter with Presets](https://mparticle.github.io/aquarium/?path=/docs/candidate-components-directory-date-range-filter--documentation)
278 changes: 278 additions & 0 deletions docs/UX Patterns/Table/Filters.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
import type { ReactNode } from 'react'
import { CopyOutlined } from '@ant-design/icons'
import { faker } from '@faker-js/faker'
import type { Meta, StoryObj } from '@storybook/react'
import {
Flex,
Icon,
Input,
Select,
Badge,
type IBadgeProps,
Table,
type TableProps,
Tag,
type ITagProps,
Typography,
Space,
Tooltip,
} from 'src/components'
import { DatePickerWithDisabledYears } from 'src/components/data-entry/DatePicker/DatePicker.stories'
import { SelectWithRangePicker } from 'docs/Candidate Components/Directory/Date Range Filter/SelectWithRangePicker'

interface DataType {
key: string
name: string
id: string
timestamp: number
output: string
environment: Environment
status: Status
mpId: string
}

type Environment = 'unknown' | 'development' | 'production'
type Status = 'draft' | 'error' | 'ready'

const EnvironmentColors: Record<Environment, ITagProps['color']> = {
production: 'blue',
development: 'purple',
unknown: 'default',
}

const EnvironmentNames: Record<Environment, string> = {
production: 'Prod',
development: 'Dev',
unknown: 'Unknown',
}

const getTagColorForEnvironment = (env: Environment): ITagProps['color'] => EnvironmentColors[env]

const getNameForEnvironment = (env: Environment) => EnvironmentNames[env]

const StatusColors: Record<Status, IBadgeProps['color']> = {
draft: 'cyan',
error: 'red',
ready: 'green',
}

const StatusNames: Record<Status, string> = {
draft: 'Draft',
error: 'Error',
ready: 'Ready',
}

const getStatusColor = (status: Status) => StatusColors[status]

const getStatusName = (status: Status) => StatusNames[status]

const columns: TableProps<DataType>['columns'] = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: (name: string) => {
const path = window.location.pathname.split('/')
path.pop()
const route = `${path.join('/')}/${name}`

return <Typography.Link href={route}>{name}</Typography.Link>
},
},
{
title: () => (
<Tooltip
title={
<>
<Typography.Text style={{ color: 'white' }}>Help lorem ipsum. </Typography.Text>
<Typography.Link href="/" style={{ color: 'white', textDecoration: 'underline' }}>
Learn More
</Typography.Link>
</>
}>
<Flex align="center" gap={2}>
<Typography.Text>ID</Typography.Text>
<Icon name="help" size="sm" />
</Flex>
</Tooltip>
),
dataIndex: 'id',
key: 'id',
},
{
title: 'Timestamp (UTC)',
dataIndex: 'timestamp',
key: 'timestamp',
render: (timestampInMicroseconds: number): string => {
return new Date(timestampInMicroseconds / (1000 * 1000)).toLocaleString(undefined, {
month: 'short',
day: '2-digit',
year: 'numeric',
hour: 'numeric',
minute: '2-digit',
second: '2-digit',
timeZone: 'UTC',
hour12: false,
})
},
},
{
title: 'mPID',
dataIndex: 'mpId',
key: 'mpId',
render: (mpId: string): ReactNode => {
return <Typography.Text copyable={{ icon: <CopyOutlined aria-label="Copy mPID" /> }}>{mpId}</Typography.Text>
},
},
{
title: 'Output',
dataIndex: 'output',
key: 'output',
},
{
title: 'Environment',
key: 'environment',
dataIndex: 'environment',
render: (env: Environment): React.ReactNode => {
return <Tag color={getTagColorForEnvironment(env)}>{getNameForEnvironment(env)}</Tag>
},
},
{
title: 'Status',
dataIndex: 'status',
key: 'status',
render: (status: Status): React.ReactNode => <Badge color={getStatusColor(status)} text={getStatusName(status)} />,
},
{
title: 'Actions',
dataIndex: 'actions',
key: 'actions',
render: (): ReactNode => (
<Select
suffixIcon={<Icon name="moreActions" />}
variant="borderless"
dropdownStyle={{ width: '200px' }}
options={[
{ label: 'Option 1', value: 'option1' },
{ label: 'Option 2', value: 'option2' },
]}
/>
),
},
]

function createMockRow(): DataType {
return {
id: `JNBSK-${faker.number.int({ min: 1000, max: 9999 }).toString()}`,
key: faker.string.uuid(),
name: faker.helpers.arrayElement([
'NBCU',
'Remarkable Foods',
'Lulo Bank',
'Shift',
'Marks and Spencer',
"Zaxby's",
]),
timestamp: faker.date.recent().valueOf() * 1000 * 1000,
mpId: faker.number.int({ max: 9_999_999_999 }).toString(),
output: faker.helpers.arrayElement(['Braze', 'mP Analytics', 'Cortex', 'Applytics', 'Google Analytics']),
environment: faker.helpers.arrayElement(['unknown', 'development', 'production']),
status: faker.helpers.arrayElement(['draft', 'error', 'ready']),
}
}

const data: DataType[] = faker.helpers.multiple(createMockRow, {
count: 3,
})

const meta: Meta<typeof Table> = {
title: 'UX Patterns/Table/Filters',
component: Table,

args: {},
}

export default meta

type Story = StoryObj<typeof Table>

export const WithBasicFilters: Story = {
name: 'Basic',
render: () => (
<Space direction="vertical" style={{ width: '100%' }}>
<Space direction="vertical" style={{ width: '100%' }}>
<Flex align={'center'} justify={'space-between'}>
<Flex gap={10}>
<DatePickerWithDisabledYears />
</Flex>
<Input
allowClear
prefix={<Icon size="sm" color="brand" name="search" />}
placeholder="Search"
style={{ width: '240px' }}
/>
</Flex>
</Space>
<Table<DataType> columns={columns} dataSource={data} scroll={{ x: 'max-content' }} />
</Space>
),
}

const TIME_OPTIONS = [
{
value: 'last12hours',
label: 'Last 12 hours',
} as const,
{
value: 'last7days',
label: 'Last 7 days',
} as const,
{
value: 'last14days',
label: 'Last 14 days',
} as const,
]

export const WithComplexFilters: Story = {
name: 'Complex',
render: () => (
<Space direction="vertical" style={{ width: '100%' }}>
<Space direction="vertical" style={{ width: '100%' }}>
<Flex align={'center'} justify={'space-between'}>
<Flex gap={10}>
<SelectWithRangePicker
value={'last14days'}
placeholder={'Choose Time'}
options={TIME_OPTIONS}
formatOptions={{
dateStyle: 'short',
timeStyle: 'short',
hour12: false,
}}
dropdownStyle={{ minWidth: 400 }}
// eslint-disable-next-line @typescript-eslint/no-shadow
// onChange={(time) => onUpdateFilters({ time })}
rangePickerProps={{
showTime: true,
showHour: true,
showMinute: true,
showSecond: false,
disabledDate: antdDayJS => {
const fourteenDaysInMs = 14 * 24 * 60 * 60 * 1000
return antdDayJS.isBefore(new Date(Date.now() - fourteenDaysInMs))
},
}}
/>
</Flex>
<Input
allowClear
prefix={<Icon size="sm" color="brand" name="search" />}
placeholder="Search"
style={{ width: '240px' }}
/>
</Flex>
</Space>
<Table<DataType> columns={columns} dataSource={data} scroll={{ x: 'max-content' }} />
</Space>
),
}
Loading

0 comments on commit f6aba2c

Please sign in to comment.