Skip to content

Instantly share code, notes, and snippets.

@CoralSilver
Last active November 21, 2022 20:26
Show Gist options
  • Save CoralSilver/5404568bdaa358e7a1f458db39220d76 to your computer and use it in GitHub Desktop.
Save CoralSilver/5404568bdaa358e7a1f458db39220d76 to your computer and use it in GitHub Desktop.
React Typography Component
:root {
--font-size-h1: calc((48 / var(--font-unit)) * 1rem);
--font-size-h2: calc((38 / var(--font-unit)) * 1rem);
--font-size-h3: calc((32 / var(--font-unit)) * 1rem);
--font-size-h4: calc((26 / var(--font-unit)) * 1rem);
--font-size-h5: calc((22 / var(--font-unit)) * 1rem);
--font-size-h6: calc((18 / var(--font-unit)) * 1rem);
--font-size-h1-min: calc((26 / var(--font-unit)) * 1rem);
--font-size-h2-min: calc((22 / var(--font-unit)) * 1rem);
--font-size-h3-min: calc((18 / var(--font-unit)) * 1rem);
--font-size-h4-min: calc((16 / var(--font-unit)) * 1rem);
--font-size-h5-min: calc((16 / var(--font-unit)) * 1rem);
--font-size-h6-min: calc((13 / var(--font-unit)) * 1rem);
--typography-breakpoint-range: var(--phone) var(--desktop);
}
import { themr } from 'react-css-themr';
import { TYPOGRAPHY } from '../identifiers';
import { typographyFactory } from './Typography';
import { Icon } from '../icon';
import theme from './theme.css';
const Typography = typographyFactory(Icon);
const ThemedTypography = themr(TYPOGRAPHY, theme)(Typography);
export default ThemedTypography;
export { ThemedTypography as Typography };
@import '../colors.css';
@import '../variables.css';
@import './config.css';
.typography {
@apply --reset;
margin: 0;
& > svg {
margin-right: var(--x-small-spacing);
}
}
.bodyText {
color: var(--color-text);
font-size: var(--font-size-normal);
line-height: var(--line-height-normal);
}
.paragraph {
margin-bottom: var(--font-margin-bottom);
&.noMargin {
margin-bottom: 0;
}
}
.heading {
color: var(--color-heading);
font-weight: var(--font-weight-bold);
letter-spacing: var(--letter-spacing-heading);
line-height: var(--line-height-heading);
margin-bottom: var(--heading-margin-bottom);
&.noMargin {
margin-bottom: 0;
}
}
.h1 {
/* viewport widths between which font-size is fluid */
font-range: var(--typography-breakpoint-range); /* stylelint-disable-line property-no-unknown */
font-size: responsive var(--font-size-h1-min) var(--font-size-h1); /* min-size, max-size */
}
.h2 {
font-range: var(--typography-breakpoint-range); /* stylelint-disable-line property-no-unknown */
font-size: responsive var(--font-size-h2-min) var(--font-size-h2);
}
.h3 {
font-range: var(--typography-breakpoint-range); /* stylelint-disable-line property-no-unknown */
font-size: responsive var(--font-size-h3-min) var(--font-size-h3);
}
.h4 {
font-range: var(--typography-breakpoint-range); /* stylelint-disable-line property-no-unknown */
font-size: responsive var(--font-size-h4-min) var(--font-size-h4);
}
.h5 {
font-range: var(--typography-breakpoint-range); /* stylelint-disable-line property-no-unknown */
font-size: responsive var(--font-size-h5-min) var(--font-size-h5);
}
.h6 {
font-range: var(--typography-breakpoint-range); /* stylelint-disable-line property-no-unknown */
font-size: responsive var(--font-size-h6-min) var(--font-size-h6);
}
.small {
font-size: var(--font-size-small);
}
.left {
text-align: left;
}
.center {
text-align: center;
}
.right {
text-align: right;
}
.italic {
font-style: italic;
}
.semibold {
font-weight: var(--font-weight-semi-bold);
}
.iconInlineFlex {
align-items: center;
display: inline-flex;
}
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { TYPOGRAPHY } from '../identifiers';
import { createIcon } from '../icon';
const factory = () => {
const Typography = ({
align,
children,
className,
headingSize,
icon,
italic,
noMargin,
semibold,
small,
tag,
theme,
...others
}) => {
const headingTags =
tag === 'h1' ||
tag === 'h2' ||
tag === 'h3' ||
tag === 'h4' ||
tag === 'h5' ||
tag === 'h6';
const inlineTags =
tag === 'span' || tag === 'small' || tag === 'em' || tag === 'strong';
const _className = classnames(
theme.typography,
{
// only set text alignment of block level elements
[theme[align]]: align && (headingTags || tag === 'p'),
[theme.semibold]: semibold || tag === 'strong',
[theme.italic]: italic || tag === 'em',
[theme.small]: small || tag === 'small',
[theme.bodyText]:
tag === 'p' || tag === 'span' || tag === 'em' || tag === 'strong',
[theme[headingSize]]: headingSize,
// if no headingSize override, set heading to default size for tag
[theme[tag]]: !headingSize && headingTags,
[theme.heading]: headingTags,
[theme.paragraph]: tag === 'p',
[theme.noMargin]: noMargin,
[theme.iconInlineFlex]: icon && inlineTags,
},
className,
);
const iconProps = { className: theme.icon, size: 'x-small' };
const Component = tag;
return (
<Component
data-react-toolbox="typography"
className={_className}
{...others}
>
{inlineTags && createIcon(icon, iconProps)}
{children}
</Component>
);
};
Typography.propTypes = {
align: PropTypes.oneOf(['left', 'right', 'center']),
children: PropTypes.node,
className: PropTypes.string,
headingSize: PropTypes.oneOf(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']),
icon: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
italic: PropTypes.bool,
noMargin: PropTypes.bool,
semibold: PropTypes.bool,
small: PropTypes.bool,
tag: PropTypes.oneOf([
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'p',
'span',
'small',
'em',
'strong',
]),
theme: PropTypes.shape({
bodyText: PropTypes.string,
paragraph: PropTypes.string,
heading: PropTypes.string,
}),
};
Typography.defaultProps = {
align: null,
className: '',
headingSize: null,
italic: false,
noMargin: false,
semibold: false,
small: false,
tag: 'p',
};
return Typography;
};
const Typography = factory();
export default themr(TYPOGRAPHY)(Typography);
export { factory as typographyFactory };
export { Typography };

Typography

The Typography component can be used to render most html text elements.

import Typography from 'react-toolbox/lib/typography';

const TypographyTest = () => (
  <div>
    <Typography tag="h1">Heading Level 1</Typography>   
    <Typography tag="p">
      Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
      commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus
      et magnis dis parturient montes, nascetur ridiculus mus. Donec quam
      felis, ultricies nec, pellentesque eu, pretium quis, sem
    </Typography>
    <Typography tag="span">This is a normal span.</Typography>
  </div>
);

If you want to provide a theme via context, the component key is RTTypography.

Properties

You can add as many properties as you want to be directly transferred to the output typography element. Apart from them you have the following properties:

Name Type Default Description
align String '' One of either left, right, center, or an empty string.
className String '' Sets a custom class name to add styles to the link.
semibold Boolean false Sets the font weight to semibold.
headingSize String '' One of 'h1', 'h2', 'h3', 'h4', 'h5' or an empty string. Can be used to override the default heading size.
italic Boolean false Sets the font style to italic.
noMargin Boolean false Can be used on block level elements remove the bottom margin.
tag String p One of 'h1','h2','h3','h4','h5','p','span','small','em','strong'. Sets the rendered html tag of the component.
small Boolean false Sets the font size to theme's tiny font size.

Theme

Name Description
bodyText Sets the base styles of all non-heading text elements.
paragraph Sets the styles of paragraphs.
heading Sets the base styles for all headings.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment