Skip to content

Commit

Permalink
enhancement #355 - TableDrawer mobile experience (#357)
Browse files Browse the repository at this point in the history
Closes #355
  • Loading branch information
nancy-dassana authored Jul 1, 2021
1 parent 13b6b37 commit 8326375
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 96 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dassana-io/web-components",
"version": "0.11.6",
"version": "0.11.7",
"publishConfig": {
"registry": "https://npm.pkg.github.com/dassana-io"
},
Expand Down
1 change: 1 addition & 0 deletions src/__snapshots__/storybook.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5097,6 +5097,7 @@ exports[`Storyshots TableDrawer Simple Drawer 1`] = `
>
<div
className="container-0-2-245"
id="table-drawer-wrapper"
>
<div
className="tableContainer-0-2-249"
Expand Down
7 changes: 4 additions & 3 deletions src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const useStyles = createUseStyles({
})

interface ModalProps {
emitter: Emitter
emitter?: Emitter
modalConfig: ModalConfig
unsetModal: () => void
}
Expand Down Expand Up @@ -70,9 +70,10 @@ const Modal: FC<ModalProps> = ({
})

useEffect(() => {
emitter.on(EmitterEventTypes.loggedOut, unsetModal)
emitter && emitter.on(EmitterEventTypes.loggedOut, unsetModal)

return () => emitter.off(EmitterEventTypes.loggedOut, unsetModal)
return () =>
emitter && emitter.off(EmitterEventTypes.loggedOut, unsetModal)
})

return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/Modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React, { FC, ReactNode } from 'react'

export interface Props {
children: ReactNode
emitter: Emitter
emitter?: Emitter
popupContainerSelector?: string
}

Expand Down
106 changes: 106 additions & 0 deletions src/components/TableDrawer/TableDrawer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import cn from 'classnames'
import { createUseStyles } from 'react-jss'
import Drawer from './Drawer'
import isEmpty from 'lodash/isEmpty'
import { TableDrawerProps } from './index'
import { useModal } from 'components/Modal'
import { useWindowSize } from 'components/Table/useWindowSize'
import { DataId, Table } from '../Table'
import React, { useState } from 'react'
import { styleguide, themes, ThemeType } from '../assets/styles'

const { borderRadius, spacing } = styleguide
const { dark, light } = ThemeType

const useStyles = createUseStyles({
container: {
borderRadius,
display: 'flex',
height: '100%',
overflowX: 'auto',
width: '100%'
},
drawer: {
flex: 1,
minWidth: 300,
overflow: 'auto',
wordBreak: 'break-word'
},
drawerOpen: {
borderLeft: `1px solid ${themes[light].border}`
},
table: {
padding: `${spacing.m}px ${spacing.l}px`
},
tableContainer: {
flex: 2.5,
overflow: 'auto',
padding: spacing.m,
position: 'relative'
},
// eslint-disable-next-line sort-keys
'@global': {
[`.${dark}`]: {
'& $drawerOpen': {
borderLeft: `1px solid ${themes[dark].border}`
}
}
}
})

export const TableDrawer = <DataType extends DataId>({
containerId,
drawerContainerClasses = [],
renderDrawerCmp,
tableContainerClasses = [],
...rest
}: TableDrawerProps<DataType>) => {
const [rowData, setRowData] = useState({} as DataType)
const resetRowData = () => setRowData({} as DataType)
const { isMobile } = useWindowSize()
const { setModalConfig } = useModal()

const isRowEmpty = isEmpty(rowData)

const classes = useStyles()
const drawerClasses = cn(
{
[classes.drawer]: true,
[classes.drawerOpen]: !isRowEmpty
},
drawerContainerClasses
)

const onRowClick = (clickedRowData: DataType) => {
isMobile &&
setModalConfig({
content: renderDrawerCmp(rowData.id, clickedRowData)
})

return rowData.id === clickedRowData.id
? resetRowData()
: setRowData(clickedRowData)
}

return (
<div className={classes.container} id={containerId}>
<div
className={cn(
{ [classes.tableContainer]: true },
tableContainerClasses
)}
>
<Table<DataType>
activeRowKey={rowData.id}
onRowClick={onRowClick}
{...rest}
/>
</div>
{!isMobile && !isRowEmpty && (
<Drawer classes={[drawerClasses]} onClose={resetRowData}>
{renderDrawerCmp(rowData.id, rowData)}
</Drawer>
)}
</div>
)
}
102 changes: 11 additions & 91 deletions src/components/TableDrawer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,101 +1,21 @@
import cn from 'classnames'
import { createUseStyles } from 'react-jss'
import Drawer from './Drawer'
import isEmpty from 'lodash/isEmpty'
import { DataId, Table, TableProps } from '../Table'
import React, { Key, ReactNode, useState } from 'react'
import { styleguide, themes, ThemeType } from '../assets/styles'

const { borderRadius, spacing } = styleguide
const { dark, light } = ThemeType

const useStyles = createUseStyles({
container: {
borderRadius,
display: 'flex',
height: '100%',
overflowX: 'auto',
width: '100%'
},
drawer: {
flex: 1,
minWidth: 300,
overflow: 'auto',
wordBreak: 'break-word'
},
drawerOpen: {
borderLeft: `1px solid ${themes[light].border}`
},
table: {
padding: `${spacing.m}px ${spacing.l}px`
},
tableContainer: {
flex: 2.5,
overflow: 'auto',
padding: spacing.m,
position: 'relative'
},
// eslint-disable-next-line sort-keys
'@global': {
[`.${dark}`]: {
'& $drawerOpen': {
borderLeft: `1px solid ${themes[dark].border}`
}
}
}
})
import { ModalProvider } from 'components/Modal'
import { TableDrawer as TableDrawerCmp } from './TableDrawer'
import { DataId, TableProps } from '../Table'
import React, { Key, ReactNode } from 'react'

export interface TableDrawerProps<DataType>
extends Omit<TableProps<DataType>, 'activeRowKey' | 'onRowClick'> {
containerId?: string
drawerContainerClasses?: string[]
renderDrawerCmp: (id: Key, rowData: DataType) => ReactNode
tableContainerClasses?: string[]
}

export const TableDrawer = <DataType extends DataId>({
drawerContainerClasses = [],
renderDrawerCmp,
tableContainerClasses = [],
containerId = 'table-drawer-wrapper',
...rest
}: TableDrawerProps<DataType>) => {
const [rowData, setRowData] = useState({} as DataType)
const resetRowData = () => setRowData({} as DataType)

const isRowEmpty = isEmpty(rowData)

const classes = useStyles()
const drawerClasses = cn(
{
[classes.drawer]: true,
[classes.drawerOpen]: !isRowEmpty
},
drawerContainerClasses
)

const onRowClick = (clickedRowData: DataType) =>
rowData.id === clickedRowData.id
? resetRowData()
: setRowData(clickedRowData)

return (
<div className={classes.container}>
<div
className={cn(
{ [classes.tableContainer]: true },
tableContainerClasses
)}
>
<Table<DataType>
activeRowKey={rowData.id}
onRowClick={onRowClick}
{...rest}
/>
</div>
{!isRowEmpty && (
<Drawer classes={[drawerClasses]} onClose={resetRowData}>
{renderDrawerCmp(rowData.id, rowData)}
</Drawer>
)}
</div>
)
}
}: TableDrawerProps<DataType>) => (
<ModalProvider popupContainerSelector={containerId}>
<TableDrawerCmp containerId={containerId} {...rest} />
</ModalProvider>
)

0 comments on commit 8326375

Please sign in to comment.