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

refa: separate table cell and table checkbox cell #2042

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
58 changes: 38 additions & 20 deletions packages/components/src/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ import { TableColumnHeader } from './TableColumnHeader';
import { TableHeaderRow } from './TableHeaderRow';
import { TableRow } from './TableRow';
import { TableRowGroup } from './TableRowGroup';
import { TableCheckboxCell } from './TableCheckboxCell';
import { TableSelectAllCell } from './TableSelectAllCell';

// Theme Extension
// ---------------
export interface TableThemeExtension
extends ThemeExtensionsWithParts<
'Table',
['table', 'header', 'row', 'cell']
['table', 'header', 'row', 'cell', 'checkboxCell']
> {}

// Props
Expand Down Expand Up @@ -54,38 +56,54 @@ export const Table: Table = ({ variant, size, ...props }: TableProps) => {
const styles = useComponentStyles(
'Table',
{ variant, size },
{ parts: ['table', 'header', 'row', 'cell'] }
{ parts: ['table', 'header', 'row', 'cell', 'checkboxCell'] }
);

return (
<Box as="table" ref={ref} __baseCSS={styles.table} {...gridProps}>
<TableRowGroup as="thead">
{state.collection.headerRows.map(headerRow => (
<TableHeaderRow key={headerRow.key} item={headerRow} state={state}>
{[...headerRow.childNodes].map(column => (
<TableColumnHeader
key={column.key}
item={column}
state={state}
isSelectionColumn={column.props.isSelectionCell}
css={styles.header}
/>
))}
{[...headerRow.childNodes].map(column =>
column.props.isSelectionCell ? (
<TableSelectAllCell
key={column.key}
item={column}
state={state}
css={styles.header}
/>
) : (
<TableColumnHeader
key={column.key}
item={column}
state={state}
css={styles.header}
/>
)
)}
</TableHeaderRow>
))}
</TableRowGroup>
<TableRowGroup as="tbody">
{[...state.collection.body.childNodes].map(row => (
<TableRow css={styles.row} key={row.key} item={row} state={state}>
{[...row.childNodes].map(cell => (
<TableCell
key={cell.key}
item={cell}
state={state}
isSelectionCell={cell.props.isSelectionCell}
css={styles.cell}
/>
))}
{[...row.childNodes].map(cell =>
cell.props.isSelectionCell ? (
<TableCheckboxCell
key={cell.key}
item={cell}
state={state}
css={styles.checkboxCell}
/>
) : (
<TableCell
key={cell.key}
item={cell}
state={state}
css={styles.cell}
/>
)
)}
</TableRow>
))}
</TableRowGroup>
Expand Down
32 changes: 3 additions & 29 deletions packages/components/src/Table/TableCell.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import React, { useRef } from 'react';
import { useCheckbox } from '@react-aria/checkbox';
import { useFocusRing } from '@react-aria/focus';
import { useTableCell, useTableSelectionCheckbox } from '@react-aria/table';
import { useTableCell } from '@react-aria/table';
import { mergeProps } from '@react-aria/utils';
import { TableState } from '@react-stately/table';
import { useToggleState } from '@react-stately/toggle';
import { Node } from '@react-types/shared';

import { CSSObject, useStateProps } from '@marigold/system';
Expand All @@ -16,50 +14,26 @@ import { Box } from '../Box';
export interface TableCellProps {
item: Node<object>;
state: TableState<object>;
/**
* Wheter it is a cell with a checkbox or a regular data cell
*/
isSelectionCell?: boolean;
css?: CSSObject;
}

// TableCell Component
// ----------------------------
export const TableCell = ({
item: cell,
state,
isSelectionCell,
css,
}: TableCellProps) => {
export const TableCell = ({ item: cell, state, css }: TableCellProps) => {
const cellRef = useRef(null);
const { gridCellProps } = useTableCell({ node: cell }, state, cellRef);

const { checkboxProps } = useTableSelectionCheckbox(
{ key: cell.parentKey! },
state
);
const inputRef = useRef(null);
const { inputProps } = useCheckbox(
checkboxProps,
useToggleState(checkboxProps),
inputRef
);

const { focusProps, isFocusVisible } = useFocusRing();
const stateProps = useStateProps({ focus: isFocusVisible });

return (
<Box
as="td"
ref={cellRef}
__baseCSS={{
textAlign: isSelectionCell ? 'center' : 'left',
}}
css={css}
{...mergeProps(gridCellProps, focusProps)}
{...stateProps}
>
{isSelectionCell ? <input {...inputProps} /> : <>{cell.rendered}</>}
{cell.rendered}
</Box>
);
};
46 changes: 46 additions & 0 deletions packages/components/src/Table/TableCheckboxCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { useRef } from 'react';
import { useCheckbox } from '@react-aria/checkbox';
import { useTableCell, useTableSelectionCheckbox } from '@react-aria/table';
import { TableState } from '@react-stately/table';
import { useToggleState } from '@react-stately/toggle';
import { Node } from '@react-types/shared';

import { CSSObject } from '@marigold/system';

import { Box } from '../Box';

// Props
// ----------------------------
export interface TableCheckboxCellProps {
item: Node<object>;
state: TableState<object>;
css?: CSSObject;
}

// TableCheckboxCell Component
// ----------------------------
export const TableCheckboxCell = ({
item: cell,
state,
css,
}: TableCheckboxCellProps) => {
const cellRef = useRef(null);
const { gridCellProps } = useTableCell({ node: cell }, state, cellRef);

const { checkboxProps } = useTableSelectionCheckbox(
{ key: cell.parentKey! },
state
);
const inputRef = useRef(null);
const { inputProps } = useCheckbox(
checkboxProps,
useToggleState(checkboxProps),
inputRef
);

return (
<Box as="td" ref={cellRef} css={css} {...gridCellProps}>
<input {...inputProps} />
</Box>
);
};
25 changes: 2 additions & 23 deletions packages/components/src/Table/TableColumnHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import React, { ReactNode, useRef } from 'react';
import { useCheckbox } from '@react-aria/checkbox';
import { useFocusRing } from '@react-aria/focus';
import {
useTableSelectAllCheckbox,
useTableColumnHeader,
} from '@react-aria/table';
import { useTableColumnHeader } from '@react-aria/table';
import { mergeProps } from '@react-aria/utils';
import { TableState } from '@react-stately/table';
import { useToggleState } from '@react-stately/toggle';
import { Node } from '@react-types/shared';

import { CSSObject, useStateProps } from '@marigold/system';
Expand All @@ -21,7 +16,6 @@ export interface TableColumnHeaderProps {
chilren?: ReactNode;
item: Node<object>;
state: TableState<object>;
isSelectionColumn?: boolean;
css?: CSSObject;
}

Expand All @@ -30,7 +24,6 @@ export interface TableColumnHeaderProps {
export const TableColumnHeader = ({
item: column,
state,
isSelectionColumn,
css,
}: TableColumnHeaderProps) => {
const ref = useRef(null);
Expand All @@ -39,32 +32,18 @@ export const TableColumnHeader = ({
state,
ref
);

const { checkboxProps } = useTableSelectAllCheckbox(state);
const inputRef = useRef(null);
const { inputProps } = useCheckbox(
checkboxProps,
useToggleState(checkboxProps),
inputRef
);

const { focusProps, isFocusVisible } = useFocusRing();
const stateProps = useStateProps({ focus: isFocusVisible });

return (
<Box
as="th"
ref={ref}
__baseCSS={{ textAlign: isSelectionColumn ? 'center' : 'left' }}
css={css}
{...mergeProps(columnHeaderProps, focusProps)}
{...stateProps}
>
{isSelectionColumn ? (
<input {...inputProps} ref={inputRef} />
) : (
<Text size="xxsmall">{column.rendered}</Text>
)}
<Text size="xxsmall">{column.rendered}</Text>
</Box>
);
};
57 changes: 57 additions & 0 deletions packages/components/src/Table/TableSelectAllCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { ReactNode, useRef } from 'react';
import { useCheckbox } from '@react-aria/checkbox';
import {
useTableSelectAllCheckbox,
useTableColumnHeader,
} from '@react-aria/table';
import { TableState } from '@react-stately/table';
import { useToggleState } from '@react-stately/toggle';
import { Node } from '@react-types/shared';

import { CSSObject } from '@marigold/system';

import { Box } from '../Box';

// Props
// ----------------------------
export interface TableSelectAllCellProps {
chilren?: ReactNode;
item: Node<object>;
state: TableState<object>;
css?: CSSObject;
}

// TableSelectAllCell Component
// ----------------------------
export const TableSelectAllCell = ({
item: column,
state,
css,
}: TableSelectAllCellProps) => {
const ref = useRef(null);
const { columnHeaderProps } = useTableColumnHeader(
{ node: column },
state,
ref
);

const { checkboxProps } = useTableSelectAllCheckbox(state);
const inputRef = useRef(null);
const { inputProps } = useCheckbox(
checkboxProps,
useToggleState(checkboxProps),
inputRef
);

return (
<Box
as="th"
ref={ref}
__baseCSS={{ textAlign: 'center' }}
css={css}
{...columnHeaderProps}
>
<input {...inputProps} ref={inputRef} />
</Box>
);
};
10 changes: 9 additions & 1 deletion themes/theme-b2b/src/components/Table.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@ export const Table: Theme['components']['Table'] = {
},
cell: {
p: 'xsmall',
cursor: 'default',
borderBottom: '1px solid',
borderColor: 'gray50',
'&:focus': {
outlineColor: 'orange60',
},
},
checkboxCell: {
textAlign: 'center',
p: 'xsmall',
borderBottom: '1px solid',
borderColor: 'gray50',
'&:focus': {
Expand Down
10 changes: 9 additions & 1 deletion themes/theme-core/src/components/Table.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,15 @@ export const Table: Theme['components']['Table'] = {
},
cell: {
p: 'xsmall',
cursor: 'default',
borderBottom: '1px solid',
borderColor: 'gray50',
'&:focus': {
outlineColor: 'orange60',
},
},
checkboxCell: {
textAlign: 'center',
p: 'xsmall',
borderBottom: '1px solid',
borderColor: 'gray50',
'&:focus': {
Expand Down
12 changes: 10 additions & 2 deletions themes/theme-unicorn/src/components/Table.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,19 @@ export const Table: Theme['components']['Table'] = {
},
cell: {
p: 'xsmall',
cursor: 'default',
borderBottom: '1px solid',
borderColor: 'gray50',
'&:focus': {
outlineColor: 'purple60',
outlineColor: 'orange60',
},
},
checkboxCell: {
textAlign: 'center',
p: 'xsmall',
borderBottom: '1px solid',
borderColor: 'gray50',
'&:focus': {
outlineColor: 'orange60',
},
},
},
Expand Down