2

I'm just starting with Material UI. Thanks for bearing with me.

I know you can use things like <Box mx={2}> out-of-the-box (ha). So if I wanted to put a margin around, say, a TextField, I could wrap it in a box.

Is there a simple way to set up my app's theme so that any component can use those style function props? (m, p, display, etc)

So that I could to <TextField mx={2}/> without having to wrap it in a Box.

The docs imply that you can do this: (the example uses ThemeProvider from styled-components but I'm assuming that MUI's ThemeProvider works the same way???)

import React from 'react'
import { ThemeProvider } from 'styled-components'

const theme = {
  spacing: 4,
  palette: {
    primary: '#007bff',
  },
};

export default function App() {
  return (
    <ThemeProvider theme={theme}>
      {/* children */}
    </ThemeProvider>
  )
}

I've tried this but it crashes from the TextField's my prop:

import { createMuiTheme, TextField, ThemeProvider } from '@material-ui/core';

// Greatly simplified version of my component
const App = () => <TextField my={2}/> 

let theme = createMuiTheme({})

export default () =>
  <ThemeProvider theme={ theme }>
    <App/>
  </ThemeProvider>;

I can do something like this and it works:

function App() {
  const Input = styled(TextField)(compose(spacing))

  return <Input my={3}/>
}

But then I'd have to compose my components every time I want to do use the style functions.

Jonathan Tuzman
  • 11,568
  • 18
  • 69
  • 129

1 Answers1

2

The docs are showing how the theme can parameterize the Box features (e.g. such that a spacing unit is 4px instead of 8px) -- the theme doesn't do anything to enable those features.

Material-UI is intending to support @material-ui/system features on core components in v5, but that is still months away.

Your main options are doing something like you showed in your example (though you should move const Input = styled(TextField)(compose(spacing)) to the top-level rather than doing this within render of App). You could put this in a separate file and import this component instead of TextField whenever you want to use those features. For instance:

MyTextField.js

import TextField from "@material-ui/core/TextField";
import { styled } from "@material-ui/core/styles";
import { compose, spacing } from "@material-ui/system";

export default styled(TextField)(compose(spacing));

App.js

import React from "react";
import TextField from "./MyTextField";

export default function App() {
  return (
    <div className="App">
      <TextField variant="outlined" label="Material-UI system demo" />
    </div>
  );
}

Edit Material-UI system demo (forked)

Another option is to use Box with the clone prop and wrap the component you want to style. For instance:

import React from "react";
import TextField from "@material-ui/core/TextField";
import Box from "@material-ui/core/Box";

export default function App() {
  return (
    <div className="App">
      <Box my={3} clone>
        <TextField variant="outlined" label="Box demo" />
      </Box>
    </div>
  );
}

Edit Box demo

You can also use the component prop of Box:

import React from "react";
import TextField from "@material-ui/core/TextField";
import Box from "@material-ui/core/Box";

export default function App() {
  return (
    <div className="App">
      <Box my={3} component={TextField} variant="outlined" label="Box demo" />
    </div>
  );
}

Edit Box demo (forked)

Related answers:

Ryan Cogswell
  • 75,046
  • 9
  • 218
  • 198