diff --git a/.changeset/fresh-eggs-think.md b/.changeset/fresh-eggs-think.md new file mode 100644 index 0000000000..57b1545bc1 --- /dev/null +++ b/.changeset/fresh-eggs-think.md @@ -0,0 +1,27 @@ +--- +"@comet/admin": minor +--- + +Add the `DataGridPanel` component to replace MUIs default `Panel` used by `DataGrid` to match the Comet DXP design + +It is recommended to add this component to your theme's `defaultProps` of `MuiDataGrid`. + +Example theme configuration for `admin/src/theme.ts`: + +```ts +import { DataGridPanel } from "@comet/admin"; +import { createCometTheme } from "@comet/admin-theme"; +import type {} from "@mui/x-data-grid/themeAugmentation"; + +export const theme = createCometTheme({ + components: { + MuiDataGrid: { + defaultProps: { + components: { + Panel: DataGridPanel, + }, + }, + }, + }, +}); +``` diff --git a/.changeset/weak-meals-juggle.md b/.changeset/weak-meals-juggle.md new file mode 100644 index 0000000000..41c82689ba --- /dev/null +++ b/.changeset/weak-meals-juggle.md @@ -0,0 +1,5 @@ +--- +"@comet/admin-theme": minor +--- + +Improve the styling of the filter and columns panels of `DataGrid` diff --git a/demo/admin/src/theme.ts b/demo/admin/src/theme.ts index 320490e163..29070500c2 100644 --- a/demo/admin/src/theme.ts +++ b/demo/admin/src/theme.ts @@ -1,4 +1,16 @@ +import { DataGridPanel } from "@comet/admin"; import { createCometTheme } from "@comet/admin-theme"; import type {} from "@mui/lab/themeAugmentation"; +import type {} from "@mui/x-data-grid/themeAugmentation"; -export const theme = createCometTheme(); +export const theme = createCometTheme({ + components: { + MuiDataGrid: { + defaultProps: { + components: { + Panel: DataGridPanel, + }, + }, + }, + }, +}); diff --git a/packages/admin/admin-theme/src/componentsTheme/MuiDataGrid.tsx b/packages/admin/admin-theme/src/componentsTheme/MuiDataGrid.tsx index 59c659176a..5811512f72 100644 --- a/packages/admin/admin-theme/src/componentsTheme/MuiDataGrid.tsx +++ b/packages/admin/admin-theme/src/componentsTheme/MuiDataGrid.tsx @@ -1,14 +1,11 @@ import { ArrowDown, ArrowUp, Check, Clear, Close, Delete, MoreVertical, Search } from "@comet/admin-icons"; import { buttonBaseClasses, - buttonClasses, - formControlClasses, getSwitchUtilityClass, iconButtonClasses, - inputAdornmentClasses, inputBaseClasses, - inputClasses, inputLabelClasses, + nativeSelectClasses, svgIconClasses, SvgIconProps, switchClasses, @@ -21,15 +18,19 @@ import type {} from "@mui/x-data-grid/themeAugmentation"; import { mergeOverrideStyles } from "../utils/mergeOverrideStyles"; import { GetMuiComponentTheme } from "./getComponentsTheme"; -export const getMuiDataGrid: GetMuiComponentTheme<"MuiDataGrid"> = (component, { palette, shadows, spacing }) => ({ +const filtersLeftSectionWidth = 120; +const filterDeleteIconSize = 32; +const filterLeftSectionGap = 5; +const filterOperatorInputWidth = filtersLeftSectionWidth - filterDeleteIconSize - filterLeftSectionGap; + +export const getMuiDataGrid: GetMuiComponentTheme<"MuiDataGrid"> = (component, { palette, shadows, spacing, breakpoints }) => ({ ...component, defaultProps: { ...component?.defaultProps, components: { - /* @TODO: add FilterPanelAddIcon to display Comet Add Icon once MUI Datagrid is updated to v6 or higher */ QuickFilterIcon: Search, QuickFilterClearIcon: Clear, - FilterPanelDeleteIcon: Delete, + FilterPanelDeleteIcon: (props: SvgIconProps) => , BooleanCellTrueIcon: Check, BooleanCellFalseIcon: Close, ColumnSortedAscendingIcon: ArrowUp, @@ -38,8 +39,16 @@ export const getMuiDataGrid: GetMuiComponentTheme<"MuiDataGrid"> = (component, { ColumnMenuIcon: (props: SvgIconProps) => , ...component?.defaultProps?.components, }, + componentsProps: { + ...component?.defaultProps?.componentsProps, + baseButton: { + color: "info", + ...component?.defaultProps?.componentsProps?.baseButton, + }, + }, localeText: { noRowsLabel: GRID_DEFAULT_LOCALE_TEXT.noResultsOverlayLabel, + columnsPanelTextFieldLabel: "", ...component?.defaultProps?.localeText, }, }, @@ -58,9 +67,20 @@ export const getMuiDataGrid: GetMuiComponentTheme<"MuiDataGrid"> = (component, { }, }, }, + panelHeader: { + padding: `4px 4px ${spacing(1)} 4px`, + borderBottom: `1px solid ${palette.divider}`, + }, + columnsPanel: { + padding: 0, + }, columnsPanelRow: { marginBottom: spacing(2), + "&:last-child": { + marginBottom: 0, + }, + [`& .${switchClasses.root}`]: { marginRight: 0, }, @@ -113,127 +133,125 @@ export const getMuiDataGrid: GetMuiComponentTheme<"MuiDataGrid"> = (component, { height: "20px", marginRight: "10px", }, - panel: { - ["@media (max-width: 900px)"]: { - width: "100%", - transform: "translate3d(0,0,0)", - }, - }, panelContent: { - padding: spacing(1, 0), - [`& .${gridClasses.filterForm}:first-child .${gridClasses.filterFormLinkOperatorInput}`]: { - display: "flex", - }, - ["@media (max-width: 900px)"]: { - maxHeight: "none", - padding: 0, - }, + padding: spacing(4), + }, + paper: { + border: `1px solid ${palette.grey[100]}`, + boxShadow: shadows[4], + borderRadius: 4, + maxHeight: "none", + flexDirection: "column", }, filterForm: { - margin: spacing(5, 4, 0, 4), - padding: spacing(2, 1), - gap: "5px", - borderBottom: `1px solid ${palette.grey[50]}`, - ["@media (max-width: 900px)"]: { - flexDirection: "row", - flexWrap: "wrap", - margin: spacing(4, 4, 0, 4), - gap: 0, - padding: 0, - paddingBottom: spacing(5), - "&:last-child": { - marginBottom: 0, - paddingBottom: 0, - }, - }, - "&:last-child": { - border: "none", + flexDirection: "row", + flexWrap: "wrap", + padding: 0, + + [`${breakpoints.up("md")}`]: { + flexWrap: "nowrap", + gap: spacing(1), }, - [`.${formControlClasses.root}`]: { - marginRight: 0, + + ["&:not(:last-child)"]: { + paddingBottom: spacing(4), + marginBottom: spacing(4), + borderBottom: `1px solid ${palette.divider}`, + + [`${breakpoints.up("md")}`]: { + paddingBottom: spacing(2), + marginBottom: spacing(2), + borderBottomColor: palette.grey[50], + }, }, - [`.${iconButtonClasses.root}`]: { - height: 32, - width: 32, + + [`&:first-child .${gridClasses.filterFormLinkOperatorInput}`]: { + // The first "Operator"-select is fully hidden by default when there is only one filter. + // Setting `display: block` makes sure it takes up it's space as if it were visible to prevent the alignment from breaking. + // Even though `display: block` is set now, it's still not visible, due to it's default styling of `visibility: hidden`. + display: "block", }, + [`.${inputLabelClasses.root}`]: { - transform: "translateY(-22px)", + position: "static", + transform: "none", fontSize: 14, - ["@media (max-width: 900px)"]: { - position: "relative", - transform: "unset", - }, + fontWeight: 600, }, - [`.${inputClasses.root}`]: { - marginTop: 0, - }, - [`& .${inputAdornmentClasses.root}`]: { - padding: spacing(0, 1, 0, 0), - }, - }, - filterFormLinkOperatorInput: { - ["@media (max-width: 900px)"]: { - padding: spacing(2, 1), - width: "27.2%", + + [`.${nativeSelectClasses.select}`]: { + whiteSpace: "nowrap", + textOverflow: "ellipsis", }, }, filterFormDeleteIcon: { + width: filterDeleteIconSize, + height: filterDeleteIconSize, + marginRight: filterLeftSectionGap, + marginTop: "auto", + marginBottom: 3, justifyContent: "center", - [`& .${svgIconClasses.root}`]: { - width: 16, - height: 16, + [`${breakpoints.up("md")}`]: { + marginRight: 0, }, - ["@media (max-width: 900px)"]: { - padding: spacing(2, 1), - alignItems: "flex-start", - justifyContent: "flex-end", - width: "11.1%", + [`& > .${iconButtonClasses.root}`]: { + height: "100%", }, }, - panelFooter: { - borderTop: `1px solid ${palette.grey[100]}`, - padding: "7px 0", - [`.${buttonClasses.root}`]: { - color: palette.primary.main, - }, - ["@media (max-width: 900px)"]: { - justifyContent: "center", - boxShadow: shadows[4], + filterFormLinkOperatorInput: { + width: filterOperatorInputWidth, + marginRight: 0, + + [`${breakpoints.up("md")}`]: { + width: 80, }, }, filterFormColumnInput: { - marginRight: spacing(4), + width: `calc(100% - ${filtersLeftSectionWidth}px)`, + paddingLeft: spacing(2), + boxSizing: "border-box", - ["@media (max-width: 900px)"]: { - padding: spacing(2, 1), - width: "61.6%", + [`${breakpoints.up("md")}`]: { + width: 199, + paddingLeft: 0, }, }, filterFormOperatorInput: { - margin: spacing(0, 4, 0, 0), + marginTop: spacing(3), + flexBasis: filterOperatorInputWidth, + flexGrow: 1, - ["@media (max-width: 900px)"]: { - padding: spacing(2, 1), - width: "38.3%", + [`${breakpoints.up("md")}`]: { + marginTop: 0, + width: 110, }, }, filterFormValueInput: { - ["@media (max-width: 900px)"]: { - padding: spacing(2, 1), - width: "61.6%", + width: `calc(100% - ${filtersLeftSectionWidth}px)`, + paddingLeft: spacing(2), + boxSizing: "border-box", + marginTop: spacing(3), + + [`${breakpoints.up("md")}`]: { + width: 199, + paddingLeft: 0, + marginTop: 0, }, - }, - paper: { - boxShadow: shadows[4], - border: `1px solid ${palette.divider}`, - borderRadius: "4px", - ["@media (max-width: 900px)"]: { - height: "100%", - maxHeight: "none", + + "&:empty": { + display: "none", // Make space for `filterFormOperatorInput` to expand and take up the full width + }, + + [`& .${inputBaseClasses.root}`]: { + marginTop: 0, }, }, + panelFooter: { + padding: spacing(2), + borderTop: `1px solid ${palette.divider}`, + }, // @ts-expect-error This key exists but is missing in the types. toolbarQuickFilter: { paddingBottom: 0, diff --git a/packages/admin/admin/src/dataGrid/DataGridPanel.tsx b/packages/admin/admin/src/dataGrid/DataGridPanel.tsx new file mode 100644 index 0000000000..877e2e215d --- /dev/null +++ b/packages/admin/admin/src/dataGrid/DataGridPanel.tsx @@ -0,0 +1,409 @@ +import { Add, Check, Close, Reset } from "@comet/admin-icons"; +import { ComponentsOverrides, css, Dialog, DialogContent, Divider, Theme, Typography, useMediaQuery, useTheme, useThemeProps } from "@mui/material"; +import { + gridColumnVisibilityModelSelector, + gridFilterableColumnDefinitionsSelector, + GridFilterItem, + gridFilterModelSelector, + GridPanel, + GridPanelProps, + gridPreferencePanelStateSelector, + GridPreferencePanelsValue, + useGridApiContext, + useGridRootProps, + useGridSelector, +} from "@mui/x-data-grid"; +import { ReactNode, useCallback, useMemo } from "react"; +import { FormattedMessage } from "react-intl"; + +import { Button } from "../common/buttons/Button"; +import { createComponentSlot } from "../helpers/createComponentSlot"; +import { ThemedComponentBaseProps } from "../helpers/ThemedComponentBaseProps"; + +const panelTypeTitle: Record = { + [GridPreferencePanelsValue.filters]: , + [GridPreferencePanelsValue.columns]: , +}; + +export type DataGridPanelClassKey = + | "desktopGridPanel" + | "desktopPanelFooterDivider" + | "desktopPanelFooter" + | "desktopAddFilterButton" + | "mobileDialog" + | "mobileDialogHeader" + | "mobileDialogTitle" + | "mobileDialogCloseButton" + | "mobileDialogContent" + | "mobileDialogFooter" + | "mobileAddFilterButtonWrapper" + | "mobileAddFilterButton" + | "mobileDialogFooterActions" + | "resetFiltersButton" + | "resetColumnsButton" + | "applyButton"; + +export type DataGridPanelProps = Pick & + Omit< + ThemedComponentBaseProps<{ + desktopGridPanel: typeof GridPanel; + desktopPanelFooterDivider: typeof Divider; + desktopPanelFooter: "div"; + desktopAddFilterButton: typeof Button; + mobileDialog: typeof Dialog; + mobileDialogHeader: "div"; + mobileDialogTitle: typeof Typography; + mobileDialogCloseButton: typeof Button; + mobileDialogContent: typeof DialogContent; + mobileDialogFooter: "div"; + mobileAddFilterButtonWrapper: "div"; + mobileAddFilterButton: typeof Button; + mobileDialogFooterActions: "div"; + resetFiltersButton: typeof Button; + resetColumnsButton: typeof Button; + applyButton: typeof Button; + }>, + "sx" + > & { + iconMapping?: { + closeDialog?: ReactNode; + addFilter?: ReactNode; + resetFilters?: ReactNode; + resetColumns?: ReactNode; + apply?: ReactNode; + }; + }; + +type OwnerState = { + openedPanelValue: GridPreferencePanelsValue | undefined; +}; + +const addFilterText = ; + +let lastAddedFilterItemId = 0; + +export const DataGridPanel = (inProps: DataGridPanelProps) => { + const { children, open, slotProps, iconMapping = {} } = useThemeProps({ props: inProps, name: "CometAdminDataGridPanel" }); + const apiRef = useGridApiContext(); + const filterModel = useGridSelector(apiRef, gridFilterModelSelector); + const filterableColumns = useGridSelector(apiRef, gridFilterableColumnDefinitionsSelector); + const { openedPanelValue } = useGridSelector(apiRef, gridPreferencePanelStateSelector); + const initialColumnVisibilityModel = useMemo(() => gridColumnVisibilityModelSelector(apiRef), [apiRef]); + const rootProps = useGridRootProps(); + + const { + closeDialog: closeDialogIcon = , + addFilter: addFilterIcon = , + resetFilters: resetFiltersIcon = , + resetColumns: resetColumnsIcon = , + apply: applyIcon = , + } = iconMapping; + + const geNewFilterItem = useCallback(() => { + const firstColumnWithOperator = filterableColumns.find((colDef) => colDef.filterOperators?.length); + + if (!firstColumnWithOperator?.filterOperators?.length) { + return null; + } + + return { + columnField: firstColumnWithOperator.field, + operatorValue: firstColumnWithOperator.filterOperators[0].value, + id: lastAddedFilterItemId++, + }; + }, [filterableColumns]); + + const filterItems = useMemo(() => { + if (filterModel.items.length) { + return filterModel.items; + } + + const newFilterItem = geNewFilterItem(); + + if (newFilterItem) { + return [newFilterItem]; + } + + return []; + }, [filterModel.items, geNewFilterItem]); + + const addNewFilter = useCallback(() => { + const newFilterItem = geNewFilterItem(); + + if (newFilterItem) { + apiRef.current.upsertFilterItems([...filterItems, newFilterItem]); + } + }, [apiRef, filterItems, geNewFilterItem]); + + const resetFilters = useCallback(() => { + apiRef.current.setFilterModel({ items: [] }); + }, [apiRef]); + + const resetColumns = useCallback(() => { + apiRef.current.setColumnVisibilityModel(initialColumnVisibilityModel); + }, [apiRef, initialColumnVisibilityModel]); + + const closeDialog = useCallback(() => { + if (openedPanelValue === GridPreferencePanelsValue.filters) { + apiRef.current.hideFilterPanel(); + } else { + apiRef.current.hidePreferences(); + } + }, [apiRef, openedPanelValue]); + + const theme = useTheme(); + const renderFullScreen = useMediaQuery(theme.breakpoints.down("md")); + + const ownerState: OwnerState = { + openedPanelValue, + }; + + const resetFiltersButton = ( + + + + ); + + const resetColumnsButton = ( + + + + ); + + const applyButton = ( + + + + ); + + if (renderFullScreen) { + return ( + + + {!!openedPanelValue && panelTypeTitle[openedPanelValue]} + + {closeDialogIcon} + + + {children} + + {openedPanelValue === GridPreferencePanelsValue.filters && !rootProps.disableMultipleColumnsFiltering && ( + + + {addFilterText} + + + )} + + {openedPanelValue === GridPreferencePanelsValue.filters && ( + <> + {resetFiltersButton} + {applyButton} + + )} + {openedPanelValue === GridPreferencePanelsValue.columns && ( + <> + {resetColumnsButton} + {applyButton} + + )} + + + + ); + } + + return ( + + {children} + + + {openedPanelValue === GridPreferencePanelsValue.filters && ( + <> +
+ {!rootProps.disableMultipleColumnsFiltering && ( + + {addFilterText} + + )} +
+ {resetFiltersButton} + + )} + {openedPanelValue === GridPreferencePanelsValue.columns && ( + <> + {resetColumnsButton} + {applyButton} + + )} +
+
+ ); +}; + +const DesktopGridPanel = createComponentSlot(GridPanel)({ + componentName: "DataGridPanel", + slotName: "desktopGridPanel", +})(css` + .MuiDataGrid-panelHeader, + .MuiDataGrid-panelFooter { + // Hide MUIs header and footer so we can add our own with a better structure for styling + display: none; + } +`); + +const DesktopPanelFooterDivider = createComponentSlot(Divider)({ + componentName: "DataGridPanel", + slotName: "desktopPanelFooterDivider", +})(); + +const DesktopPanelFooter = createComponentSlot("div")({ + componentName: "DataGridPanel", + slotName: "desktopPanelFooter", +})( + ({ theme }) => css` + display: flex; + justify-content: space-between; + padding: ${theme.spacing(4)}; + `, +); + +const DesktopAddFilterButton = createComponentSlot(Button)({ + componentName: "DataGridPanel", + slotName: "desktopAddFilterButton", +})(); + +const MobileDialog = createComponentSlot(Dialog)({ + componentName: "DataGridPanel", + slotName: "mobileDialog", +})(css` + .MuiDataGrid-panelContent { + max-height: none; + } + + .MuiDataGrid-panelHeader, + .MuiDataGrid-panelFooter { + // Hide MUIs header and footer so we can add our own with a better structure for styling + display: none; + } +`); + +const MobileDialogHeader = createComponentSlot("div")({ + componentName: "DataGridPanel", + slotName: "mobileDialogHeader", +})( + ({ theme }) => css` + position: relative; + display: flex; + align-items: center; + justify-content: space-between; + padding: ${theme.spacing(2)}; + padding-left: ${theme.spacing(4)}; + box-shadow: ${theme.shadows[4]}; + `, +); + +const MobileDialogTitle = createComponentSlot(Typography)({ + componentName: "DataGridPanel", + slotName: "mobileDialogTitle", +})(); + +const MobileDialogCloseButton = createComponentSlot(Button)({ + componentName: "DataGridPanel", + slotName: "mobileDialogCloseButton", +})(css` + min-width: 0; // TODO: Should this be done in the theme? +`); + +const MobileDialogContent = createComponentSlot(DialogContent)({ + componentName: "DataGridPanel", + slotName: "mobileDialogContent", +})( + ({ theme }) => css` + padding: 0; + background-color: white; + + ${theme.breakpoints.up("sm")} { + padding: 0; + } + `, +); + +const MobileDialogFooter = createComponentSlot("div")({ + componentName: "DataGridPanel", + slotName: "mobileDialogFooter", +})(); + +const MobileAddFilterButtonWrapper = createComponentSlot("div")({ + componentName: "DataGridPanel", + slotName: "mobileAddFilterButtonWrapper", +})( + ({ theme }) => css` + position: relative; + display: flex; + justify-content: center; + padding: ${theme.spacing(2)} ${theme.spacing(4)}; + box-shadow: ${theme.shadows[4]}; + border-bottom: 1px solid ${theme.palette.divider}; + `, +); + +const MobileAddFilterButton = createComponentSlot(Button)({ + componentName: "DataGridPanel", + slotName: "mobileAddFilterButton", +})(); + +const MobileDialogFooterActions = createComponentSlot("div")({ + componentName: "DataGridPanel", + slotName: "mobileDialogFooterActions", +})( + ({ theme }) => css` + display: flex; + justify-content: space-between; + padding: ${theme.spacing(4)}; + box-shadow: ${theme.shadows[4]}; + `, +); + +const ResetFiltersButton = createComponentSlot(Button)({ + componentName: "DataGridPanel", + slotName: "resetFiltersButton", +})(); + +const ResetColumnsButton = createComponentSlot(Button)({ + componentName: "DataGridPanel", + slotName: "resetColumnsButton", +})(); + +const ApplyButton = createComponentSlot(Button)({ + componentName: "DataGridPanel", + slotName: "applyButton", +})(); + +declare module "@mui/material/styles" { + interface ComponentsPropsList { + CometAdminDataGridPanel: DataGridPanelProps; + } + + interface ComponentNameToClassKey { + CometAdminDataGridPanel: DataGridPanelClassKey; + } + + interface Components { + CometAdminDataGridPanel?: { + defaultProps?: Partial; + styleOverrides?: ComponentsOverrides["CometAdminDataGridPanel"]; + }; + } +} diff --git a/packages/admin/admin/src/index.ts b/packages/admin/admin/src/index.ts index 25f4b5b049..1ec990b73c 100644 --- a/packages/admin/admin/src/index.ts +++ b/packages/admin/admin/src/index.ts @@ -49,6 +49,7 @@ export { ContentOverflow, ContentOverflowClassKey, ContentOverflowProps } from " export { CrudContextMenu, CrudContextMenuClassKey, CrudContextMenuProps } from "./dataGrid/CrudContextMenu"; export { CrudMoreActionsMenu, CrudMoreActionsMenuContext, CrudMoreActionsMenuItem, CrudMoreActionsMenuProps } from "./dataGrid/CrudMoreActionsMenu"; export { CrudVisibility, CrudVisibilityProps } from "./dataGrid/CrudVisibility"; +export { DataGridPanel, DataGridPanelClassKey, DataGridPanelProps } from "./dataGrid/DataGridPanel"; export { ExportApi, useDataGridExcelExport } from "./dataGrid/excelExport/useDataGridExcelExport"; export { GridCellContent, GridCellContentClassKey, GridCellContentProps } from "./dataGrid/GridCellContent"; export { GridColDef } from "./dataGrid/GridColDef"; diff --git a/storybook/.storybook/preview.tsx b/storybook/.storybook/preview.tsx index 172b5310df..eb469a9629 100644 --- a/storybook/.storybook/preview.tsx +++ b/storybook/.storybook/preview.tsx @@ -1,6 +1,6 @@ import "@fontsource-variable/roboto-flex/full.css"; -import { MainContent, MuiThemeProvider } from "@comet/admin"; +import { DataGridPanel, MainContent, MuiThemeProvider } from "@comet/admin"; import { DateFnsLocaleProvider } from "@comet/admin-date-time"; import { createCometTheme } from "@comet/admin-theme"; import { createTheme as createMuiTheme, GlobalStyles } from "@mui/material"; @@ -70,7 +70,20 @@ const preview: Preview = { decorators: [ (Story, context) => { const { theme: selectedTheme, locale: selectedLocale } = context.args; - const theme = selectedTheme === themeOptions.defaultMui ? createMuiTheme() : createCometTheme(); + const theme = + selectedTheme === themeOptions.defaultMui + ? createMuiTheme() + : createCometTheme({ + components: { + MuiDataGrid: { + defaultProps: { + components: { + Panel: DataGridPanel, + }, + }, + }, + }, + }); return ( diff --git a/storybook/src/admin/toolbar/DataGridToolbar.stories.tsx b/storybook/src/admin/toolbar/DataGridToolbar.stories.tsx index fa5471a4f2..a80e6dfeaa 100644 --- a/storybook/src/admin/toolbar/DataGridToolbar.stories.tsx +++ b/storybook/src/admin/toolbar/DataGridToolbar.stories.tsx @@ -1,7 +1,18 @@ -import { DataGridToolbar, FillSpace, GridColumnsButton, GridFilterButton, StackLink, ToolbarActions, ToolbarItem } from "@comet/admin"; +import { + Button, + DataGridToolbar, + FillSpace, + GridColumnsButton, + GridFilterButton, + StackLink, + ToolbarActions, + ToolbarItem, + useDataGridRemote, + usePersistentColumnState, +} from "@comet/admin"; import { Add as AddIcon } from "@comet/admin-icons"; -import { Button } from "@mui/material"; -import { DataGrid, GridToolbarQuickFilter } from "@mui/x-data-grid"; +import { DataGrid as DataGridCommunity, GridToolbarQuickFilter } from "@mui/x-data-grid"; +import { DataGridPro } from "@mui/x-data-grid-pro"; import { storyRouterDecorator } from "../../story-router.decorator"; @@ -11,50 +22,62 @@ const data = [ { id: "e60900ec-3c69-4e67-8d78-83a10c7573d3", firstname: "Sophia", lastname: "Williams" }, ]; +const gridOptions = ["Community", "Pro"] as const; + export default { title: "@comet/admin/DataGridToolbar", decorators: [storyRouterDecorator()], + argTypes: { + gridVersion: { + name: "Data Grid Version", + control: "select", + options: gridOptions, + }, + }, + args: { gridVersion: gridOptions[0] }, }; export const _DataGridToolbar = { - render: () => { + render: ({ gridVersion }: { gridVersion: (typeof gridOptions)[number] }) => { + const dataGridProps = { ...useDataGridRemote(), ...usePersistentColumnState("FooBar") }; + const columns = [ { field: "firstname", headerName: "First Name", width: 150 }, { field: "lastname", headerName: "Last Name", width: 150 }, ]; + const Toolbar = () => { + return ( + + + + + + + + + + + + + + + + ); + }; + + const DataGrid = gridVersion === "Community" ? DataGridCommunity : DataGridPro; + return ( ( - - - - - - - - - - - - - - - - ), + Toolbar, }} /> );