Skip to content

Commit

Permalink
feat(Table): add Table.ScrolView to support horizontal scroll (#1735)
Browse files Browse the repository at this point in the history
* Update snapshots

* feat(Table): add Table.ScrolView to support horizontal scroll
  • Loading branch information
tujoworker authored Nov 21, 2022
1 parent c2b043d commit 85a4d86
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import React from 'react'
import { css, Global } from '@emotion/react'
import styled from '@emotion/styled'
import ComponentBox from 'dnb-design-system-portal/src/shared/tags/ComponentBox'
import { P, Code } from '@dnb/eufemia/src/elements'
import Table from '@dnb/eufemia/src/components/table/Table'
Expand Down Expand Up @@ -86,32 +87,24 @@ export const TableVariantComplex = () => (
</thead>
<tbody>
<Tr variant="even">
<th className="dnb-table__td" scope="row">
Row 1 header
</th>
<Td>Row 1</Td>
<Td rowSpan={2}>Row 1 that spans</Td>
<Td>Row 1</Td>
<Td>Row 1</Td>
</Tr>
<Tr variant="even">
<th className="dnb-table__td" scope="row">
Row 2 header
</th>
<Td>Row 2</Td>
<Td>Row 2</Td>
<Td>Row 2</Td>
</Tr>
<Tr>
<th className="dnb-table__td" scope="row">
Row 3 header
</th>
<Td>Row 3</Td>
<Td>Row 3</Td>
<Td>Row 3</Td>
<Td>Row 3</Td>
</Tr>
<Tr>
<th className="dnb-table__td" scope="row">
Row 4 header
</th>
<Td>Row 4</Td>
<Td>Row 4</Td>
<Td>Row 4</Td>
<Td>Row 4</Td>
Expand All @@ -126,6 +119,120 @@ export const TableVariantComplex = () => (
</ComponentBox>
)

export const TableVariantFixed = () => (
<ComponentBox hideCode data-visual-test="table-fixed">
{() => {
const FixedTable = styled(Table)`
min-width: 80rem;
thead {
th:nth-of-type(1) {
width: 30%;
}
th:nth-of-type(2) {
width: 20%;
}
th:nth-of-type(3) {
width: 10%;
}
th:nth-of-type(4) {
width: 10%;
}
th:nth-of-type(5) {
width: 5%;
}
th:nth-of-type(6) {
width: 5%;
}
th:nth-of-type(7) {
width: 5%;
}
th:nth-of-type(8) {
width: 5%;
}
}
`
return (
<Table.ScrollView bottom="large">
<FixedTable fixed>
<caption className="dnb-sr-only">A Table Caption</caption>
<thead>
<Tr>
<Th scope="col" noWrap>
Column 1
</Th>
<Th scope="col" noWrap>
Column 2
</Th>
<Th scope="col" noWrap>
Column 3
</Th>
<Th scope="col" noWrap>
Column 4
</Th>
<Th scope="col" noWrap>
Column 5
</Th>
<Th scope="col" noWrap>
Column 6
</Th>
<Th scope="col" noWrap>
Column 7
</Th>
<Th scope="col" noWrap align="right">
Column 8
</Th>
</Tr>
</thead>
<tbody>
<Tr>
<Td>Row 1</Td>
<Td>Row 1</Td>
<Td>Row 1</Td>
<Td>Row 1</Td>
<Td>Row 1</Td>
<Td>Row 1</Td>
<Td>Row 1</Td>
<Td align="right">Row 1</Td>
</Tr>
<Tr>
<Td>Row 2</Td>
<Td>Row 2</Td>
<Td>Row 2</Td>
<Td>Row 2</Td>
<Td>Row 2</Td>
<Td>Row 2</Td>
<Td>Row 2</Td>
<Td align="right">Row 2</Td>
</Tr>
<Tr>
<Td>Row 3</Td>
<Td>Row 3</Td>
<Td>Row 3</Td>
<Td>Row 3</Td>
<Td>Row 3</Td>
<Td>Row 3</Td>
<Td>Row 3</Td>
<Td align="right">Row 3</Td>
</Tr>
<Tr>
<Td>Row 4</Td>
<Td>Row 4</Td>
<Td>Row 4</Td>
<Td>Row 4</Td>
<Td>Row 4</Td>
<Td>Row 4</Td>
<Td>Row 4</Td>
<Td align="right">Row 4</Td>
</Tr>
</tbody>
</FixedTable>
</Table.ScrollView>
)
}}
</ComponentBox>
)

export const TableClassHelpers = () => (
<ComponentBox hideCode data-visual-test="table-classes">
<table className="dnb-table">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ showTabs: true
import {
TableVariantBasic,
TableVariantComplex,
TableVariantFixed,
TableClassHelpers,
TableLongHeader,
TableSticky,
Expand All @@ -22,6 +23,10 @@ You can force a row to overwrite the automated odd/even counting by providing e.

<TableVariantComplex />

### Fixed table with Table.ScrollView

<TableVariantFixed />

### Table with sticky header

**NB:** Keep in mind, you have to avoid using `overflow: hidden;` on any child elements to get `position: sticky;` to work. This is a know issue happening on every modern browser. There are various tricks, including [this deallocation / sync solution](https://uxdesign.cc/position-stuck-96c9f55d9526).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,17 @@ Use e.g. `align="right"` on a `<Th>`, `<Td>` or `<Tr>` to align a table header o
## Fixed layout

You may consider using `table-layout: fixed;`. You can use the modifier property `fixed` for doing so and combine it with CSS e.g. `width: 40%` on spesific table headers.

### Scrollable

Depending on your situation, you may want to wrap your Table within `Table.ScrollView`:

```jsx
import { Table } from '@dnb/eufemia'

render(
<Table.ScrollView>
<Table />
</Table.ScrollView>
)
```
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ showTabs: true

### `<Table>`

| Properties | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sticky` | _(optional)_ use `true` to enable a sticky Table header. Defaults to `false`. |
| `stickyOffset` | _(optional)_ defines the offset (top) in `rem` from where the header should start to stick. You may define your app header height here, if you have a sticky header on your page. Defaults to `0`. |
| ~~`variant`~~ (not implemented yet) | _(coming)_ defines the style variant of the table. Options: `basis` . Defaults to `generic`. |
| ~~`size`~~ (not implemented yet) | _(coming)_ spacing size inside the table header and data. Options: `small` \| `medium` \| `large` \. Defaults to `large`. |
| `fixed` | _(optional)_ if set to `true`, the table will behave with a fixed table layout, using: `table-layout: fixed;`. Defaults to `false`. |
| `skeleton` | _(optional)_ if set to `true`, an overlaying skeleton with animation will be shown. |
| [Space](/uilib/components/space/properties) | _(optional)_ spacing properties like `top` or `bottom` are supported. |
| Properties | Description |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sticky` | _(optional)_ use `true` to enable a sticky Table header. Defaults to `false`. |
| `stickyOffset` | _(optional)_ defines the offset (top) in `rem` from where the header should start to stick. You may define your app header height here, if you have a sticky header on your page. Defaults to `0`. |
| ~~`variant`~~ (not implemented yet) | _(coming)_ defines the style variant of the table. Options: `basis` . Defaults to `generic`. |
| ~~`size`~~ (not implemented yet) | _(coming)_ spacing size inside the table header and data. Options: `small` \| `medium` \| `large` \. Defaults to `large`. |
| `fixed` | _(optional)_ if set to `true`, the table will behave with a fixed table layout, using: `table-layout: fixed;`. Use e.g. CSS `width: 40%` on a table column to define the width. Defaults to `false`. |
| `skeleton` | _(optional)_ if set to `true`, an overlaying skeleton with animation will be shown. |
| [Space](/uilib/components/space/properties) | _(optional)_ spacing properties like `top` or `bottom` are supported. |

### Table Row `<Tr>`

Expand Down
31 changes: 14 additions & 17 deletions packages/dnb-eufemia/src/components/table/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
import React from 'react'
import classnames from 'classnames'

// Shared
import Context from '../../shared/Context'
import Provider from '../../shared/Provider'
import { createSpacingClasses } from '../space/SpacingHelper'
import { createSkeletonClass } from '../skeleton/SkeletonHelper'
import { SkeletonShow } from '../skeleton/Skeleton'
import { SpacingProps } from '../../shared/types'
import {
extendPropsWithContext,
validateDOMAttributes,
} from '../../shared/component-helper'
import ScrollView from './TableScrollView'
import TableContext from './TableContext'
import { useStickyHeader, StickyHelper } from './TableStickyHeader'

// Internal
import {
useStickyHeader,
StickyHelper,
StickyTableHeaderProps,
} from './TableStickyHeader'
import type { StickyTableHeaderProps } from './TableStickyHeader'
import type { SkeletonShow } from '../skeleton/Skeleton'
import type { SpacingProps } from '../../shared/types'

export type TableSizes = 'large' | 'medium'
export type TableVariants = 'generic'

export { StickyHelper }
export { ScrollView }

export interface TableProps extends StickyTableHeaderProps {
export type TableProps = {
/**
* The content of the component.
*/
Expand Down Expand Up @@ -59,18 +55,18 @@ export interface TableProps extends StickyTableHeaderProps {
* Default: null.
*/
fixed?: boolean
}
} & StickyTableHeaderProps

export type TableAllProps = TableProps &
React.TableHTMLAttributes<HTMLTableElement> &
SpacingProps

export const defaultProps = {
size: 'large',
variant: 'generic',
}

const Table = (
componentProps: TableProps &
React.TableHTMLAttributes<HTMLTableElement> &
SpacingProps
) => {
const Table = (componentProps: TableAllProps) => {
const context = React.useContext(Context)

const allProps = extendPropsWithContext(
Expand Down Expand Up @@ -150,3 +146,4 @@ const Table = (
export default Table

Table.StickyHelper = StickyHelper
Table.ScrollView = ScrollView
29 changes: 29 additions & 0 deletions packages/dnb-eufemia/src/components/table/TableScrollView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react'
import classnames from 'classnames'
import ScrollView from '../../fragments/scroll-view/ScrollView'

import type { SpacingProps } from '../../shared/types'

export type TableScrollViewProps = {
/**
* The content of the component.
*/
children: React.ReactElement<HTMLTableElement>
}

export type TableScrollViewAllProps = TableScrollViewProps &
Omit<React.TableHTMLAttributes<HTMLDivElement>, 'children'> &
SpacingProps

export default function TableScrollView(props: TableScrollViewAllProps) {
const { className, children, ...rest } = props

return (
<ScrollView
className={classnames('dnb-table__scroll-view', className)}
{...rest}
>
{children}
</ScrollView>
)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import { warn } from '../../shared/component-helper'

export interface StickyTableHeaderProps {
export type StickyTableHeaderProps = {
/**
* Makes the Table header sticky
* Default: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ describe('Table screenshot', () => {
expect(screenshot).toMatchImageSnapshot()
})

it('have to match a fixed table layout', async () => {
const screenshot = await testPageScreenshot({
selector: '[data-visual-test="table-fixed"]',
})
expect(screenshot).toMatchImageSnapshot()
})

it('have to match a sortable table header on focus', async () => {
const selector =
'[data-visual-test="table-classes"] th.dnb-table--sortable.dnb-table--reversed'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ exports[`Table scss have to match snapshot 1`] = `
/* stylelint-disable */
/* stylelint-enable */ }
.dnb-table--fixed {
table-layout: fixed; }
table-layout: fixed;
width: auto; }
.dnb-table__sticky-helper > td {
display: block;
overflow: hidden;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

&--fixed {
table-layout: fixed;
width: auto;
}

&__sticky-helper > td {
Expand Down

0 comments on commit 85a4d86

Please sign in to comment.