Skip to content

Instantly share code, notes, and snippets.

@AlexFrazer
Last active February 9, 2020 20:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlexFrazer/60687d37515625b962c29ae09b5e72e5 to your computer and use it in GitHub Desktop.
Save AlexFrazer/60687d37515625b962c29ae09b5e72e5 to your computer and use it in GitHub Desktop.
A basic button component
import styled from "@emotion/styled";
import { shouldForwardProp } from "@styled-system/should-forward-prop";
import {
background,
border,
color,
flexbox,
grid,
layout,
position,
shadow,
space,
typography,
compose,
BackgroundProps,
BorderProps,
ColorProps,
FlexboxProps,
GridProps,
LayoutProps,
PositionProps,
ShadowProps,
SpaceProps,
TypographyProps,
} from "styled-system";
type Props = BackgroundProps &
BorderProps &
ColorProps &
FlexboxProps &
GridProps &
LayoutProps &
PositionProps &
ShadowProps &
SpaceProps &
TypographyProps &
export const systemProps = compose(
layout,
color,
space,
background,
border,
grid,
position,
shadow,
typography,
flexbox,
extraConfig,
);
const Box = styled<'div', Props>("div", { shouldForwardProp })(systemProps);
Box.displayName = "Box";
export default Box;
/** @jsx jsx */
import styled from '@emotion/styled';
import css from '@styled-system/css';
import { variant } from 'styled-system';
import Box from '../Box';
interface Props {
/**
* Button Size
* @default 'md'
*/
readonly size?: 'lg' | 'md' | 'sm';
/**
* Different "types" of buttons
* - `solid` - default button type with a solid background and white text
* - `outline` - border but transparent background
* - `link` - appears similar to a link element
* - `ghost` - shows only text
* @default 'solid'
*/
readonly variant?: 'ghost' | 'outline' | 'solid' | 'link';
/**
* color to apply to the variant
*/
readonly variantColor?: string;
}
/**
* Basic button component
* Composes `Box`, which utlizes styled-system
*/
const Button = styled(Box.withComponent('button'))<Props>(
css({
borderWidth: '2px',
borderStyle: 'solid',
display: "inline-flex",
appearance: "none",
alignItems: "center",
justifyContent: "center",
transition: "all 250ms",
userSelect: "none",
position: "relative",
whiteSpace: "nowrap",
verticalAlign: "middle",
lineHeight: "1.2",
outline: "none",
'&:disabled': {
opacity: 0.4,
}
}),
variant({
prop: 'size',
variants: {
lg: {
height: 12,
minWidth: 12,
fontSize: "lg",
px: 6,
},
md: {
height: 10,
minWidth: 10,
fontSize: "md",
px: 4,
},
sm: {
height: 8,
minWidth: 8,
fontSize: "sm",
px: 3,
}
},
}),
({ variantColor = 'primary' }) => variant({
prop: 'variant',
variants: {
ghost: {
borderColor: 'transparent',
backgroundColor: 'transparent',
color: variantColor,
},
solid: {
borderColor: variantColor,
backgroundColor: variantColor,
color: 'white',
},
outline: {
borderColor: variantColor,
color: variantColor,
backgroundColor: 'transparent',
},
link: {
textDecoration: 'underline',
borderColor: 'transparent',
backgroundColor: 'transparent',
color: variantColor,
}
}
}),
);
Button.defaultProps = {
size: 'md',
variant: 'solid',
variantColor: 'primary',
};
Button.displayName = 'Button';
export default Button;
import React from 'react';
import Button from '@my-lib/ui';
function SomeForm() {
return (
<footer>
<Button type="reset" variant="link" variantColor="secondary">Clear</Button>
<Button type="submit">Submit</Button>
</footer>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment