Skip to content

A flexbox wrapper for MaterialUI Box and Grid components with handy shorthand props

License

Notifications You must be signed in to change notification settings

brandonscript/mui-flexy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

flex-logo

mui-flexy

A flexbox wrapper for Material UI Box and Grid components with handy shorthand props.

NPM Version NPM Downloads GitHub Issues or Pull Requests MUI Versions React Versions

Why?

The problem

If you have never been confused whether to use justify-content or align-items, then Flexy is not for you. If you have, then get started with yarn add mui-flexy or npm install mui-flexy.

Vanilla CSS requires a lot of mental gymnastics to remember which alignment property to use depending on the axis of your flexbox:

justify-content aligns along the main axis and align-items aligns along the cross axis. When you change the axis, you have to re-write your alignments. This gets exponentially more difficult when you introduce responsive breakpoints.

The solution

Science and math solved this problem a long time ago with constants like x and y to represent 2-dimensional space, where x is the horizontal axis and y is the vertical axis.

mui-flexy gives you a way to align things in the same way using x and y props instead, calculating all the hard CSS stuff for you so you don't have to.

So instead of:

<FlexBox
  justifyContent="center" // is this the main or cross axis?
  alignItems="center" // maybe I can use stretch or space-around? 🤷‍♂️
  flexDirection="row" // if I change this to column, do I need to change the other two?
  width="100vw"
  height="100vh"
/>

You can just do:

<FlexBox x="center" y="center" width="100vw" height="100vh" />

// and

<FlexBox column x="left" y="bottom" />

mui-flexy

Get started

Install

yarn add mui-flexy
# or
npm install mui-flexy

Notes:

  • This lib was designed for TypeScript, so please file a bug or PR if you find any issues using it with untyped JS.
  • As of v1.2.0, CommonJS is no longer supported. If you need it, please use an older version, or file a bug/PR.

Dependencies

Make sure you've got @mui/material and its dependencies installed, as well as React:

yarn add @mui/material @emotion/react @emotion/styled react react-dom
# or
npm install @mui/material @emotion/react @emotion/styled react react-dom

If you haven't already, make sure to wrap your app with the MUI ThemeProvider:

import { ThemeProvider, createTheme } from "@mui/material/styles";
import { CssBaseline } from "@mui/material";

const theme = createTheme({
  palette: {
    mode: "light", // or "dark"
  },
});
const App = () => (
  <ThemeProvider theme={theme}>
    <CssBaseline />
    <YourApp />
  </ThemeProvider>
);

Basic usage

Import the FlexBox or FlexGrid components from mui-flexy and use them in your app as you would with MUI's Box or Grid components:

import { Typography } from "@mui/material"; // or use a <p> if you don't like fun typography
import { FlexBox, FlexGrid } from "mui-flex";

<FlexBox x="top" y="center">
  <Typography>Hello, Bajor</Typography>
</FlexBox>;

FlexGrid2

As of v1.2.0, you can also use FlexGrid2 for MUI v6, which is a drop-in replacement for @mui/material/Grid2. Because both v5 and v6 are supported simultaneously in this package, you should use React.lazy() to import FlexGrid2:

// @mui/material v6+
const FlexGrid2 = React.lazy(() => import("mui-flexy/FlexGrid2"));
// @mui/material v5
const FlexGrid2 = React.lazy(() => import("mui-flexy/Unstable_FlexGrid2"));

// Then use it in a <Suspense> block:
<Suspense fallback={<div>{/* Loading... */}</div>}>
  <FlexGrid2 container x="center" y="center">
    <FlexGrid2 item xs={12} sm={6} md={4} lg={3}>
      <Typography>Grids are cool</Typography>
    </FlexGrid2>
  </FlexGrid2>
</Suspense>;

If your transpiler supports top-level await, you can also use await import("mui-flexy/FlexGrid2"):

const FlexGrid2 = muiVersion > 5 ? await import("../src/FlexGrid2") : await import("../src/Unstable_FlexGrid2");

Or import createFlexGrid2 / createUnstableFlexGrid2 from mui-flexy and export your own FlexGrid2:

// for @mui/material v6+
import { createFlexGrid2 } from "mui-flexy/FlexGrid2";
const FlexGrid2 = createFlexGrid2();

// for @mui/material v5
import { createUnstable_FlexGrid2 } from "mui-flexy/Unstable_FlexGrid2";
const FlexGrid2 = createUnstable_FlexGrid2();

More usage & features

Check out the live demo for examples of all mui-flexy's features.

FlexBox can be used as a drop-in replacement for MUI's Box component, with the added benefit of x and y props for alignment:

const YouTooCanCenterADiv = () => (
  <FlexBox x="center" y="center" width="100vw" height="100vh">
    <Typography>2-D coordinate systems are cool</Typography>
  </FlexBox>
);

