typography.ts
May 6, 2021•564 words
/**
* Typography.ts
* This file defines all text styles for use throughout the application
*/
import {
textSizes as bodySizes,
headingSizes,
lineHeights,
letterSpacing,
} from '@/styles/Sizes';
import Colors from '@/styles/Colors';
/**
* Reset the font styles to avoid unexpected styles on some browsers
* And adds base font styles, that are applied globally to all app text
*/
export const TextReset = `
font-family: "aktiv-grotesk", Helvetica, Arial, sans-serif;
font-weight: 400;
font-style: normal;
font-stretch: normal;
line-height: normal;
letter-spacing: 0.38px;
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
`;
/**
* Types relating to typography
*/
export type Alignment = 'left' | 'center' | 'right';
export type BodyTag = 'p' | 'span' | 'div' | 'li' | 'a';
export type HeadingTag = 'h1' | 'h2' | 'h3' | 'h4' | 'p';
export type BodyStyle = 'small' | 'medium' | 'tab' | 'subHeader';
export type HeadingSize = 'small' | 'medium' | 'large';
/**
* Builds text sizes and spacings, based on specified theme/ style
* @param style
*/
export const getTextSize = (style: BodyStyle = 'medium') =>
({
small: `font-size: ${bodySizes.small}`,
medium: `font-size: ${bodySizes.medium};
line-height: ${lineHeights.medium};`,
tab: `font-size: ${bodySizes.small};
letter-spacing: ${letterSpacing.small}`,
subHeader: `font-size: ${bodySizes.small};
line-height: ${lineHeights.large};
letter-spacing: ${letterSpacing.small};`,
}[style]);
/**
* Styles used for body Text (p, a, li, label etc)
* @param style
* @param color
* @param align
*/
export const getBodyStyles = (
style: BodyStyle = 'medium',
color: Colors = Colors.darkGrey,
align: Alignment = 'left',
inline: boolean = false,
) => `
${TextReset}
${getTextSize(style)};
color: ${color || 'inherit'};
text-align: ${align || 'inherit'};
display: ${inline ? 'inline' : 'block'};
`;
/**
* Styled for Heading (h1, h2, h3, h4)
* @param color
* @param align
* @param size
* @param inline
*/
export const getHeadingStyles = (
size: HeadingSize,
color: Colors,
align: Alignment,
inline: boolean,
) => `
${TextReset}
text-align: ${align || 'inherit'};
color: ${color || 'inherit'};
font-size: ${headingSizes[size || 'medium']};
display: ${inline ? 'inline' : 'block'};
`;
// Text.ts
import styled from 'styled-components';
import { getBodyStyles, BodyStyle, Alignment } from '@/styles/Typography';
import Colors from '@/styles/Colors';
/**
* Text: Component used for all application body text
*/
export const Text = styled.span.attrs((props: TextProps) => ({
...(props.attrs || {}),
as: props.as,
}))<TextProps>`
${props => {
const { size, color, align, inline } = props;
return getBodyStyles(size, color, align, inline);
}}
`;
export interface TextProps {
as?: 'p' | 'span' | 'div' | 'li' | 'a'; // Element tag
size?: BodyStyle; // small, medium, tab, subHeader
align?: Alignment; // text-align property
color?: Colors; // font-color, must come from Color pallet
inline?: boolean; // Should display inline?
attrs?: object; // Optional HTML attributes
}
export default Text;
// Heading.tsx
import styled from 'styled-components';
import Colors from '@/styles/Colors';
import { getHeadingStyles, HeadingSize, Alignment } from '@/styles/Typography';
/**
* Component used for all instances of heading text (e.g. title, sub-title)
* All props are optional. The tag type should be correct (specify with the `as` prop)
* Additional styles can be applied by extending Heading with Styled-Components
*/
export interface HeadingProps {
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'p';
align?: Alignment;
color?: Colors;
size?: HeadingSize;
inline?: boolean;
}
export const Heading = styled.h1.attrs((props: HeadingProps) => props.as)<HeadingProps>`
${props => {
const { align, color, size, inline } = props;
return getHeadingStyles(
size || 'medium',
color || Colors.darkGrey,
align || 'left',
inline || true,
);
}}
`;
Heading.defaultProps = {
as: 'h1',
};
export default Heading;