Skip to content

Commit

Permalink
feat: adding row expansion to stack cards
Browse files Browse the repository at this point in the history
  • Loading branch information
jordankoschei-okta committed Jun 24, 2024
1 parent c6591ca commit 695cd6d
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 8 deletions.
70 changes: 64 additions & 6 deletions packages/odyssey-react-mui/src/labs/DataComponents/StackCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ import {
memo,
useMemo,
ReactNode,
useState,
} from "react";
import {
IconButton as MuiIconButton,
Card as MuiCard,
CardActions as MuiCardActions,
CardActionArea as MuiCardActionArea,
Tooltip as MuiTooltip,
} from "@mui/material";
import styled from "@emotion/styled";
import { useTranslation } from "react-i18next";
Expand All @@ -34,13 +37,18 @@ import {
} from "../../OdysseyDesignTokensContext";
import { Heading5, Paragraph, Support } from "../../Typography";
import { MenuButton, MenuButtonProps } from "../../MenuButton";
import { MoreIcon } from "../../icons.generated";
import {
ChevronDownIcon,
ChevronUpIcon,
MoreIcon,
} from "../../icons.generated";

export const CARD_IMAGE_HEIGHT = "64px";

export type StackCardProps = {
children?: ReactNode;
description?: string;
detailPanel?: ReactNode;
image?: ReactElement;
overline?: string;
title?: string;
Expand Down Expand Up @@ -88,19 +96,22 @@ const CardContentContainer = styled("div", {
gap: odysseyDesignTokens.Spacing3,
}));

