Skip to content

Instantly share code, notes, and snippets.

@mscolnick
Created November 20, 2020 16:19
Show Gist options
  • Save mscolnick/eae216a0e926f2315e6e2c7b29fc8cf9 to your computer and use it in GitHub Desktop.
Save mscolnick/eae216a0e926f2315e6e2c7b29fc8cf9 to your computer and use it in GitHub Desktop.
styled-utils
const SectionedListWrapper = styled.div<{ clickable?: boolean; bordered?: boolean }>`
display: flex;
flex-direction: column;
${padding.b('$8')}
${cond.if(
'clickable',
css`
> *:not(:first-child):hover {
cursor: pointer;
${borderRadius('default')}
${boxShadow('default')}
${margin.x('-10px')}
${padding.x('10px')}
${color.bg('white')}
${color.border('transparent')}
}
`
)}
${cond.if(
'bordered',
css`
> *:not(:first-child) {
${padding.y('$6')}
${border.top()}
}
`,
css`
> *:not(:first-child) {
${padding.y('$2')}
}
> *:nth-child(2) {
${border.top()}
}
`
)}
`;
import { css } from 'styled-components';
import { ThemeColor } from './colors';
import { Radii } from './radii';
import { Shadow } from './shadows';
import { ThemeSpace, themeSpaces } from './space';
import {
StyledBorderRadiusUtil,
StyledBorderUtil,
StyledBoxShadowFn,
StyledColorUtil,
StyledConditionalUtil,
StyledSpaceUtil,
} from './utilTypes';
export const border: StyledBorderUtil = () => ({ theme }) => css`
border: 1px solid ${theme.colors.divider};
`;
border.top = () => ({ theme }) => css`
border-top: 1px solid ${theme.colors.divider};
`;
border.left = () => ({ theme }) => css`
border-left: 1px solid ${theme.colors.divider};
`;
border.bottom = () => ({ theme }) => css`
border-bottom: 1px solid ${theme.colors.divider};
`;
border.right = () => ({ theme }) => css`
border-right: 1px solid ${theme.colors.divider};
`;
export const color: StyledColorUtil = c => ({ theme }) => css`
color: ${theme.colors[c as ThemeColor] || c};
`;
color.bg = c => ({ theme }) => css`
background-color: ${theme.colors[c as ThemeColor] || c};
`;
color.border = c => ({ theme }) => css`
border-color: ${theme.colors[c as ThemeColor] || c};
`;
export const boxShadow: StyledBoxShadowFn = sh => ({ theme }) => css`
box-shadow: ${theme.shadows[sh as Shadow] || sh};
`;
export const borderRadius: StyledBorderRadiusUtil = r => ({ theme }) => css`
border-radius: ${theme.radii[r as Radii] || r};
`;
export const margin: StyledSpaceUtil = s => () => css`
margin: ${themeSpaces[s as ThemeSpace] || s};
`;
margin.t = s => () => css`
margin-top: ${themeSpaces[s as ThemeSpace] || s};
`;
margin.l = s => () => css`
margin-left: ${themeSpaces[s as ThemeSpace] || s};
`;
margin.b = s => () => css`
margin-bottom: ${themeSpaces[s as ThemeSpace] || s};
`;
margin.r = s => () => css`
margin-right: ${themeSpaces[s as ThemeSpace] || s};
`;
margin.x = s => () => css`
margin-right: ${themeSpaces[s as ThemeSpace] || s};
margin-left: ${themeSpaces[s as ThemeSpace] || s};
`;
margin.y = s => () => css`
margin-top: ${themeSpaces[s as ThemeSpace] || s};
margin-bottom: ${themeSpaces[s as ThemeSpace] || s};
`;
export const padding: StyledSpaceUtil = s => () => css`
padding: ${themeSpaces[s as ThemeSpace] || s};
`;
padding.t = s => () => css`
padding-top: ${themeSpaces[s as ThemeSpace] || s};
`;
padding.l = s => () => css`
padding-left: ${themeSpaces[s as ThemeSpace] || s};
`;
padding.b = s => () => css`
padding-bottom: ${themeSpaces[s as ThemeSpace] || s};
`;
padding.r = s => () => css`
padding-right: ${themeSpaces[s as ThemeSpace] || s};
`;
padding.x = s => () => css`
padding-right: ${themeSpaces[s as ThemeSpace] || s};
padding-left: ${themeSpaces[s as ThemeSpace] || s};
`;
padding.y = s => () => css`
padding-top: ${themeSpaces[s as ThemeSpace] || s};
padding-bottom: ${themeSpaces[s as ThemeSpace] || s};
`;
export const cond: StyledConditionalUtil = {
if: (key, whenTrue, whenFalse) => props => (props[key] ? whenTrue : whenFalse),
};
import { FlattenInterpolation, DefaultTheme, ThemeProps } from 'styled-components';
import { ThemeColor } from './colors';
import { Radii } from './radii';
import { Shadow } from './shadows';
import { ThemeSpace } from './space';
type DefaultThemeProps = ThemeProps<DefaultTheme>;
type CssInput = FlattenInterpolation<DefaultThemeProps> | string;
type CssOutput = FlattenInterpolation<DefaultThemeProps> | string;
type BooleanProperties<T> = { [K in keyof T]: T[K] extends boolean ? T[K] : never };
export type StyledBorderFn = (b?: React.CSSProperties['border']) => (props: DefaultThemeProps) => CssOutput;
export type StyledBorderUtil = StyledBorderFn & {
top: StyledBorderFn;
bottom: StyledBorderFn;
left: StyledBorderFn;
right: StyledBorderFn;
};
export type StyledSpaceFn = (s: ThemeSpace | (string & {})) => (props: DefaultThemeProps) => CssOutput;
export type StyledSpaceUtil = StyledSpaceFn & {
t: StyledSpaceFn;
b: StyledSpaceFn;
l: StyledSpaceFn;
r: StyledSpaceFn;
x: StyledSpaceFn;
y: StyledSpaceFn;
};
export type StyledColorFn = (s: ThemeColor | (string & {})) => (props: DefaultThemeProps) => CssOutput;
export type StyledColorUtil = StyledColorFn & {
bg: StyledColorFn;
border: StyledColorFn;
};
export type StyledBoxShadowFn = (s: Shadow | (string & {})) => (props: DefaultThemeProps) => CssOutput;
export type StyledBorderRadiusFn = (s: Radii | (string & {})) => (props: DefaultThemeProps) => CssOutput;
export type StyledBorderRadiusUtil = StyledBorderRadiusFn;
export interface StyledConditionalUtil {
if<P extends {}>(
key: keyof BooleanProperties<P>,
whenTrue: CssInput,
whenFalse?: CssInput
): (props: P) => CssOutput | undefined;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment