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

Custom breakpoints typing and Grid support #170

Open
evertheylen opened this issue Jan 27, 2023 · 3 comments
Open

Custom breakpoints typing and Grid support #170

evertheylen opened this issue Jan 27, 2023 · 3 comments
Labels
enhancement New feature or request

Comments

@evertheylen
Copy link

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;
@juanrgm juanrgm added enhancement New feature or request WIP Work in process and removed WIP Work in process labels Feb 1, 2023
@juanrgm
Copy link
Member

juanrgm commented Feb 2, 2023

Closed via 0f7daa6

@juanrgm juanrgm closed this as completed Feb 2, 2023
@evertheylen
Copy link
Author

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,

@juanrgm
Copy link
Member

juanrgm commented Feb 4, 2023

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.keys should be optional.
  • Add the breakpoint selector classes MuiGrid-grid-{breakpoint}-{size}.

@juanrgm juanrgm reopened this Feb 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants