-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement core atom HTML element component
Heading
This commit implements the core atom(s) `H1`-`H6` which represent the content sectioning (1) HTML element `<h1>`-`<h6>` (2). It uses custom styles instead of browser defaults and allows to disable the bottom margin via the `noMargin` prop. The font styles like size, modular scale and family adhere to the "Typography" design concept (3). References: (1) https://developer.mozilla.org/en-US/docs/Web/HTML/Element#Content_sectioning (2) https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements (3) #2 Associated epics: GH-69, GH-2 GH-81
- Loading branch information
1 parent
ad995b0
commit 0d629ca
Showing
9 changed files
with
373 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
src/components/atoms/core/HTMLElements/sectioning/Heading.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
/** | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements | ||
* @since 0.3.0 | ||
*/ | ||
|
||
import PropTypes from "prop-types"; | ||
import styled, { css } from "styled-components"; | ||
|
||
import { ms } from "styles/theme"; | ||
|
||
const baseHeadingStyles = css` | ||
margin-top: 0; | ||
margin-bottom: ${({ noMargin }) => (noMargin ? 0 : "0.5rem")}; | ||
font-weight: 500; | ||
`; | ||
|
||
/** | ||
* A base HTML component that represents a level 1 section heading. | ||
*/ | ||
const H1 = styled.h1` | ||
${baseHeadingStyles}; | ||
font-size: ${ms(6)}; | ||
`; | ||
|
||
/** | ||
* A base HTML component that represents a level 2 section heading. | ||
*/ | ||
const H2 = styled.h2` | ||
${baseHeadingStyles}; | ||
font-size: ${ms(5)}; | ||
`; | ||
|
||
/** | ||
* A base HTML component that represents a level 3 section heading. | ||
*/ | ||
const H3 = styled.h3` | ||
${baseHeadingStyles}; | ||
font-size: ${ms(4)}; | ||
`; | ||
|
||
/** | ||
* A base HTML component that represents a level 4 section heading. | ||
*/ | ||
const H4 = styled.h4` | ||
${baseHeadingStyles}; | ||
font-size: ${ms(3)}; | ||
`; | ||
|
||
/** | ||
* A base HTML component that represents a level 5 section heading. | ||
*/ | ||
const H5 = styled.h5` | ||
${baseHeadingStyles}; | ||
font-size: ${ms(2)}; | ||
`; | ||
|
||
/** | ||
* A base HTML component that represents a level 6 section heading. | ||
*/ | ||
const H6 = styled.h6` | ||
${baseHeadingStyles}; | ||
font-size: ${ms(1)}; | ||
`; | ||
|
||
const propTypes = { | ||
hasBottomMargin: PropTypes.bool | ||
}; | ||
|
||
const defaultProps = { | ||
hasBottomMargin: false | ||
}; | ||
|
||
H1.propTypes = propTypes; | ||
H1.defaultProps = defaultProps; | ||
|
||
H2.propTypes = propTypes; | ||
H2.defaultProps = defaultProps; | ||
|
||
H3.propTypes = propTypes; | ||
H3.defaultProps = defaultProps; | ||
|
||
H4.propTypes = propTypes; | ||
H4.defaultProps = defaultProps; | ||
|
||
H5.propTypes = propTypes; | ||
H5.defaultProps = defaultProps; | ||
|
||
H6.propTypes = propTypes; | ||
H6.defaultProps = defaultProps; | ||
|
||
export { H1, H2, H3, H4, H5, H6 }; |
20 changes: 20 additions & 0 deletions
20
src/components/atoms/core/HTMLElements/sectioning/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
/** | ||
* @file Provides components that represent basic HTML elements with content sectioning functionality. | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element#Content_sectioning | ||
* @since 0.3.0 | ||
*/ | ||
|
||
import { H1, H2, H3, H4, H5, H6 } from "./Heading"; | ||
|
||
export { H1, H2, H3, H4, H5, H6 }; |
File renamed without changes.
File renamed without changes.
93 changes: 93 additions & 0 deletions
93
test/components/atoms/core/HTMLElements/sectioning/Heading.test.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
import React, { Fragment } from "react"; | ||
import { stripUnit } from "polished"; | ||
|
||
import { renderWithTheme } from "nord-docs-test-utils"; | ||
import { H1, H2, H3, H4, H5, H6 } from "atoms/core/HTMLElements"; | ||
|
||
describe("theme styles", () => { | ||
test("matches the snapshot", () => { | ||
const { container } = renderWithTheme( | ||
<Fragment> | ||
<H1>Heading Level 1</H1> | ||
<H2>Heading Level 2</H2> | ||
<H3>Heading Level 3</H3> | ||
<H4>Heading Level 4</H4> | ||
<H5>Heading Level 5</H5> | ||
<H6>Heading Level 6</H6> | ||
</Fragment> | ||
); | ||
expect(container).toMatchSnapshot(); | ||
}); | ||
|
||
test("matches the snapshot with adjusted margin", () => { | ||
const { container } = renderWithTheme( | ||
<Fragment> | ||
<H1 noMargin>Heading Level 1</H1> | ||
<H2 noMargin>Heading Level 2</H2> | ||
<H3 noMargin>Heading Level 3</H3> | ||
<H4 noMargin>Heading Level 4</H4> | ||
<H5 noMargin>Heading Level 5</H5> | ||
<H6 noMargin>Heading Level 6</H6> | ||
</Fragment> | ||
); | ||
expect(container).toMatchSnapshot(); | ||
}); | ||
|
||
test("has explicit font size definitions", () => { | ||
const { container } = renderWithTheme( | ||
<Fragment> | ||
<H1 noMargin>Heading Level 1</H1> | ||
<H2 noMargin>Heading Level 2</H2> | ||
<H3 noMargin>Heading Level 3</H3> | ||
<H4 noMargin>Heading Level 4</H4> | ||
<H5 noMargin>Heading Level 5</H5> | ||
<H6 noMargin>Heading Level 6</H6> | ||
</Fragment> | ||
); | ||
expect( | ||
Object.values(container.children) | ||
.map(headingElement => getComputedStyle(headingElement).fontSize) | ||
.filter(Boolean).length | ||
).toEqual(container.children.length); | ||
}); | ||
|
||
test("has no top margin", () => { | ||
const { container } = renderWithTheme(<H1>Nord</H1>); | ||
expect(container.firstChild).toHaveStyleRule("margin-top", "0"); | ||
}); | ||
|
||
test("adjusts bottom margin based on passed props", () => { | ||
const { container } = renderWithTheme(<H1 noMargin>Nord</H1>); | ||
expect(container.firstChild).toHaveStyleRule("margin-bottom", "0"); | ||
}); | ||
|
||
test("Ensure descending font sizes between all heading levels", () => { | ||
const { container } = renderWithTheme( | ||
<Fragment> | ||
<H1 noMargin>Heading Level 1</H1> | ||
<H2 noMargin>Heading Level 2</H2> | ||
<H3 noMargin>Heading Level 3</H3> | ||
<H4 noMargin>Heading Level 4</H4> | ||
<H5 noMargin>Heading Level 5</H5> | ||
<H6 noMargin>Heading Level 6</H6> | ||
</Fragment> | ||
); | ||
|
||
expect( | ||
/* Get the font sizes as numbers of all heading components in rendered order. */ | ||
Object.values(container.children) | ||
.map(headingElement => stripUnit(getComputedStyle(headingElement).fontSize)) | ||
/* Ensure descending font sizes by comparing a higher level heading with the next lower one. */ | ||
.reduce((acc, cur) => (acc > cur ? cur : 0)) | ||
).toBeGreaterThan(0); | ||
}); | ||
}); |
155 changes: 155 additions & 0 deletions
155
test/components/atoms/core/HTMLElements/sectioning/__snapshots__/Heading.test.jsx.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`theme styles matches the snapshot 1`] = ` | ||
.c0 { | ||
margin-top: 0; | ||
margin-bottom: 0.5rem; | ||
font-weight: 500; | ||
font-size: 2.0272865295410156em; | ||
} | ||
.c1 { | ||
margin-top: 0; | ||
margin-bottom: 0.5rem; | ||
font-weight: 500; | ||
font-size: 1.802032470703125em; | ||
} | ||
.c2 { | ||
margin-top: 0; | ||
margin-bottom: 0.5rem; | ||
font-weight: 500; | ||
font-size: 1.601806640625em; | ||
} | ||
.c3 { | ||
margin-top: 0; | ||
margin-bottom: 0.5rem; | ||
font-weight: 500; | ||
font-size: 1.423828125em; | ||
} | ||
.c4 { | ||
margin-top: 0; | ||
margin-bottom: 0.5rem; | ||
font-weight: 500; | ||
font-size: 1.265625em; | ||
} | ||
.c5 { | ||
margin-top: 0; | ||
margin-bottom: 0.5rem; | ||
font-weight: 500; | ||
font-size: 1.125em; | ||
} | ||
<div> | ||
<h1 | ||
class="c0" | ||
> | ||
Heading Level 1 | ||
</h1> | ||
<h2 | ||
class="c1" | ||
> | ||
Heading Level 2 | ||
</h2> | ||
<h3 | ||
class="c2" | ||
> | ||
Heading Level 3 | ||
</h3> | ||
<h4 | ||
class="c3" | ||
> | ||
Heading Level 4 | ||
</h4> | ||
<h5 | ||
class="c4" | ||
> | ||
Heading Level 5 | ||
</h5> | ||
<h6 | ||
class="c5" | ||
> | ||
Heading Level 6 | ||
</h6> | ||
</div> | ||
`; | ||
|
||
exports[`theme styles matches the snapshot with adjusted margin 1`] = ` | ||
.c0 { | ||
margin-top: 0; | ||
margin-bottom: 0; | ||
font-weight: 500; | ||
font-size: 2.0272865295410156em; | ||
} | ||
.c1 { | ||
margin-top: 0; | ||
margin-bottom: 0; | ||
font-weight: 500; | ||
font-size: 1.802032470703125em; | ||
} | ||
.c2 { | ||
margin-top: 0; | ||
margin-bottom: 0; | ||
font-weight: 500; | ||
font-size: 1.601806640625em; | ||
} | ||
.c3 { | ||
margin-top: 0; | ||
margin-bottom: 0; | ||
font-weight: 500; | ||
font-size: 1.423828125em; | ||
} | ||
.c4 { | ||
margin-top: 0; | ||
margin-bottom: 0; | ||
font-weight: 500; | ||
font-size: 1.265625em; | ||
} | ||
.c5 { | ||
margin-top: 0; | ||
margin-bottom: 0; | ||
font-weight: 500; | ||
font-size: 1.125em; | ||
} | ||
<div> | ||
<h1 | ||
class="c0" | ||
> | ||
Heading Level 1 | ||
</h1> | ||
<h2 | ||
class="c1" | ||
> | ||
Heading Level 2 | ||
</h2> | ||
<h3 | ||
class="c2" | ||
> | ||
Heading Level 3 | ||
</h3> | ||
<h4 | ||
class="c3" | ||
> | ||
Heading Level 4 | ||
</h4> | ||
<h5 | ||
class="c4" | ||
> | ||
Heading Level 5 | ||
</h5> | ||
<h6 | ||
class="c5" | ||
> | ||
Heading Level 6 | ||
</h6> | ||
</div> | ||
`; |
File renamed without changes.
File renamed without changes.