diff --git a/.storybook/preview.scss b/.storybook/preview.scss
index 64be7cb8..bb303918 100644
--- a/.storybook/preview.scss
+++ b/.storybook/preview.scss
@@ -92,6 +92,10 @@ div.sbdocs-content {
}
}
+.sbdocs.sbdocs-wrapper {
+ padding-top: 1rem;
+}
+
div.reset-article {
width: calc(100% + 30px);
margin-left: -15px;
diff --git a/bin/css-to-js/index.js b/bin/css-to-js/index.js
new file mode 100644
index 00000000..4b35ce5f
--- /dev/null
+++ b/bin/css-to-js/index.js
@@ -0,0 +1,343 @@
+/*
+ * Reuters Graphics browser port of:
+ * Copyright 2020 American Express Travel Related Services Company, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+import css from 'css';
+
+function _defineProperty(obj, key, value) {
+ if (key in obj) {
+ Object.defineProperty(obj, key, {
+ value,
+ enumerable: true,
+ configurable: true,
+ writable: true,
+ });
+ } else {
+ obj[key] = value;
+ }
+
+ return obj;
+}
+
+function ownKeys(object, enumerableOnly) {
+ const keys = Object.keys(object);
+
+ if (Object.getOwnPropertySymbols) {
+ let symbols = Object.getOwnPropertySymbols(object);
+ if (enumerableOnly) {
+ symbols = symbols.filter(function(sym) {
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+ });
+ }
+ keys.push.apply(keys, symbols);
+ }
+
+ return keys;
+}
+
+function _objectSpread2(target) {
+ for (let i = 1; i < arguments.length; i++) {
+ var source = arguments[i] != null ? arguments[i] : {};
+
+ if (i % 2) {
+ ownKeys(Object(source), true).forEach(function(key) {
+ _defineProperty(target, key, source[key]);
+ });
+ } else if (Object.getOwnPropertyDescriptors) {
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
+ } else {
+ ownKeys(Object(source)).forEach(function(key) {
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
+ });
+ }
+ }
+
+ return target;
+}
+
+function _slicedToArray(arr, i) {
+ return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
+}
+
+function _arrayWithHoles(arr) {
+ if (Array.isArray(arr)) return arr;
+}
+
+function _iterableToArrayLimit(arr, i) {
+ if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === '[object Arguments]')) {
+ return;
+ }
+
+ const _arr = [];
+ let _n = true;
+ let _d = false;
+ let _e;
+
+ try {
+ for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
+ _arr.push(_s.value);
+
+ if (i && _arr.length === i) break;
+ }
+ } catch (err) {
+ _d = true;
+ _e = err;
+ } finally {
+ try {
+ if (!_n && _i.return != null) _i.return();
+ } finally {
+ if (_d) throw _e;
+ }
+ }
+
+ return _arr;
+}
+
+function _nonIterableRest() {
+ throw new TypeError('Invalid attempt to destructure non-iterable instance');
+}
+
+const addProperty = function addProperty(obj, key, value) {
+ const retObj = obj;
+
+ if (retObj[key]) {
+ retObj[key] = _objectSpread2({}, retObj[key], {}, value);
+ } else {
+ retObj[key] = value;
+ }
+
+ return retObj;
+};
+
+const camelize = function camelize(str) {
+ return str.replace(/-([a-z])/g, function(g) {
+ return g[1].toUpperCase();
+ });
+};
+
+const capitalize = function capitalize(str) {
+ return str.charAt(0).toUpperCase() + str.slice(1);
+};
+
+const sanitize = function sanitize(name) {
+ return name.replace(/\*/g, 'all-children').replace(/#/g, '$').replace(/\s\s+/g, ' ').replace(/[^a-zA-Z0-9$]/g, '_').replace(/^_+/g, '').replace(/_+$/g, '');
+};
+
+const fontface = function fontface(rule, result) {
+ let name = '';
+ let obj = {};
+ const fontObj = {};
+ rule.declarations.forEach(function(declaration) {
+ const cssProperty = camelize(declaration.property);
+ fontObj[cssProperty] = declaration.value;
+ name = capitalize(camelize(fontObj.fontFamily).replace(/"/g, ''));
+ obj = {
+ '@font-face': fontObj,
+ };
+ });
+ let dupeFlag = false;
+ Object.keys(result).forEach(function(key) {
+ if (key.split('_')[0] === name) {
+ if (JSON.stringify(result[key]) === JSON.stringify(obj)) {
+ dupeFlag = true;
+ }
+ }
+ });
+
+ if (!dupeFlag) {
+ const numVar = Object.entries(result).filter(function(resObj) {
+ return resObj[0].split('_')[0] === name;
+ }).length;
+
+ if (numVar > 0) {
+ name = ''.concat(name, '_').concat(numVar + 1);
+ }
+
+ name = sanitize(name);
+ return [name, obj];
+ }
+
+ return false;
+};
+
+const keyframes = function keyframes(rule) {
+ const keyFrameObj = {};
+ rule.keyframes.forEach(function(keyframe) {
+ keyframe.declarations.forEach(function(decl) {
+ keyFrameObj[keyframe.values[0]] = _objectSpread2({}, keyFrameObj[keyframe.values[0]], _defineProperty({}, decl.property, decl.value));
+ });
+ });
+ let name = camelize('keyframes-'.concat(rule.name));
+ const obj = {};
+ obj['@keyframes '.concat(rule.name)] = keyFrameObj;
+ name = sanitize(name);
+ return [name, obj];
+};
+
+const standard = function standard(rule, result) {
+ const obj = {};
+ let retObj = {};
+ rule.declarations.forEach(function(declaration) {
+ const cssProperty = camelize(declaration.property);
+ obj[cssProperty] = declaration.value;
+ });
+ rule.selectors.forEach(function(selector) {
+ let name; // Check if selector contains a pseudo selector
+
+ const pseudoSelectorIndex = selector.indexOf(':');
+
+ if (pseudoSelectorIndex !== -1) {
+ // Find end of pseudo selector
+ let endPseudoSelectorIndex = selector.indexOf(' ', pseudoSelectorIndex);
+ if (endPseudoSelectorIndex === -1) endPseudoSelectorIndex = selector.length; // Split selector
+
+ const primarySelector = selector.slice(0, pseudoSelectorIndex);
+ const pseudoSelector = selector.slice(pseudoSelectorIndex, endPseudoSelectorIndex);
+ const secondarySelector = selector.slice(endPseudoSelectorIndex, selector.length);
+ const pseudoObj = {};
+ pseudoObj['&'.concat(pseudoSelector).concat(secondarySelector)] = obj;
+ name = sanitize(primarySelector.trim());
+ retObj = addProperty(result, name, pseudoObj);
+ } else {
+ name = sanitize(selector.trim());
+ retObj = addProperty(result, name, obj);
+ }
+ });
+ return retObj;
+};
+
+const convertRules = function convertRules(rules) {
+ const res = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ let result = res;
+ rules.forEach(function(rule) {
+ if (rule.type === 'media') {
+ // Convert @media rules
+ const name = '@media '.concat(rule.media);
+ result[name] = result[name] || {};
+ const media = result[name];
+ convertRules(rule.rules, media);
+ } else if (rule.type === 'font-face') {
+ // Convert @font-face rules
+ const fontProp = fontface(rule, result);
+ if (fontProp) result = addProperty(result, fontProp[0], fontProp[1]);
+ } else if (rule.type === 'keyframes') {
+ // Convert @keyframes rules
+ const keyProp = keyframes(rule);
+ result = addProperty(result, keyProp[0], keyProp[1]);
+ } else if (rule.type === 'rule') {
+ // Convert standard CSS rules
+ const standardProp = standard(rule, result);
+ Object.entries(standardProp).forEach(function(_ref) {
+ const _ref2 = _slicedToArray(_ref, 2);
+ const key = _ref2[0];
+ const value = _ref2[1];
+
+ result = addProperty(result, key, value);
+ });
+ }
+ });
+ return result;
+};
+
+const convertToJS = function convertToJS(input) {
+ // Parse CSS string into rules array
+ try {
+ const parsedCss = css.parse(input);
+ const rules = parsedCss.stylesheet.rules;
+ return convertRules(rules);
+ } catch (err) {
+ throw new Error('Invalid CSS input: '.concat(err));
+ }
+};
+
+const reverseMediaQueries = function reverseMediaQueries(inputData) {
+ const exportObject = {};
+
+ const moveMediaInsideClass = function moveMediaInsideClass(object) {
+ const media = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+ Object.entries(object).forEach(function(_ref) {
+ const _ref2 = _slicedToArray(_ref, 2);
+ const key = _ref2[0];
+ const value = _ref2[1];
+
+ if (key.includes('@media')) {
+ moveMediaInsideClass(object[key], key);
+ } else if (media) {
+ const tempObj = {};
+ tempObj[media] = value;
+
+ if (exportObject[key]) {
+ exportObject[key] = _objectSpread2({}, exportObject[key], {}, tempObj);
+ } else {
+ exportObject[key] = tempObj;
+ }
+ } else if (exportObject[key]) {
+ exportObject[key] = _objectSpread2({}, exportObject[key], {}, value);
+ } else {
+ exportObject[key] = value;
+ }
+ });
+ };
+
+ moveMediaInsideClass(inputData);
+ return exportObject;
+};
+
+const convertStringToJson = function convertStringToJson(input, mediaReverse) {
+ let contents = convertToJS(input);
+
+ if (mediaReverse) {
+ contents = reverseMediaQueries(contents);
+ }
+
+ return {
+ contents,
+ };
+};
+
+const convert = function convert(input) {
+ const config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ const outputType = config.outputType;
+ const outputPath = config.outputPath;
+ let mediaReverse = config.mediaReverse;
+ let convertedCss;
+
+ if (outputType === 'splitFile' || outputType === 'shakeFile') {
+ mediaReverse = true;
+ } // If input is a String of CSS
+
+ convertedCss = convertStringToJson(input, mediaReverse);
+
+ if (!outputType) {
+ if (Array.isArray(convertedCss)) {
+ return convertedCss.map(function(obj) {
+ return obj.contents;
+ });
+ } else {
+ return convertedCss.contents;
+ }
+ } else {
+ const writeRecur = function writeRecur(input) {
+ if (Array.isArray(input)) {
+ input.forEach(function(obj) {
+ writeRecur(obj);
+ });
+ }
+ };
+
+ writeRecur(convertedCss);
+ }
+};
+
+export { convert };
diff --git a/package.json b/package.json
index d1bb3680..27114dc8 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
"node": ">=16.19"
},
"devDependencies": {
+ "@americanexpress/css-to-js": "^1.0.1",
"@babel/core": "^7.21.4",
"@babel/eslint-parser": "^7.21.3",
"@babel/eslint-plugin": "^7.19.1",
@@ -51,6 +52,7 @@
"@sveltejs/vite-plugin-svelte": "^2.4.1",
"@tsconfig/svelte": "^4.0.1",
"@types/gtag.js": "^0.0.12",
+ "@types/mdx": "^2.0.5",
"@types/proper-url-join": "^2.1.1",
"@types/react-syntax-highlighter": "^15.5.7",
"@typescript-eslint/eslint-plugin": "^5.59.0",
diff --git a/src/docs/docs-components/CopyTable/Table.jsx b/src/docs/docs-components/CopyTable/Table.jsx
index c0ab43d1..2ff88526 100644
--- a/src/docs/docs-components/CopyTable/Table.jsx
+++ b/src/docs/docs-components/CopyTable/Table.jsx
@@ -1,5 +1,6 @@
import React from 'react';
import { Unstyled } from '@storybook/blocks';
+// @ts-ignore
import classes from './styles.module.scss';
const handleClick = async(props) => {
@@ -22,6 +23,14 @@ const TH = (props) =>
{props.children} | ;
const CopyTable = (props) => {
return (
+
+ {props.title}
+ {(props.title && !props.noLink) && (
+
+ link
+
+ )}
+
diff --git a/src/docs/docs-components/CopyTable/styles.module.scss b/src/docs/docs-components/CopyTable/styles.module.scss
index 2885187d..d5e5c09b 100644
--- a/src/docs/docs-components/CopyTable/styles.module.scss
+++ b/src/docs/docs-components/CopyTable/styles.module.scss
@@ -1,6 +1,24 @@
$copyable: #0071a1;
$header: #5e81ac;
+.title {
+ font-size: 18px;
+ color: #666;
+ margin-bottom: 5px;
+ font-weight: 400;
+ a span {
+ font-size: 18px;
+ line-height: 18px;
+ margin-left: 2px;
+ vertical-align: middle;
+ font-weight: bold;
+ opacity: 0.6;
+ &:hover {
+ opacity: 1;
+ }
+ }
+}
+
.table {
min-height: 100px;
margin: 0 0 3rem;
@@ -8,32 +26,39 @@ $header: #5e81ac;
max-width: 600px;
border-collapse: collapse;
border-radius: 4px;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.25);
overflow: hidden;
th,
td {
- padding: 6px 10px;
+ padding: 6px 13px;
+ font-family: 'Nunito Sans', Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ line-height: 24px;
}
thead tr {
- background-color: #5e81ac;
- color: #ffffff;
+ // background-color: #5e81ac;
+ color: #333;
text-align: left;
th {
- font-weight: 500;
- border-right: 1px solid rgba(255, 255, 255, 0.2);
+ font-weight: bold;
+ color: #2e3438;
+ border: 1px solid hsla(203, 50%, 30%, 0.15);
+ margin: 0;
+
+ border-collapse: collapse;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
}
}
tbody tr {
- border-bottom: 1px solid #dddddd;
+ border: 1px solid hsla(203, 50%, 30%, 0.15);
border-radius: 4px;
- font-family: 'Fira Code', monospace;
- letter-spacing: -1px;
font-size: 0.9rem;
font-weight: 400;
color: #404040;
td {
border-right: 1px solid #eee;
vertical-align: text-top;
+ color: #2e3438;
button {
text-align: left;
padding: 0;
@@ -41,7 +66,6 @@ $header: #5e81ac;
background-color: transparent;
cursor: pointer;
color: $copyable;
- letter-spacing: -1px;
span {
font-size: 1rem;
color: inherit;
@@ -56,6 +80,6 @@ $header: #5e81ac;
}
tbody tr:nth-of-type(even) {
- background-color: #f3f3f3;
+ background-color: #f7fafc;
}
}
diff --git a/src/docs/styling/intro.stories.mdx b/src/docs/styles/intro.stories.mdx
similarity index 73%
rename from src/docs/styling/intro.stories.mdx
rename to src/docs/styles/intro.stories.mdx
index f9244217..0adbcabc 100644
--- a/src/docs/styling/intro.stories.mdx
+++ b/src/docs/styles/intro.stories.mdx
@@ -1,13 +1,13 @@
import { Meta } from '@storybook/addon-docs';
import { parameters } from '$docs/utils/docsPage.js';
-
+

-# SCSS
+# Styles
-This library also includes our main SCSS stylesheets and pre-defined classes and SCSS mixins you can use to style your pages.
+This library also includes our main SCSS stylesheets with pre-defined classes you can use to style your page.
### Importing our main stylesheet
diff --git a/src/docs/styles/layout/flexbox.stories.mdx b/src/docs/styles/layout/flexbox.stories.mdx
new file mode 100644
index 00000000..01c9bde2
--- /dev/null
+++ b/src/docs/styles/layout/flexbox.stories.mdx
@@ -0,0 +1,124 @@
+import { Meta } from '@storybook/addon-docs';
+import { parameters } from '$docs/utils/docsPage.js';
+import CopyTable from '../../docs-components/CopyTable/Table.jsx';
+import { cssStringToTableArray } from '../../utils/parseCss';
+
+{/* @ts-ignore */}
+import alignContent from '$lib/scss/layout/flex/\_align-content.scss?raw';
+
+{/* @ts-ignore */}
+import alignItems from '$lib/scss/layout/flex/\_align-items.scss?raw';
+
+{/* @ts-ignore */}
+import alignSelf from '$lib/scss/layout/flex/\_align-self.scss?raw';
+
+{/* @ts-ignore */}
+import flexDirection from '$lib/scss/layout/flex/\_flex-direction.scss?raw';
+
+{/* @ts-ignore */}
+import flexGrow from '$lib/scss/layout/flex/\_flex-grow.scss?raw';
+
+{/* @ts-ignore */}
+import flexShrink from '$lib/scss/layout/flex/\_flex-shrink.scss?raw';
+
+{/* @ts-ignore */}
+import flexWrap from '$lib/scss/layout/flex/\_flex-wrap.scss?raw';
+
+{/* @ts-ignore */}
+import flex from '$lib/scss/layout/flex/\_flex.scss?raw';
+
+{/* @ts-ignore */}
+import justifyContent from '$lib/scss/layout/flex/\_justify-content.scss?raw';
+
+{/* @ts-ignore */}
+import justifyItems from '$lib/scss/layout/flex/\_justify-items.scss?raw';
+
+{/* @ts-ignore */}
+import justifySelf from '$lib/scss/layout/flex/\_justify-self.scss?raw';
+
+
+
+
+
+# Flexbox
+
+Flexbox is a modern way to lay out elements on your page while controling their alignment, distribution, space between and more. If flexbox is new, checkout the excellent [CSS tricks guide](https://css-tricks.com/snippets/css/a-guide-to-flexbox/).
+
+Our style library provides these flexbox utility classes:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/docs/styles/layout/utilities.stories.mdx b/src/docs/styles/layout/utilities.stories.mdx
new file mode 100644
index 00000000..0ba441ba
--- /dev/null
+++ b/src/docs/styles/layout/utilities.stories.mdx
@@ -0,0 +1,40 @@
+import { Meta } from '@storybook/addon-docs';
+import { parameters } from '$docs/utils/docsPage.js';
+import CopyTable from '../../docs-components/CopyTable/Table.jsx';
+import { cssStringToTableArray } from '../../utils/parseCss';
+
+{/* @ts-ignore */}
+import boxSizine from '$lib/scss/layout/\_box-sizing.scss?raw';
+
+{/* @ts-ignore */}
+import display from '$lib/scss/layout/\_display.scss?raw';
+
+{/* @ts-ignore */}
+import floats from '$lib/scss/layout/\_floats.scss?raw';
+
+
+
+
+
+# Layout classes
+
+
+
+
+
+
diff --git a/src/docs/styles/typography/MdxTheme.jsx b/src/docs/styles/typography/MdxTheme.jsx
deleted file mode 100644
index 41e46e85..00000000
--- a/src/docs/styles/typography/MdxTheme.jsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { Canvas, Unstyled } from '@storybook/blocks';
-
-import React from 'react';
-import flatten from '../../../components/Theme/utils/flatten';
-import lightTheme from '../../../components/Theme/themes/light';
-
-// This is a React equivalent for the Svelte Theme component
-// which is useful for setting CSS variables in MDX docs around
-// typography demos. It also wraps demos in an unstyled storybook
-// canvas.
-
-const ThemeWrapper = (props) => {
- const theme = flatten(lightTheme);
- const styleObj = {};
- Object.keys(theme).forEach(key => {
- styleObj[`--theme-${key}`] = theme[key];
- });
- return (
-
-
-
- );
-};
-
-export default ThemeWrapper;
diff --git a/src/docs/styles/typography/intro.stories.mdx b/src/docs/styles/typography/intro.stories.mdx
index 66e0568d..eef451fe 100644
--- a/src/docs/styles/typography/intro.stories.mdx
+++ b/src/docs/styles/typography/intro.stories.mdx
@@ -1,8 +1,13 @@
import { Meta } from '@storybook/addon-docs';
import { parameters } from '$docs/utils/docsPage.js';
+{/* @ts-ignore */}
import Typeset from './imgs/typeset.png';
+
+{/* @ts-ignore */}
import TypeGuides from './imgs/type-guides.png';
+
+{/* @ts-ignore */}
import DemoImg from './imgs/demo.png';
diff --git a/src/docs/styles/typography/utilities.stories.mdx b/src/docs/styles/typography/utilities.stories.mdx
index 3aee2b95..e8734ed3 100644
--- a/src/docs/styles/typography/utilities.stories.mdx
+++ b/src/docs/styles/typography/utilities.stories.mdx
@@ -1,138 +1,112 @@
import { Meta } from '@storybook/addon-docs';
import { parameters } from '$docs/utils/docsPage.js';
import CopyTable from '../../docs-components/CopyTable/Table.jsx';
+import { cssStringToTableArray } from '../../utils/parseCss';
+
+{/* @ts-ignore */}
+import fontFamily from '$lib/scss/text/\_font-family.scss?raw';
+
+{/* @ts-ignore */}
+import fontStyle from '$lib/scss/text/\_font-style.scss?raw';
+
+{/* @ts-ignore */}
+import fontWeight from '$lib/scss/text/\_font-weight.scss?raw';
+
+{/* @ts-ignore */}
+import letterSpacing from '$lib/scss/text/\_letter-spacing.scss?raw';
+
+{/* @ts-ignore */}
+import textAlign from '$lib/scss/text/\_text-align.scss?raw';
+
+{/* @ts-ignore */}
+import textDecoration from '$lib/scss/text/\_text-decoration.scss?raw';
+
+{/* @ts-ignore */}
+import textTransform from '$lib/scss/text/\_text-transform.scss?raw';
+
+{/* @ts-ignore */}
+import verticalAlign from '$lib/scss/text/\_vertical-align.scss?raw';
+
+{/* @ts-ignore */}
+import whiteSpace from '$lib/scss/text/\_white-space.scss?raw';
+
+{/* @ts-ignore */}
+import wordBreak from '$lib/scss/text/\_word-break.scss?raw';
import './styles.scss';
-
+

-# Utility classes
-
-Utility classes apply various often used styles to your markup. Just copy a class and use it on the element you wish to style.
-
-For example, these classes will bold and uppercase your text:
-
-```html
-My text
-```
-
-### Make it `!important`
-
-You can make any utility class `!important` by adding a `!` to the front of the class name.
-
-```html
-My text
-```
-
----
-
-### Font style
+# Typography classes
-### Font weight
-
-### Letter spacing
-
-### Text align
-
-### Text transform
-
-### Vertical align
-
-### White space
-
-### Word break
-
+
+
+
+
diff --git a/src/docs/utils/parseCss.js b/src/docs/utils/parseCss.js
new file mode 100644
index 00000000..97cc1c74
--- /dev/null
+++ b/src/docs/utils/parseCss.js
@@ -0,0 +1,18 @@
+import { convert } from '../../../bin/css-to-js/index.js';
+import { kebabCase } from 'lodash-es';
+
+export const cssStringToTableArray = (cssString) => {
+ const cssObj = convert(cssString);
+ return Object.entries(cssObj).map(([key, value]) => {
+ const className = key.replace(/_/g, '-');
+ const properties = Object.entries(value)
+ .map(([propName, propValue]) => {
+ return `${kebabCase(propName)}: ${propValue.replace(
+ /\s?!important/g,
+ ''
+ )};`;
+ })
+ .join('\n');
+ return [className, properties];
+ });
+};
diff --git a/src/scss/layout/_box-sizing.scss b/src/scss/layout/_box-sizing.scss
new file mode 100644
index 00000000..8ab8893f
--- /dev/null
+++ b/src/scss/layout/_box-sizing.scss
@@ -0,0 +1,12 @@
+.box-border {
+ box-sizing: border-box;
+}
+.box-content {
+ box-sizing: content-box;
+}
+.\!box-border {
+ box-sizing: border-box !important;
+}
+.\!box-content {
+ box-sizing: content-box !important;
+}
diff --git a/src/scss/layout/_display.scss b/src/scss/layout/_display.scss
new file mode 100644
index 00000000..72273eda
--- /dev/null
+++ b/src/scss/layout/_display.scss
@@ -0,0 +1,126 @@
+.block {
+ display: block;
+}
+.inline-block {
+ display: inline-block;
+}
+.inline {
+ display: inline;
+}
+.flex {
+ display: flex;
+}
+.inline-flex {
+ display: inline-flex;
+}
+.table {
+ display: table;
+}
+.inline-table {
+ display: inline-table;
+}
+.table-caption {
+ display: table-caption;
+}
+.table-cell {
+ display: table-cell;
+}
+.table-column {
+ display: table-column;
+}
+.table-column-group {
+ display: table-column-group;
+}
+.table-footer-group {
+ display: table-footer-group;
+}
+.table-header-group {
+ display: table-header-group;
+}
+.table-row-group {
+ display: table-row-group;
+}
+.table-row {
+ display: table-row;
+}
+.flow-root {
+ display: flow-root;
+}
+.grid {
+ display: grid;
+}
+.inline-grid {
+ display: inline-grid;
+}
+.contents {
+ display: contents;
+}
+.list-item {
+ display: list-item;
+}
+.hidden {
+ display: none;
+}
+.\!block {
+ display: block !important;
+}
+.\!inline-block {
+ display: inline-block !important;
+}
+.\!inline {
+ display: inline !important;
+}
+.\!flex {
+ display: flex !important;
+}
+.\!inline-flex {
+ display: inline-flex !important;
+}
+.\!table {
+ display: table !important;
+}
+.\!inline-table {
+ display: inline-table !important;
+}
+.\!table-caption {
+ display: table-caption !important;
+}
+.\!table-cell {
+ display: table-cell !important;
+}
+.\!table-column {
+ display: table-column !important;
+}
+.\!table-column-group {
+ display: table-column-group !important;
+}
+.\!table-footer-group {
+ display: table-footer-group !important;
+}
+.\!table-header-group {
+ display: table-header-group !important;
+}
+.\!table-row-group {
+ display: table-row-group !important;
+}
+.\!table-row {
+ display: table-row !important;
+}
+.\!flow-root {
+ display: flow-root !important;
+}
+.\!grid {
+ display: grid !important;
+}
+.\!inline-grid {
+ display: inline-grid !important;
+}
+.\!contents {
+ display: contents !important;
+}
+.\!list-item {
+ display: list-item !important;
+}
+.\!hidden {
+ display: none !important;
+}
diff --git a/src/scss/layout/_floats.scss b/src/scss/layout/_floats.scss
new file mode 100644
index 00000000..5fe95058
--- /dev/null
+++ b/src/scss/layout/_floats.scss
@@ -0,0 +1,18 @@
+.float-right {
+ float: right;
+}
+.float-left {
+ float: left;
+}
+.float-none {
+ float: none;
+}
+.\!float-right {
+ float: right !important;
+}
+.\!float-left {
+ float: left !important;
+}
+.\!float-none {
+ float: none !important;
+}
diff --git a/src/scss/layout/_rules.scss b/src/scss/layout/_rules.scss
new file mode 100644
index 00000000..4ea881ec
--- /dev/null
+++ b/src/scss/layout/_rules.scss
@@ -0,0 +1,4 @@
+@import 'flex/rules';
+@import 'box-sizing';
+@import 'display';
+@import 'floats';
diff --git a/src/scss/layout/flex/_align-content.scss b/src/scss/layout/flex/_align-content.scss
new file mode 100644
index 00000000..f8871ca8
--- /dev/null
+++ b/src/scss/layout/flex/_align-content.scss
@@ -0,0 +1,54 @@
+.content-normal {
+ align-content: normal;
+}
+.content-center {
+ align-content: center;
+}
+.content-start {
+ align-content: flex-start;
+}
+.content-end {
+ align-content: flex-end;
+}
+.content-between {
+ align-content: space-between;
+}
+.content-around {
+ align-content: space-around;
+}
+.content-evenly {
+ align-content: space-evenly;
+}
+.content-baseline {
+ align-content: baseline;
+}
+.content-stretch {
+ align-content: stretch;
+}
+.\!content-normal {
+ align-content: normal !important;
+}
+.\!content-center {
+ align-content: center !important;
+}
+.\!content-start {
+ align-content: flex-start !important;
+}
+.\!content-end {
+ align-content: flex-end !important;
+}
+.\!content-between {
+ align-content: space-between !important;
+}
+.\!content-around {
+ align-content: space-around !important;
+}
+.\!content-evenly {
+ align-content: space-evenly !important;
+}
+.\!content-baseline {
+ align-content: baseline !important;
+}
+.\!content-stretch {
+ align-content: stretch !important;
+}
diff --git a/src/scss/layout/flex/_align-items.scss b/src/scss/layout/flex/_align-items.scss
new file mode 100644
index 00000000..0ad5d1de
--- /dev/null
+++ b/src/scss/layout/flex/_align-items.scss
@@ -0,0 +1,30 @@
+.items-start {
+ align-items: flex-start;
+}
+.items-end {
+ align-items: flex-end;
+}
+.items-center {
+ align-items: center;
+}
+.items-baseline {
+ align-items: baseline;
+}
+.items-stretch {
+ align-items: stretch;
+}
+.\!items-start {
+ align-items: flex-start !important;
+}
+.\!items-end {
+ align-items: flex-end !important;
+}
+.\!items-center {
+ align-items: center !important;
+}
+.\!items-baseline {
+ align-items: baseline !important;
+}
+.\!items-stretch {
+ align-items: stretch !important;
+}
diff --git a/src/scss/layout/flex/_align-self.scss b/src/scss/layout/flex/_align-self.scss
new file mode 100644
index 00000000..8f2ec1e8
--- /dev/null
+++ b/src/scss/layout/flex/_align-self.scss
@@ -0,0 +1,36 @@
+.self-auto {
+ align-self: auto;
+}
+.self-start {
+ align-self: flex-start;
+}
+.self-end {
+ align-self: flex-end;
+}
+.self-center {
+ align-self: center;
+}
+.self-stretch {
+ align-self: stretch;
+}
+.self-baseline {
+ align-self: baseline;
+}
+.\!self-auto {
+ align-self: auto !important;
+}
+.\!self-start {
+ align-self: flex-start !important;
+}
+.\!self-end {
+ align-self: flex-end !important;
+}
+.\!self-center {
+ align-self: center !important;
+}
+.\!self-stretch {
+ align-self: stretch !important;
+}
+.\!self-baseline {
+ align-self: baseline !important;
+}
diff --git a/src/scss/layout/flex/_flex-direction.scss b/src/scss/layout/flex/_flex-direction.scss
new file mode 100644
index 00000000..a04fd76d
--- /dev/null
+++ b/src/scss/layout/flex/_flex-direction.scss
@@ -0,0 +1,24 @@
+.flex-row {
+ flex-direction: row;
+}
+.flex-row-reverse {
+ flex-direction: row-reverse;
+}
+.flex-col {
+ flex-direction: column;
+}
+.flex-col-reverse {
+ flex-direction: column-reverse;
+}
+.\!flex-row {
+ flex-direction: row !important;
+}
+.\!flex-row-reverse {
+ flex-direction: row-reverse !important;
+}
+.\!flex-col {
+ flex-direction: column !important;
+}
+.\!flex-col-reverse {
+ flex-direction: column-reverse !important;
+}
diff --git a/src/scss/layout/flex/_flex-grow.scss b/src/scss/layout/flex/_flex-grow.scss
new file mode 100644
index 00000000..b6f52f2a
--- /dev/null
+++ b/src/scss/layout/flex/_flex-grow.scss
@@ -0,0 +1,12 @@
+.grow {
+ flex-grow: 1;
+}
+.grow-0 {
+ flex-grow: 0;
+}
+.\!grow {
+ flex-grow: 1 !important;
+}
+.\!grow-0 {
+ flex-grow: 0 !important;
+}
diff --git a/src/scss/layout/flex/_flex-shrink.scss b/src/scss/layout/flex/_flex-shrink.scss
new file mode 100644
index 00000000..65c3a75d
--- /dev/null
+++ b/src/scss/layout/flex/_flex-shrink.scss
@@ -0,0 +1,12 @@
+.shrink {
+ flex-shrink: 1;
+}
+.shrink-0 {
+ flex-shrink: 0;
+}
+.\!shrink {
+ flex-shrink: 1 !important;
+}
+.\!shrink-0 {
+ flex-shrink: 0 !important;
+}
diff --git a/src/scss/layout/flex/_flex-wrap.scss b/src/scss/layout/flex/_flex-wrap.scss
new file mode 100644
index 00000000..5f175b95
--- /dev/null
+++ b/src/scss/layout/flex/_flex-wrap.scss
@@ -0,0 +1,18 @@
+.flex-wrap {
+ flex-wrap: wrap;
+}
+.flex-wrap-reverse {
+ flex-wrap: wrap-reverse;
+}
+.flex-nowrap {
+ flex-wrap: nowrap;
+}
+.\!flex-wrap {
+ flex-wrap: wrap !important;
+}
+.\!flex-wrap-reverse {
+ flex-wrap: wrap-reverse !important;
+}
+.\!flex-nowrap {
+ flex-wrap: nowrap !important;
+}
diff --git a/src/scss/layout/flex/_flex.scss b/src/scss/layout/flex/_flex.scss
new file mode 100644
index 00000000..e6c90d51
--- /dev/null
+++ b/src/scss/layout/flex/_flex.scss
@@ -0,0 +1,24 @@
+.flex-1 {
+ flex: 1 1 0%;
+}
+.flex-auto {
+ flex: 1 1 auto;
+}
+.flex-initial {
+ flex: 0 1 auto;
+}
+.flex-none {
+ flex: none;
+}
+.\!flex-1 {
+ flex: 1 1 0% !important;
+}
+.\!flex-auto {
+ flex: 1 1 auto !important;
+}
+.\!flex-initial {
+ flex: 0 1 auto !important;
+}
+.\!flex-none {
+ flex: none !important;
+}
diff --git a/src/scss/layout/flex/_justify-content.scss b/src/scss/layout/flex/_justify-content.scss
new file mode 100644
index 00000000..13d525f9
--- /dev/null
+++ b/src/scss/layout/flex/_justify-content.scss
@@ -0,0 +1,48 @@
+.justify-normal {
+ justify-content: normal;
+}
+.justify-start {
+ justify-content: flex-start;
+}
+.justify-end {
+ justify-content: flex-end;
+}
+.justify-center {
+ justify-content: center;
+}
+.justify-between {
+ justify-content: space-between;
+}
+.justify-around {
+ justify-content: space-around;
+}
+.justify-evenly {
+ justify-content: space-evenly;
+}
+.justify-stretch {
+ justify-content: stretch;
+}
+.\!justify-normal {
+ justify-content: normal !important;
+}
+.\!justify-start {
+ justify-content: flex-start !important;
+}
+.\!justify-end {
+ justify-content: flex-end !important;
+}
+.\!justify-center {
+ justify-content: center !important;
+}
+.\!justify-between {
+ justify-content: space-between !important;
+}
+.\!justify-around {
+ justify-content: space-around !important;
+}
+.\!justify-evenly {
+ justify-content: space-evenly !important;
+}
+.\!justify-stretch {
+ justify-content: stretch !important;
+}
diff --git a/src/scss/layout/flex/_justify-items.scss b/src/scss/layout/flex/_justify-items.scss
new file mode 100644
index 00000000..b2e4022a
--- /dev/null
+++ b/src/scss/layout/flex/_justify-items.scss
@@ -0,0 +1,24 @@
+.justify-items-start {
+ justify-items: start;
+}
+.justify-items-end {
+ justify-items: end;
+}
+.justify-items-center {
+ justify-items: center;
+}
+.justify-items-stretch {
+ justify-items: stretch;
+}
+.\!justify-items-start {
+ justify-items: start !important;
+}
+.\!justify-items-end {
+ justify-items: end !important;
+}
+.\!justify-items-center {
+ justify-items: center !important;
+}
+.\!justify-items-stretch {
+ justify-items: stretch !important;
+}
diff --git a/src/scss/layout/flex/_justify-self.scss b/src/scss/layout/flex/_justify-self.scss
new file mode 100644
index 00000000..0a9f23af
--- /dev/null
+++ b/src/scss/layout/flex/_justify-self.scss
@@ -0,0 +1,30 @@
+.justify-self-auto {
+ justify-self: auto;
+}
+.justify-self-start {
+ justify-self: start;
+}
+.justify-self-end {
+ justify-self: end;
+}
+.justify-self-center {
+ justify-self: center;
+}
+.justify-self-stretch {
+ justify-self: stretch;
+}
+.\!justify-self-auto {
+ justify-self: auto !important;
+}
+.\!justify-self-start {
+ justify-self: start !important;
+}
+.\!justify-self-end {
+ justify-self: end !important;
+}
+.\!justify-self-center {
+ justify-self: center !important;
+}
+.\!justify-self-stretch {
+ justify-self: stretch !important;
+}
diff --git a/src/scss/layout/flex/_rules.scss b/src/scss/layout/flex/_rules.scss
new file mode 100644
index 00000000..0c9bcd71
--- /dev/null
+++ b/src/scss/layout/flex/_rules.scss
@@ -0,0 +1,11 @@
+@import 'align-content';
+@import 'align-items';
+@import 'align-self';
+@import 'flex-direction';
+@import 'flex-grow';
+@import 'flex-shrink';
+@import 'flex-wrap';
+@import 'flex';
+@import 'justify-content';
+@import 'justify-items';
+@import 'justify-self';
diff --git a/src/scss/main.scss b/src/scss/main.scss
index 31b62fc0..c96f5b36 100644
--- a/src/scss/main.scss
+++ b/src/scss/main.scss
@@ -21,3 +21,4 @@
@import 'spacers/rules';
@import 'typography/rules';
@import 'text/rules';
+@import 'layout/rules';
diff --git a/src/scss/text/_font-family.scss b/src/scss/text/_font-family.scss
new file mode 100644
index 00000000..2935a668
--- /dev/null
+++ b/src/scss/text/_font-family.scss
@@ -0,0 +1,18 @@
+.font-serif {
+ font-family: var(--theme-typeface-serif);
+}
+.font-sans {
+ font-family: var(--theme-typeface-sans-serif);
+}
+.font-mono {
+ font-family: var(--theme-typeface-monospace);
+}
+.\!font-serif {
+ font-family: var(--theme-typeface-serif) !important;
+}
+.\!font-sans {
+ font-family: var(--theme-typeface-sans-serif) !important;
+}
+.\!font-mono {
+ font-family: var(--theme-typeface-monospace) !important;
+}
diff --git a/src/scss/text/_rules.scss b/src/scss/text/_rules.scss
index 7b50e364..4b8e2098 100644
--- a/src/scss/text/_rules.scss
+++ b/src/scss/text/_rules.scss
@@ -1,3 +1,4 @@
+@import 'font-family';
@import 'font-style';
@import 'font-weight';
@import 'letter-spacing';
diff --git a/yarn.lock b/yarn.lock
index 9c22f6b4..7f8a51b8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,6 +2,13 @@
# yarn lockfile v1
+"@americanexpress/css-to-js@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@americanexpress/css-to-js/-/css-to-js-1.0.1.tgz#fcef058d9febcc492a1c941f71ac5177bc2c3f5d"
+ integrity sha512-bblN1i5kZIdsmWU7CSpK/HVtUItq5Ly1Qubgbe+cGZx181Ji3F0VrQt6+DdYPgkPENUFdFqJHDfgVE1tQz5B/Q==
+ dependencies:
+ css "^2.2.4"
+
"@ampproject/remapping@^2.2.0":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630"
@@ -2476,6 +2483,11 @@
resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.4.tgz#d1cad61ccc803b3c248c3d9990a2a6880bef537f"
integrity sha512-qCYrNdpKwN6YO6FVnx+ulfqifKlE3lQGsNhvDaW9Oxzyob/cRLBJWow8GHBBD4NxQ7BVvtsATgLsX0vZAWmtrg==
+"@types/mdx@^2.0.5":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.5.tgz#9a85a8f70c7c4d9e695a21d5ae5c93645eda64b1"
+ integrity sha512-76CqzuD6Q7LC+AtbPqrvD9AqsN0k8bsYo2bM2J8pmNldP1aIPAbzUQ7QbobyXL4eLr1wK5x8FZFe8eF/ubRuBg==
+
"@types/mime-types@^2.1.0":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@types/mime-types/-/mime-types-2.1.1.tgz#d9ba43490fa3a3df958759adf69396c3532cf2c1"
@@ -3010,6 +3022,11 @@ asynckit@^0.4.0:
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+atob@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
+ integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
+
autoprefixer@^10.4.14:
version "10.4.14"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d"
@@ -3646,6 +3663,16 @@ css-unit-converter@^1.1.2:
resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21"
integrity sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==
+css@^2.2.4:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
+ integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==
+ dependencies:
+ inherits "^2.0.3"
+ source-map "^0.6.1"
+ source-map-resolve "^0.5.2"
+ urix "^0.1.0"
+
csstype@^3.0.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
@@ -7537,6 +7564,11 @@ resolve-from@^5.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+resolve-url@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
+ integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==
+
resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.22.1:
version "1.22.3"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.3.tgz#4b4055349ffb962600972da1fdc33c46a4eb3283"
@@ -7890,6 +7922,17 @@ sorcery@^0.11.0:
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
+source-map-resolve@^0.5.2:
+ version "0.5.3"
+ resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
+ integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
+ dependencies:
+ atob "^2.1.2"
+ decode-uri-component "^0.2.0"
+ resolve-url "^0.2.1"
+ source-map-url "^0.4.0"
+ urix "^0.1.0"
+
source-map-support@^0.5.16:
version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
@@ -7898,6 +7941,11 @@ source-map-support@^0.5.16:
buffer-from "^1.0.0"
source-map "^0.6.0"
+source-map-url@^0.4.0:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
+ integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
+
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
@@ -8579,6 +8627,11 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
+urix@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
+ integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==
+
use-resize-observer@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/use-resize-observer/-/use-resize-observer-9.1.0.tgz#14735235cf3268569c1ea468f8a90c5789fc5c6c"