where:

{
  x: "center",
  y: "center",
  row: true // default is row, or you can pass column
}
produces {
  justifyContent: "center",
  alignItems: "center",
  flexDirection: "row"
}

and

{
  x: "left",
  y: "bottom",
  column: true
}
produces {
  justifyContent: "flex-end",
  alignItems: "flex-start",
  flexDirection: "column"
}

It also supports ResponsiveStyleObject arrays/object notation:

{
  x: ["left", "center", "right"],
  y: ["bottom", "center", "top"],
  row: true
}
produces {
  justifyContent: ["flex-start", "center", "flex-end"],
  alignItems: ["flex-end", "center", "flex-start"],
  flexDirection: "row"
}

//

{
  x: ["left", "space-between"],
  y: ["top", "center"],
  flexDirection: ["row", "column"]
}
produces {
  justifyContent: ["flex-start", "center"],
  alignItems: ["flex-start", "space-between"],
  flexDirection: ["row", "column"]
}

//

{
  x: {
    xs: "left",
    sm: "center",
    md: "right"
  },
  y: {
    xs: "bottom",
    sm: "center",
    md: "top"
  },
  row: true
}
produces {
  justifyContent: {
    xs: "flex-start",
    sm: "center",
    md: "flex-end"
  },
  alignItems: {
    xs: "flex-end",
    sm: "center",
    md: "flex-start"
  },
  flexDirection: "row"
}

//

{
  x: {
    xs: "left",
    sm: "center",
    md: "left",
    lg: "inherit",
    xl: "space-around"
  },
  y: {
    xs: "top",
    sm: "center",
    md: "bottom",
    lg: "space-between",
    xl: "center"
  }
  flexDirection: {
    xs: "row",
    sm: "row",
    md: "column",
    lg: "column",
    xl: "column"
  }
}
produces {
  justifyContent: {
    xs: "flex-start",
    sm: "center",
    md: "flex-end",
    lg: "center",
    xl: "center"
  },
  alignItems: {
    xs: "flex-start",
    sm: "center",
    md: "flex-start",
    lg: "inherit",
    xl: "space-around"
  },
  flexDirection: {
    xs: "row",
    sm: "row",
    md: "column",
    lg: "column",
    xl: "column"
  }
}

As of v1.2.0, you can now use responsive arrays/objects for row and column properties, too:

{
  x: "center",
  y: "center",
  row: [true, true, false], // xs, sm: 'row', md+: 'column'
  // column: [false, false, true] // implied, not required
}

// or

{
  x: "center",
  y: "center",
  row: { xs: true, md: false },
  column: { xs: false, md: true } // implied, not required, but helps with readability
}

It supports reverse, too:

{
  x: "left",
  y: "center",
  reverse: true
  row: true
}
produces {
  justifyContent: "flex-start",
  alignItems: "center",
  flexDirection: "row-reverse"
}

Using a FlexGrid

Like FlexBox, FlexGrid is a drop-in replacement for MUI's Grid component. Note that with @mui/material v6, Unstable_Grid2 has been renamed to Grid2, and Grid is deprecated.

// Grid (v5), based on @mui/material/Grid
<FlexGrid container x="center" y="center">
  <FlexGrid item xs={12} sm={6} md={4} lg={3}>
    <Typography>Grids are cool</Typography>
  </FlexGrid>
</FlexGrid>

// Grid2 (v5), based on @mui/material/Unstable_Grid2
<FlexGrid2 container x="center" y="center">
  <FlexGrid2 xs={12} sm={6} md={4} lg={3}>
    <Typography>Grids are cool</Typography>
  </FlexGrid2>
</FlexGrid2>

// Grid2 (v6), based on @mui/material/Grid2
<FlexGrid2 container x="center" y="center">
  <FlexGrid2 size={{ xs: 12, sm: 6, md: 4, lg: 3 }}>
    <Typography>Grids are cool</Typography>
  </FlexGrid2>
</FlexGrid2>

Refs & component overrides

Both FlexBox and FlexGrid are wrapped with forwardRef, so you can pass a ref to FlexBox and FlexGrid. You can also pass a component prop to override the default div:

import { forwardRef } from "react";

const boxRef = useRef(null);

<FlexBox ref={boxRef} id="my-flex-box">
  <Typography>{`I'm a FlexBox with id ${boxRef.current?.id}`}</Typography>
</FlexBox>;
const SpanFlex = <FlexBox component="span" x="center" y="center" />;
const TypographyFlex = <FlexBox component={Typography} x="center" y="center" variant="subtitle1" />;

About

A flexbox wrapper for MaterialUI Box and Grid components with handy shorthand props

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published