Доброго времени суток, Хабр!

Итак, material-uireactJS's фрэймворк, предоставляющий готовые google решения для быстрой и довольно простой web разработки.

Material-UI достаточно крупная библиотека, где ключевой частью react компонентов и стилизации является @material-ui/core (целью ее использования должен быть немаленький проект).

Этот туториал не включает в себя продвинутое использование material-ui. Это мини мануал по стилизации компонентов.

Использовать material компоненты действительно не сложно, но есть нюансы использования стилизации. Об этом собственно и пойдет речь.

Рассмотрим следующее


  1. JSS и немного о синтаксисе;
  2. Стилизация классовых react, material компонентов;
  3. Стилизация функциональных с использованием хуков react, material компонентов;
  4. Стилизация посредством styledComponent react, material компонентов;
  5. Провайдер theme;
  6. Переопределение material компонентов;

GO под кат!


1. JSS и немного о синтаксисе


JSS(библиотека) — стилизация css на языке Javascript в декларативном стиле весом в 6кб, без учета установки плагинов. JSS не компилируется в inline-style и может повторно переиспользоваться, избегая конфликтов, за счет генерации уникальных имен классов. Имеет возможность работать посредством server-side в nodejs и имеет расширение [.js]. В jss нет ограничения на установку стилей для псевдо-селекторов или псевдо-элементов и подобном. Описывается jss в стиле camelCase. Одной из ключевых возможностей jss — возможность архитектурного подхода в описании стилей.

Да, и эта штука используется в material-ui в качестве семантики.

Для того чтобы начать использовать jss необходимо вызвать его определенный метод опрокинув в качестве аргумента объект стилей, который вернет функцию, вызвав которую мы получим генератор jss классов, например:

/src/components/JssComponent
JssComponent.js


import React from "react";

import useStyles from "./style";

export default function JssComponent() {
  // получаем метод для генерации классов jss
  const classes = useStyles();

  return (
    <div className={classes.root}>
      <h1>That's JssComponent</h1>
      <h2 className="basic_h2">I use JSS</h2>
      <div className={classes.content_div}>
        Any Text
      </div>
    </div>
  );
}

style.js

// Импортируем метод для создания функции, вызвав которую мы получим функцию генерирующую классы jss
import { createUseStyles } from "react-jss";

const rootStyle = {
  width: 400,
  border: "1px solid grey",
  margin: "0px auto",
  padding: 15
};

const fontStyle = {
  fontWeight: "bold",
  fontStyle: "italic"
};

const useStyles = createUseStyles({
  root: {
    ...rootStyle,
    "& h1": {
      textAlign: "center",
      color: "purple"
    },
    "& .basic_h2": {
      textAlign: "right",
      color: "green",
      cursor: "pointer",
      "&:hover": {
        color: "purple"
      }
    }
  },
  content_div: {
    textAlign: "justify",
    ...fontStyle
  }
});

export default useStyles;

2. Стилизация классовых react, material компонентов


React не отказался от поддержки написания интерфейсов на классах. Следующим образом используются стили в классовых material компонентов:

/src/components/ClassComponent
ClassComponent.js


import React from "react";
import { withStyles } from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";

import styles from "./style";

class ClassComponent extends React.Component {
  render() {
    const { classes } = this.props;

    return <Button className={classes.button}>ClassComponent</Button>;
  }
}

// Опрокидываем в пропс объект стилей 
export default withStyles(styles)(ClassComponent);

style.js

// Простой js объект описывающий стили компонента
const styles = {
    button: {
      backgroundColor: "grey",
      border: 0,
      borderRadius: 3,
      boxShadow: "0 3px 5px 2px",
      color: "black",
      height: 48,
      padding: "0 30px",
      margin: 10
    }
  };
  
  export default styles;

3. Стилизация функциональных с использованием хуков react, material компонентов


Начиная с 16.8 релиза React появилась новая возможность в написании интерфейсов на хуках:

/src/components/HookComponent
HookComponent.js


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

import useStyles from "./style";

const HookComponent = props => {
  // Получаем функцию для генерации классов
  const classes = useStyles();

  return <Button className={classes.button}>HookComponent</Button>;
};

export default HookComponent;

style.js

// Импортируем метод для создания функции, вызвав которую мы получим функцию для генерации классов 
import { makeStyles } from "@material-ui/core/styles";

