suid
suid copied to clipboard
Custom breakpoints typing and Grid support
I wanted to customize the breakpoints (as MUI normally supports this). It slightly differs from how you do it in MUI, and at least one component does not support it (Grid). First of all, I found out you have to augment a different module to adjust the Breakpoint type, as follows:
declare module '@suid/system/createTheme/createBreakpoints' {
interface BreakpointOverrides {
xs: false; // removes the 'xs' breakpoint
tiny: true: // adds the 'tiny' breakpoint
}
}
This is enough to make styled work, for example with [theme.breakpoints.up('tiny')]: {...}. It would be nice if the documentation specified this.
As for Grid, the breakpoints are hardcoded into the code. I'm not sure how to get around this. I've fixed the types (see below) but it's the implementation itself that has the breakpoints hardcoded. I'm not sure how I can adjust the many hardcoded values. And I certainly wouldn't know how to do this automatically from MUI source (as this is the overall goal of SUID).
Any help would be appreciated :)
Fixed `@suid/material/Grid/GridProps.d.ts`
import { OverrideProps } from "../OverridableComponent";
import { Theme } from "../styles";
import { GridClasses } from "./gridClasses";
import { ResponsiveStyleValue, SystemProps } from "@suid/system";
import { Breakpoint } from "@suid/system/createTheme/createBreakpoints"; // <-- note the extra import
import SxProps from "@suid/system/sxProps";
import { ElementType } from "@suid/types";
import { JSXElement } from "solid-js";
export type GridDirection = "row" | "row-reverse" | "column" | "column-reverse";
export type GridSpacing = number | string;
export type GridWrap = "nowrap" | "wrap" | "wrap-reverse";
export type GridSize = "auto" | number;
export interface GridTypeMap<P = {}, D extends ElementType = "div"> {
name: "MuiGrid";
defaultPropNames: "columns" | "container" | "direction" | "item" | "spacing" | "wrap" | "zeroMinWidth" | "rowSpacing" | "columnSpacing" | Breakpoint;
selfProps: {
/**
* The content of the component.
*/
children?: JSXElement;
/**
* Override or extend the styles applied to the component.
*/
classes?: Partial<GridClasses>;
/**
* The number of columns.
* @default 12
*/
columns?: ResponsiveStyleValue<number>;
/**
* Defines the horizontal space between the type `item` components.
* It overrides the value of the `spacing` prop.
*/
columnSpacing?: ResponsiveStyleValue<GridSpacing>;
/**
* If `true`, the component will have the flex *container* behavior.
* You should be wrapping *items* with a *container*.
* @default false
*/
container?: boolean;
/**
* Defines the `flex-direction` style property.
* It is applied for all screen sizes.
* @default 'row'
*/
direction?: ResponsiveStyleValue<GridDirection>;
/**
* If `true`, the component will have the flex *item* behavior.
* You should be wrapping *items* with a *container*.
* @default false
*/
item?: boolean;
/**
* Defines the vertical space between the type `item` components.
* It overrides the value of the `spacing` prop.
*/
rowSpacing?: ResponsiveStyleValue<GridSpacing>;
/**
* Defines the space between the type `item` components.
* It can only be used on a type `container` component.
* @default 0
*/
spacing?: ResponsiveStyleValue<GridSpacing>;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme>;
/**
* Defines the `flex-wrap` style property.
* It's applied for all screen sizes.
* @default 'wrap'
*/
wrap?: GridWrap;
/**
* If `true`, it sets `min-width: 0` on the item.
* Refer to the limitations section of the documentation to better understand the use case.
* @default false
*/
zeroMinWidth?: boolean;
} & {
/**
* If a number, it sets the number of columns the grid item uses.
* It can't be greater than the total number of columns of the container (12 by default).
* If 'auto', the grid item's width matches its content.
* If false, the prop is ignored.
* If true, the grid item's width grows to use the space available in the grid container.
* The value is applied for the this breakpoint and wider screens if not overridden.
* @default false
*/
[key in Breakpoint]?: boolean | GridSize
};
props: P & SystemProps<Theme> & GridTypeMap["selfProps"];
defaultComponent: D;
}
export type GridProps<D extends ElementType = GridTypeMap["defaultComponent"], P = {}> = OverrideProps<GridTypeMap<P, D>, D>;
export default GridProps;
Closed via 0f7daa6121aeba5c872f5abe830cdbe524db2853
Thanks for the fix, but it seems to me this only fixes the typing, not the implementation? I may not have been clear in my original issue but I believe the implementation of Grid has the breakpoints hardcoded. For example, see https://github.com/swordev/suid/blob/main/packages/material/src/Grid/Grid.tsx#L58 where it says:
lg: false,
md: false,
sm: false,
But that lines are for the dummy MuiGrid-grid-{breakpoint}-{size} classes, the code works:
https://stackblitz.com/edit/angular-t9udkq?file=src%2FApp.tsx (SUID) https://stackblitz.com/edit/react-znhsdj?file=demo.tsx (MUI)
import { Grid, useMediaQuery } from '@suid/material';
import { createTheme, ThemeProvider } from '@suid/material/styles';
declare module '@suid/material/styles' {
interface BreakpointOverrides {
xs: false;
sm: false;
md: false;
lg: false;
xl: false;
mobile: true;
tablet: true;
laptop: true;
desktop: true;
}
}
const theme = createTheme({
breakpoints: {
keys: ['mobile', 'tablet', 'laptop', 'desktop'],
values: {
mobile: 0,
tablet: 600,
laptop: 900,
desktop: 1200,
},
},
});
export default function BreakpointsExample() {
const mediaQuery: {
[K in keyof typeof theme.breakpoints.keys[number]]: () => boolean;
} = {} as any;
theme.breakpoints.keys.forEach(
(key) => (mediaQuery[key] = useMediaQuery(theme.breakpoints.up(key)))
);
const breakpoint = () =>
theme.breakpoints.keys
.map((key) => mediaQuery[key]() && key)
.filter((v) => !!v)
.slice(-1);
return (
<ThemeProvider theme={theme}>
<Grid container>
<Grid
item
height={100}
border={1}
borderColor="black"
mobile={12}
tablet={6}
laptop={3}
desktop={1}
>
{breakpoint()}
</Grid>
</Grid>
</ThemeProvider>
);
}
So there are two issues:
theme.breakpoints.keysshould be optional.- Add the breakpoint selector classes
MuiGrid-grid-{breakpoint}-{size}.