Создание отзывчивого стилизованного компонента сушки - PullRequest
1 голос
/ 24 сентября 2019

У меня есть следующий код, чтобы помочь мне с адаптивным дизайном в Styled Components:

const breakpoints = {
  tablet: "769px",
  desktop: "1024px",
  widescreen: "1216px",
  fullhd: "1408px"
};

const gridCSS = ({ bg, color }) => css`
  background-color: ${bg};
  color: ${color};
`;

const responsiveGrid = (key, prop) =>
  prop &&
  css`
    @media screen and (min-width: ${breakpoints[key]}) {
      color: ${prop.color};
      background-color: ${prop.bg};
    }
  `;

const Grid = styled.div(
  ({ color, bg, desktop, tablet }) => css`
  display: grid;
  justify-content: center;
  align-content: center;
  min-height: 100vh;
  ${responsiveGrid("tablet", tablet)}
  ${responsiveGrid("desktop", desktop)}
  ${gridCSS}
`
);

function App() {
  return (
    <Grid
      color="orange"
      bg="lightgreen"
      tablet={{
        color: "green",
        bg: "orange"
      }}
      desktop={{
        color: "yellow",
        bg: "purple"
      }}
    >
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
    </Grid>
  );
}

Теперь это работает так, как я хочу.Цвет текста и фона меняется в зависимости от размера экрана.

Однако я хотел бы отметить определенную повторяемость в коде:

Например, функция gridCSS содержит точно такие же свойства css и имена реквизитов, что и функция responsiveGrid.Оба имеют свойство color и background-color, и оба ссылаются на реквизиты color и bg.

Но, если я попытаюсь вставить gridCSS в `respiveGrid, он не будет работать.Другими словами, это работает:

const responsiveGrid = (key, {bg, color}) =>
  (color || bg) &&
  css`
    @media screen and (min-width: ${breakpoints[key]}) {
      color: ${color};
      background-color: ${bg};
    }
  `;

Но это работает не работа:

const responsiveGrid = (key, {bg, color}) =>
  (color || bg) &&
  css`
    @media screen and (min-width: ${breakpoints[key]}) {
      ${gridCSS}
    }
  `;

Итак, я хочу знать, есть ли или нетспособ иметь одно центральное расположение для имен свойств css и их соответствующих реквизитов без необходимости писать его дважды (один раз в функции gridCSS и второй раз в функции responsiveGrid.

Обратите внимание, чтоКонечный результат, который я ищу, следующий:

function App() {
  return (
    <Grid
      color="orange"
      bg="lightgreen"
      tablet={{
        color: "green",
        bg: "orange"
      }}
      desktop={{
        color: "yellow",
        bg: "purple"
      }}
    >
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
    </Grid>
  );
}

, с помощью которого я могу установить color или bg реквизит без каких-либо медиа-запросов, а также установить те же реквизиты в медиа-запросе, например, tablet или desktop.

Есть идеи?

Спасибо.

PS Если это полезно, вот коды и поле длявышеуказанный код: https://codesandbox.io/s/vigorous-brook-ughkv?fontsize=14

1 Ответ

0 голосов
/ 24 сентября 2019

Вот решение, которое я придумал:

const breakpoints = {
  tablet: {
    value: 769,
    unit: "px"
  },
  desktop: {
    value: 1024,
    unit: "px"
  },
  widescreen: {
    value: 1216,
    unit: "px"
  },
  fullhd: {
    value: 1408,
    unit: "px"
  }
};

const breakpointKeys = Object.keys(breakpoints);

const gridCSS = ({ bg, textColor, ...props }) => {
  let mediaQueryCSS = breakpointKeys.map(key => {
    let mediaQuery = breakpoints[key].value + breakpoints[key].unit;
    let newMQ = mediaQuery - 1
    console.log(newMQ)

    return css`
      @media screen and (min-width: ${mediaQuery}) {
        color: ${props[key] && props[key].textColor};
        background-color: ${props[key] && props[key].bg};
      }
    `;
  });

  return css`
    background-color: ${bg};
    color: ${textColor};
    ${mediaQueryCSS};
  `;
};

const Grid = styled.div(
  ({ color, bg, desktop, tablet }) => css`
    display: grid;
    justify-content: center;
    align-content: center;
    min-height: 100vh;
    ${gridCSS}
  `
);

function App() {
  return (
    <Grid
      textColor="orange"
      bg="lightgreen"
      tablet={{
        textColor: "green",
        bg: "orange"
      }}
      desktop={{
        textColor: "yellow",
        bg: "purple"
      }}
    >
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
    </Grid>
  );
}
...