.ts
TypeScript
(application/typescript)
import styled, { css, CSSProperties, StyledComponent } from "styled-components";

type GridCommonTypes = {
  /**
   * If set, will flex: 1.
   * Takes precedence over `flex`.
   */
  fluid?: boolean;
  flex?: CSSProperties["flex"];
  gap?: CSSProperties["gap"];
  alignItems?: CSSProperties["alignItems"];
  justifyContent?: CSSProperties["justifyContent"];
  nowrap?: boolean;
};

type GridTypes = {
  Row: StyledComponent<"div", object, GridCommonTypes, never>;
  Col: StyledComponent<"div", object, GridCommonTypes, never>;
};

const gridCommonCss = css<GridCommonTypes>`
  display: flex;
  justify-content: ${({ justifyContent }) => justifyContent || "flex-start"};
  align-items: ${({ alignItems }) => alignItems || "flex-start"};

  width: 100%;

  flex: ${({ flex, fluid }) => (fluid ? 1 : flex || 0)};
  gap: ${({ gap }) =>
    gap != null ? (typeof gap === "number" ? `${gap}px` : gap) : "auto"};
`;

export const Grid: GridTypes = {
  Row: styled.div<GridCommonTypes>`
    ${gridCommonCss};
    flex-flow: row ${({ nowrap }) => (nowrap ? "nowrap" : "wrap")};
  `,
  Col: styled.div<GridCommonTypes>`
    ${gridCommonCss};
    flex-flow: column ${({ nowrap }) => (nowrap ? "nowrap" : "wrap")};
  `,
};