const CardChildrenContainer = styled("div")(() => ({
const CardChildrenContainer = styled("div", {
shouldForwardProp: (prop) => prop !== "odysseyDesignTokens",
})<{ odysseyDesignTokens: DesignTokens }>(({ odysseyDesignTokens }) => ({
["* + &"]: {
marginBlockStart: 3,
marginBlockStart: odysseyDesignTokens.Spacing3,
},
}));

const buttonProviderValue = { isFullWidth: true };

const StackCard = ({
Accessory,
Accessory: AccessoryProp,
button,
children,
description,
detailPanel,
image,
menuButtonChildren,
onClick,
Expand All @@ -110,6 +121,43 @@ const StackCard = ({
const odysseyDesignTokens = useOdysseyDesignTokens();
const { t } = useTranslation();

const [isDetailPanelOpen, setIsDetailPanelOpen] = useState<boolean>(false);

const Accessory = useMemo(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: 2,
}}
>
{AccessoryProp}
<MuiTooltip
title={
isDetailPanelOpen
? t("table.rowexpansion.close")
: t("table.rowexpansion.open")
}
>
<MuiIconButton
children={
isDetailPanelOpen ? <ChevronUpIcon /> : <ChevronDownIcon />
}
onClick={() => setIsDetailPanelOpen(!isDetailPanelOpen)}
aria-label={
isDetailPanelOpen
? t("table.rowexpansion.close")
: t("table.rowexpansion.open")
}
/>
</MuiTooltip>
</Box>
),
[AccessoryProp, isDetailPanelOpen, t],
);

const cardContent = useMemo(
() => (
<CardContentContainer odysseyDesignTokens={odysseyDesignTokens}>
Expand Down Expand Up @@ -139,21 +187,31 @@ const StackCard = ({
)}

{children && (
<CardChildrenContainer>{children}</CardChildrenContainer>
<CardChildrenContainer odysseyDesignTokens={odysseyDesignTokens}>
{children}
</CardChildrenContainer>
)}

{detailPanel && isDetailPanelOpen && (
<CardChildrenContainer odysseyDesignTokens={odysseyDesignTokens}>
{detailPanel}
</CardChildrenContainer>
)}
</Box>
</CardContentContainer>
),
[
odysseyDesignTokens,
Accessory,
detailPanel,
image,
odysseyDesignTokens,
menuButtonChildren,
overline,
title,
description,
button,
children,
isDetailPanelOpen,
],
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ const StackContent = ({
[setRowSelection],
);

const renderDetailPanelProp = stackOptions.renderDetailPanel;

const renderDetailPanel = useCallback(
(row: MRT_RowData) => {
return renderDetailPanelProp?.({ row });
},
[renderDetailPanelProp],
);

const { updateRowOrder } = rowReorderingUtilities;

const odysseyDesignTokens = useOdysseyDesignTokens();
Expand Down Expand Up @@ -200,6 +209,7 @@ const StackContent = ({
}
children={children}
description={description}
detailPanel={renderDetailPanel(row)}
image={image}
key={row.id}
menuButtonChildren={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,28 @@ const TableContent = ({
renderRowActions: ({ row }) => renderRowActions({ row }),
enableRowOrdering: hasRowReordering && Boolean(onReorderRows),
enableRowDragging: hasRowReordering && Boolean(onReorderRows),
muiTableBodyRowProps: ({ table, row }) => ({
muiDetailPanelProps: ({ row }) => ({
sx: {
paddingBlock: row.getIsExpanded()
? `${odysseyDesignTokens.Spacing3} !important`
: undefined,
},
}),
muiTableBodyRowProps: ({ table, row, isDetailPanel }) => ({
className: draggableTableBodyRowClassName({
currentRowId: row.id,
draggingRowId: draggingRow?.id,
hoveredRowId: table.getState().hoveredRow?.id,
}),
sx: isDetailPanel
? {
paddingBlock: "0 !important",
border: 0,
["&:hover"]: {
backgroundColor: `${odysseyDesignTokens.HueNeutralWhite} !important`,
},
}
: {},
}),
muiRowDragHandleProps: ({ table, row }) => ({
onKeyDown: (event) => handleDragHandleKeyDown({ table, row, event }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export type TableProps = {
export type StackProps = {
cardProps: (row: MRT_RowData) => StackCardProps;
maxGridColumns?: number;
renderDetailPanel?: (props: { row: MRT_RowData }) => ReactNode;
rowActionMenuItems?: DataTableRowActionsProps["rowActionMenuItems"];
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ export const displayColumnDefOptions = {
},
"mrt-row-expand": {
header: "",
muiTableBodyCellProps: {
sx: {
overflow: "visible",
},
},
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,6 @@ pagination.rowswithtotal = {{firstRow}}-{{lastRow}} of {{totalRows}} rows
pagination.rowswithouttotal = {{firstRow}}-{{lastRow}} rows
table.actions.selectall = Select all
table.actions.selectnone = Select none
table.actions.selectsome = {{selectedRowCount}} selected
table.actions.selectsome = {{selectedRowCount}} selected
table.rowexpansion.open = Open
table.rowexpansion.close = Close
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
Button,
EmptyState,
paginationTypeValues,
DataTableRenderDetailPanelType,
} from "@okta/odyssey-react-mui";

type DataViewMetaProps = DataViewProps &
Expand Down Expand Up @@ -562,3 +563,41 @@ export const DataStackComponent: StoryObj<DataViewMetaProps> = {
);
},
};

export const ExpandableRowsAndCards: StoryObj<DataViewMetaProps> = {
render: function Base(args) {
console.log(args);

const [data, setData] = useState<Person[]>(personData);
const { getData, onReorderRows, onChangeRowSelection } = useDataCallbacks(
data,
setData,
);

const renderAdditionalContent = useCallback(
({ row }: DataTableRenderDetailPanelType) => {
return <Box>This is additional content for row {row.id}</Box>;
},
[],
);

return (
<DataView
availableLayouts={["table", "grid"]}
initialLayout={"grid"}
getData={getData}
hasRowSelection={args.hasRowSelection}
onReorderRows={onReorderRows}
onChangeRowSelection={onChangeRowSelection}
tableOptions={{
columns: personColumns,
renderDetailPanel: renderAdditionalContent,
}}
stackOptions={{
cardProps: cardProps,
renderDetailPanel: renderAdditionalContent,
}}
/>
);
},
};

0 comments on commit 695cd6d

Please sign in to comment.