const useStyles = makeStyles({
  button: {
    backgroundColor: "grey",
    border: 0,
    borderRadius: 3,
    boxShadow: "0 3px 5px 2px",
    color: "black",
    height: 48,
    padding: "0 30px",
    margin: 10
  }
});

export default useStyles;

4. Стилизация посредством styledComponent react, material компонентов


StyledComponent — принцип стилизации компонентов без метода, возвращающего функцию для генерации классов.

/src/components/StyledComponent
StyledComponent.js


import React from "react";
// Импортируем метод для стилизации любого типа компонентов
import { styled } from "@material-ui/core/styles";
// Предоставляем компонент для стилизации
import Button from "@material-ui/core/Button";

import styles from './style';

// Стилизованный компонент на все времена
const ButtonComponent = styled(Button)({ ...styles });

export default function StyledComponent() {
  return <ButtonComponent>StyledComponent</ButtonComponent>;
}

style.js

// Простой js объект описывающий стили компонента
const styles = {
    backgroundColor: "grey",
    border: 0,
    borderRadius: 3,
    boxShadow: "0 3px 5px 2px",
    color: "black",
    height: 48,
    padding: "0 30px",
    margin: 10
  };

  export default styles;

5. Провайдер theme.


Theming — это предоставление дефолтных стилей проекту, либо его части, учитывая вложенность компонентов, концептуально схож с контекстом в React. В material-ui уже есть готовый объект theme заданный по умолчанию, но вы можете создать его сами под свои нужды, предварительно обеспечив его доступность через provider, таким образом вы предоставите функцию с объектом theme в качестве аргумента, для методов material по написанию стилей, например:

/src/components
App.js


import React from 'react';
import { ThemeProvider } from "@material-ui/core/styles";

import  ThemedComponent from './ThemedComponent/ThemedComponent';
import theme from './theme';

function App() {
  return (
        <ThemeProvider theme={theme}>
          < ThemedComponent />  
        </ThemeProvider>
  );
}

export default App;

theme.js

// Простой js объект дэфолтных стилей
const theme = {
    button: {
      backgroundColor: "grey",
      border: 0,
      borderRadius: 3,
      boxShadow: "0 3px 5px 2px",
      color: "black",
      height: 48,
      padding: "0 30px"
    }
  };

  export default theme;

/src/components/ThemedComponent
ThemedComponent.js


import React from "react";

import useStyles from "./style";

const ThemedComponent = props => {
    // Получаем функцию для генерации классов
  const classes = useStyles();

  return <button className={classes.button}>ThemedComponent</button>;
};

export default ThemedComponent;

style.js

// Метод принимает функцию с агрументом theme
import { makeStyles } from "@material-ui/core/styles";

const useStyles = makeStyles(theme => {
  return {
    button: { ...theme.button, margin: 10 }
  };
});

export default useStyles;

6. Переопределение material компонентов


В material-ui каждому компоненту уже установлены соответсвующие стили, то есть импорт любого material компонента предоставит уже стилизованный компонент с имеющимися классами. Создание theme посредством специального api material — createMuiTheme можно не только предоставить theme, но и переопределять заданные дефолтные классы material компонентов посредством специального свойства overrides, например:

/src/components
App.js


import React from 'react';
import { ThemeProvider } from "@material-ui/core/styles";

import CreatedThemeComponent from './CreatedThemeComponent/CreatedThemeComponent';
import createdTheme from './createdTheme';

function App() {
  return (
        <ThemeProvider theme={createdTheme}>
          <CreatedThemeComponent />  
        </ThemeProvider>
  );
}

export default App;

/src/components
createdTheme.js


// Импортируем метод с возможностью переопределения стилей заданных классов компонентов material по умолчанию
import { createMuiTheme } from "@material-ui/core/styles";

const createdTheme = createMuiTheme({
    // Переопределяющее свойство
    overrides: {
      MuiButton: {
        root: {
          color: "red",
          border: "1px solid grey",
          margin: 10
        }
      }
    }
  });
  
export default createdTheme;

/src/components/CreatedThemeComponent
CreatedThemeComponent.js


import React from "react";
import { Button } from "@material-ui/core";

const CreatedThemeComponent = props => {
  return <Button>CreatedThemeComponent</Button>;
};

export default CreatedThemeComponent;

Итоги:

  • JSS и его особенности;
  • JSS стилизация react, material компонентов за счет api material-ui;

Исходный код: https://gitlab.com/ImaGadzhiev/material-style-components