+`
+}
+
export const createLayout = ({ style = 'basic', rightSidebar = false }) => {
if (style === 'basic') {
return createBasicLayout()
@@ -315,5 +388,9 @@ export const createLayout = ({ style = 'basic', rightSidebar = false }) => {
return createUtilityLayout()
}
+ if (style === 'card-grid') {
+ return createCardGridLayout()
+ }
+
return ``
}
diff --git a/src/stories/Recipes/Layout/Layout.mdx b/src/stories/Recipes/Layout/Layout.mdx
index d1be640c..66604309 100644
--- a/src/stories/Recipes/Layout/Layout.mdx
+++ b/src/stories/Recipes/Layout/Layout.mdx
@@ -259,6 +259,14 @@ A layout for a login page could look like the following:
### Utility
-A layout explaining how the stack, split, and cluster utilities can be used to make flex layouts more readable.
+A layout explaining how the stack, split, cluster, and flank utilities can be used to make flex layouts more readable.
+
+### Card Grid
+
+A responsive card grid built with the `op-grid` and `op-frame` utilities. The `op-frame` utility keeps each card's
+media at a consistent aspect ratio regardless of the source image dimensions, and it isn't limited to media — the
+"Coming soon" card frames a text placeholder to hold the same shape.
+
+
diff --git a/src/stories/Recipes/Layout/Layout.stories.js b/src/stories/Recipes/Layout/Layout.stories.js
index f5c8f100..1d62c93e 100644
--- a/src/stories/Recipes/Layout/Layout.stories.js
+++ b/src/stories/Recipes/Layout/Layout.stories.js
@@ -8,7 +8,7 @@ export default {
argTypes: {
style: {
control: { type: 'select' },
- options: ['basic', 'sidebar', 'navbar', 'spinner', 'sidepanel', 'login', 'utility'],
+ options: ['basic', 'sidebar', 'navbar', 'spinner', 'sidepanel', 'login', 'utility', 'card-grid'],
},
rightSidebar: {
control: { type: 'boolean' },
@@ -68,3 +68,9 @@ export const Utility = {
style: 'utility',
},
}
+
+export const CardGrid = {
+ args: {
+ style: 'card-grid',
+ },
+}
diff --git a/src/stories/Utilities/Cluster/Cluster.js b/src/stories/Utilities/Advanced/Cluster/Cluster.js
similarity index 86%
rename from src/stories/Utilities/Cluster/Cluster.js
rename to src/stories/Utilities/Advanced/Cluster/Cluster.js
index 5a9e435a..9a5f680f 100644
--- a/src/stories/Utilities/Cluster/Cluster.js
+++ b/src/stories/Utilities/Advanced/Cluster/Cluster.js
@@ -1,4 +1,4 @@
-import { createChildren } from '../../helpers/utils'
+import { createChildren } from '../../../helpers/utils'
export const createCluster = ({ cluster = true, alignItems = '', gap = '' }) => {
const wrapper = document.createElement('div')
diff --git a/src/stories/Utilities/Cluster/Cluster.mdx b/src/stories/Utilities/Advanced/Cluster/Cluster.mdx
similarity index 96%
rename from src/stories/Utilities/Cluster/Cluster.mdx
rename to src/stories/Utilities/Advanced/Cluster/Cluster.mdx
index 0ea45cb6..d0eff28a 100644
--- a/src/stories/Utilities/Cluster/Cluster.mdx
+++ b/src/stories/Utilities/Advanced/Cluster/Cluster.mdx
@@ -1,6 +1,6 @@
import { Meta, Story, Canvas, Controls } from '@storybook/addon-docs/blocks'
import * as ClusterStories from './Cluster.stories'
-import { createSourceCodeLink } from '../../helpers/sourceCodeLink.js'
+import { createSourceCodeLink } from '../../../helpers/sourceCodeLink.js'
diff --git a/src/stories/Utilities/Cluster/Cluster.stories.js b/src/stories/Utilities/Advanced/Cluster/Cluster.stories.js
similarity index 90%
rename from src/stories/Utilities/Cluster/Cluster.stories.js
rename to src/stories/Utilities/Advanced/Cluster/Cluster.stories.js
index dbba4f28..035090e3 100644
--- a/src/stories/Utilities/Cluster/Cluster.stories.js
+++ b/src/stories/Utilities/Advanced/Cluster/Cluster.stories.js
@@ -1,7 +1,7 @@
import { createCluster } from './Cluster.js'
export default {
- title: 'Utilities/Cluster',
+ title: 'Utilities/Advanced/Cluster',
render: ({ cluster, ...args }) => {
return createCluster({ cluster, ...args })
},
@@ -13,7 +13,7 @@ export default {
},
gap: {
control: { type: 'select' },
- options: ['xxs', 'xs', 'sm', 'md', 'lg', 'xl'],
+ options: ['none', 'xxs', 'xs', 'sm', 'md', 'lg', 'xl'],
},
},
parameters: {
diff --git a/src/stories/Utilities/Advanced/Flank/Flank.js b/src/stories/Utilities/Advanced/Flank/Flank.js
new file mode 100644
index 00000000..a4a8fb12
--- /dev/null
+++ b/src/stories/Utilities/Advanced/Flank/Flank.js
@@ -0,0 +1,46 @@
+import { createChildren } from '../../../helpers/utils'
+import { createAvatar } from '../../../Components/Avatar/Avatar'
+import { createTextPair } from '../../../Components/TextPair/TextPair'
+
+export const createFlank = ({ flank = true, end = false, gap = '', example = false }) => {
+ if (example) {
+ return createAvatarExample({ flank, end, gap })
+ }
+
+ const wrapper = document.createElement('div')
+
+ wrapper.className = classlist(flank, end, gap)
+
+ createChildren(wrapper, 2)
+
+ return wrapper
+}
+
+const createAvatarExample = ({ flank, end, gap }) => {
+ const avatar = createAvatar({
+ size: 'large',
+ useLink: false,
+ imageSource: 'https://avatars.githubusercontent.com/u/5957102?v=4',
+ }).outerHTML
+ const textPairEl = createTextPair({ titleText: 'Jeremy Walton', subtitleText: 'RoleModel Software' })
+ if (end) textPairEl.classList.add('text-right')
+ const textPair = textPairEl.outerHTML
+
+ // Reverse order of elements if end is true
+ const [first, second] = end ? [textPair, avatar] : [avatar, textPair]
+
+ return `
+
+
+ ${first}
+ ${second}
+
+
+`
+}
+
+const classlist = (flank, end, gap) => {
+ return [flank ? 'op-flank' : '', flank && end ? 'op-flank--end' : '', gap ? `gap-${gap}` : '']
+ .filter(Boolean)
+ .join(' ')
+}
diff --git a/src/stories/Utilities/Advanced/Flank/Flank.mdx b/src/stories/Utilities/Advanced/Flank/Flank.mdx
new file mode 100644
index 00000000..925d82a7
--- /dev/null
+++ b/src/stories/Utilities/Advanced/Flank/Flank.mdx
@@ -0,0 +1,57 @@
+import { Meta, Story, Canvas, Controls } from '@storybook/addon-docs/blocks'
+import * as FlankStories from './Flank.stories'
+import { createSourceCodeLink } from '../../../helpers/sourceCodeLink.js'
+
+
+
+# Flank
+
+
+
+The flank utility provides a simple way to create a horizontal row with an item flanked by another large item. It
+works with all of the gap and other flex utilities.
+
+See [Utility Introduction](?path=/docs/utilities-introduction--docs#higher-order-utilities-vs-components) for more information.
+
+See [Utility Layout](?path=/docs/recipes-layout--docs#utility) for an example of how flanks
+can be used to create more readable flex layouts.
+
+Note: This utility uses the `op` prefix to avoid potential naming conflicts with other CSS frameworks.
+This is a pattern we hope to move towards for all utilities in the future.
+
+## Playground
+
+
+
+
+## Without
+
+A normal `div` without the flank utility
+
+
+
+## Flank Property
+
+`.op-flank` Creates a flex row with an item flanked by another large item.
+
+
+
+## Flank End
+
+`.op-flank.op-flank--end` Flips which side of the container the item is flanked to.
+
+
+
+## Example Flank
+
+`.op-flank` with an avatar and text pair to demonstrate a common use case.
+
+
+
+`.op-flank.op-flank--end` to show an alternate example.
+
+
diff --git a/src/stories/Utilities/Advanced/Flank/Flank.stories.js b/src/stories/Utilities/Advanced/Flank/Flank.stories.js
new file mode 100644
index 00000000..94a44b97
--- /dev/null
+++ b/src/stories/Utilities/Advanced/Flank/Flank.stories.js
@@ -0,0 +1,54 @@
+import { createFlank } from './Flank.js'
+
+export default {
+ title: 'Utilities/Advanced/Flank',
+ render: ({ flank, end, ...args }) => {
+ return createFlank({ flank, end, ...args })
+ },
+ argTypes: {
+ flank: { control: 'boolean' },
+ end: { control: 'boolean' },
+ gap: {
+ control: { type: 'select' },
+ options: ['none', 'xxs', 'xs', 'sm', 'md', 'lg', 'xl'],
+ },
+ example: { control: 'boolean' },
+ },
+ parameters: {
+ layout: 'fullscreen',
+ },
+}
+
+export const With = {
+ args: {
+ flank: true,
+ },
+}
+
+export const Without = {
+ args: {
+ flank: false,
+ },
+}
+
+export const FlankEnd = {
+ args: {
+ flank: true,
+ end: true,
+ },
+}
+
+export const AvatarExample = {
+ args: {
+ flank: true,
+ example: true,
+ },
+}
+
+export const AvatarExampleEnd = {
+ args: {
+ flank: true,
+ example: true,
+ end: true,
+ },
+}
diff --git a/src/stories/Utilities/Advanced/Frame/Frame.js b/src/stories/Utilities/Advanced/Frame/Frame.js
new file mode 100644
index 00000000..377d31ff
--- /dev/null
+++ b/src/stories/Utilities/Advanced/Frame/Frame.js
@@ -0,0 +1,18 @@
+const IMAGE_SOURCE = 'https://images.unsplash.com/photo-1517849845537-4d257902454a?w=800&q=80'
+
+export const createFrame = ({ frame = true, aspect = '', inlineSize = '' }) => {
+ const style = inlineSize ? ` style="--_op-frame-inline-size: ${inlineSize};"` : ''
+
+ // Sizing is for demo only, don't write inline styles
+ return `
+
+
+
+
+
+`
+}
+
+const classlist = (frame, aspect) => {
+ return [frame ? 'op-frame' : '', frame && aspect ? `op-frame--${aspect}` : ''].filter(Boolean).join(' ')
+}
diff --git a/src/stories/Utilities/Advanced/Frame/Frame.mdx b/src/stories/Utilities/Advanced/Frame/Frame.mdx
new file mode 100644
index 00000000..90f09b48
--- /dev/null
+++ b/src/stories/Utilities/Advanced/Frame/Frame.mdx
@@ -0,0 +1,88 @@
+import { Meta, Story, Canvas, Controls } from '@storybook/addon-docs/blocks'
+import * as FrameStories from './Frame.stories.js'
+import { createSourceCodeLink } from '../../../helpers/sourceCodeLink.js'
+
+
+
+# Frame
+
+
+
+The frame utility provides a simple way to constrain content to a consistent aspect ratio. It centers its content
+and clips any overflow, so whatever it wraps fills a fixed shape regardless of its intrinsic dimensions.
+
+While it's a natural fit for media like images and videos, the frame isn't limited to them — its primary job is
+enforcing the aspect ratio, so it works just as well for cards, map embeds, charts, or any element that should hold
+a fixed shape.
+
+See [Utility Introduction](?path=/docs/utilities-introduction--docs#higher-order-utilities-vs-components) for more information.
+
+See [Card Grid Layout](?path=/docs/recipes-layout--docs#card-grid) for an example of how frames
+can be used to keep media at a consistent aspect ratio within a card grid.
+
+Note: This utility uses the `op` prefix to avoid potential naming conflicts with other CSS frameworks.
+This is a pattern we hope to move towards for all utilities in the future.
+
+## Playground
+
+
+
+
+## Without
+
+A normal `div` without the frame utility
+
+
+
+## Square
+
+`.op-frame.op-frame--square` Crops media to a 1:1 aspect ratio. This is also the default when no aspect modifier is applied.
+
+
+
+## Landscape
+
+`.op-frame.op-frame--landscape` Crops media to a 16:9 aspect ratio.
+
+
+
+## Portrait
+
+`.op-frame.op-frame--portrait` Crops media to a 9:16 aspect ratio.
+
+
+
+## 4:3
+
+`.op-frame.op-frame--4-3` Crops media to a 4:3 aspect ratio.
+
+
+
+## 3:4
+
+`.op-frame.op-frame--3-4` Crops media to a 3:4 (inverse of 4:3) aspect ratio.
+
+
+
+## 3:2
+
+`.op-frame.op-frame--3-2` Crops media to a 3:2 aspect ratio.
+
+
+
+## 2:3
+
+`.op-frame.op-frame--2-3` Crops media to a 2:3 (inverse of 3:2) aspect ratio.
+
+
+
+## Custom Inline Size
+
+The `--_op-frame-inline-size` custom property controls the frame's `max-inline-size` (defaults to `100%`).
+Set it inline to constrain the frame to a smaller width while preserving its aspect ratio.
+
+
diff --git a/src/stories/Utilities/Advanced/Frame/Frame.stories.js b/src/stories/Utilities/Advanced/Frame/Frame.stories.js
new file mode 100644
index 00000000..f0a39a06
--- /dev/null
+++ b/src/stories/Utilities/Advanced/Frame/Frame.stories.js
@@ -0,0 +1,90 @@
+import { createFrame } from './Frame.js'
+
+export default {
+ title: 'Utilities/Advanced/Frame',
+ render: ({ frame, ...args }) => {
+ return createFrame({ frame, ...args })
+ },
+ argTypes: {
+ frame: { control: 'boolean' },
+ aspect: {
+ control: { type: 'select' },
+ options: ['square', 'landscape', 'portrait', '4-3', '3-4', '3-2', '2-3'],
+ },
+ inlineSize: {
+ control: { type: 'text' },
+ },
+ },
+ parameters: {
+ layout: 'fullscreen',
+ },
+}
+
+export const With = {
+ args: {
+ frame: true,
+ },
+}
+
+export const Without = {
+ args: {
+ frame: false,
+ },
+}
+
+export const Square = {
+ args: {
+ frame: true,
+ aspect: 'square',
+ },
+}
+
+export const Landscape = {
+ args: {
+ frame: true,
+ aspect: 'landscape',
+ },
+}
+
+export const Portrait = {
+ args: {
+ frame: true,
+ aspect: 'portrait',
+ },
+}
+
+export const FourThree = {
+ args: {
+ frame: true,
+ aspect: '4-3',
+ },
+}
+
+export const ThreeFour = {
+ args: {
+ frame: true,
+ aspect: '3-4',
+ },
+}
+
+export const ThreeTwo = {
+ args: {
+ frame: true,
+ aspect: '3-2',
+ },
+}
+
+export const TwoThree = {
+ args: {
+ frame: true,
+ aspect: '2-3',
+ },
+}
+
+export const CustomInlineSize = {
+ args: {
+ frame: true,
+ aspect: 'square',
+ inlineSize: '50%',
+ },
+}
diff --git a/src/stories/Utilities/Advanced/Grid/Grid.js b/src/stories/Utilities/Advanced/Grid/Grid.js
new file mode 100644
index 00000000..5daf48b7
--- /dev/null
+++ b/src/stories/Utilities/Advanced/Grid/Grid.js
@@ -0,0 +1,14 @@
+import { createChildren } from '../../../helpers/utils'
+
+export const createGrid = ({ grid = true, gap = '', columns = 0 }) => {
+ const wrapper = document.createElement('div')
+ wrapper.style.height = '10rem'
+
+ wrapper.className = [grid ? 'op-grid' : '', gap ? `gap-${gap}` : '', columns > 0 ? `op-grid--${columns}-column` : '']
+ .filter(Boolean)
+ .join(' ')
+
+ createChildren(wrapper, 10)
+
+ return wrapper
+}
diff --git a/src/stories/Utilities/Advanced/Grid/Grid.mdx b/src/stories/Utilities/Advanced/Grid/Grid.mdx
new file mode 100644
index 00000000..8c209538
--- /dev/null
+++ b/src/stories/Utilities/Advanced/Grid/Grid.mdx
@@ -0,0 +1,39 @@
+import { Meta, Story, Canvas, Controls } from '@storybook/addon-docs/blocks'
+import * as GridStories from './Grid.stories.js'
+import { createSourceCodeLink } from '../../../helpers/sourceCodeLink.js'
+
+
+
+# Grid
+
+
+
+The grid utility provides a simple way to create a dynamic grid layout. It is primarily intended for simple layouts with a minimum column size, or evenly divided columns from 2 to 6.
+
+See [Utility Introduction](?path=/docs/utilities-introduction--docs#higher-order-utilities-vs-components) for more information.
+
+Note: This utility uses the `op` prefix to avoid potential naming conflicts with other CSS frameworks.
+This is a pattern we hope to move towards for all utilities in the future.
+
+## Playground
+
+
+
+
+## Without
+
+A normal `div` without the grid utility
+
+
+
+## Two columns
+
+
+
+## Six columns
+
+
diff --git a/src/stories/Utilities/Advanced/Grid/Grid.stories.js b/src/stories/Utilities/Advanced/Grid/Grid.stories.js
new file mode 100644
index 00000000..5fde73be
--- /dev/null
+++ b/src/stories/Utilities/Advanced/Grid/Grid.stories.js
@@ -0,0 +1,52 @@
+import { createGrid } from './Grid.js'
+
+export default {
+ title: 'Utilities/Advanced/Grid',
+ render: ({ grid, ...args }) => {
+ return createGrid({ grid, ...args })
+ },
+ argTypes: {
+ grid: { control: 'boolean' },
+ gap: {
+ control: { type: 'select' },
+ options: ['none', 'xxs', 'xs', 'sm', 'md', 'lg', 'xl'],
+ },
+ columns: {
+ control: {
+ type: 'number',
+ min: 2,
+ max: 6,
+ step: 1,
+ },
+ },
+ },
+ parameters: {
+ layout: 'fullscreen',
+ },
+}
+
+export const With = {
+ args: {
+ grid: true,
+ },
+}
+
+export const Without = {
+ args: {
+ grid: false,
+ },
+}
+
+export const TwoColumns = {
+ args: {
+ grid: true,
+ columns: 2,
+ },
+}
+
+export const SixColumns = {
+ args: {
+ grid: true,
+ columns: 6,
+ },
+}
diff --git a/src/stories/Utilities/Split/Split.js b/src/stories/Utilities/Advanced/Split/Split.js
similarity index 86%
rename from src/stories/Utilities/Split/Split.js
rename to src/stories/Utilities/Advanced/Split/Split.js
index eedb2741..33b4a21e 100644
--- a/src/stories/Utilities/Split/Split.js
+++ b/src/stories/Utilities/Advanced/Split/Split.js
@@ -1,4 +1,4 @@
-import { createChildren } from '../../helpers/utils'
+import { createChildren } from '../../../helpers/utils'
export const createSplit = ({ split = true, alignItems = '', gap = '' }) => {
const wrapper = document.createElement('div')
diff --git a/src/stories/Utilities/Split/Split.mdx b/src/stories/Utilities/Advanced/Split/Split.mdx
similarity index 96%
rename from src/stories/Utilities/Split/Split.mdx
rename to src/stories/Utilities/Advanced/Split/Split.mdx
index fd29fb50..9f5554fc 100644
--- a/src/stories/Utilities/Split/Split.mdx
+++ b/src/stories/Utilities/Advanced/Split/Split.mdx
@@ -1,6 +1,6 @@
import { Meta, Story, Canvas, Controls } from '@storybook/addon-docs/blocks'
import * as SplitStories from './Split.stories'
-import { createSourceCodeLink } from '../../helpers/sourceCodeLink.js'
+import { createSourceCodeLink } from '../../../helpers/sourceCodeLink.js'
diff --git a/src/stories/Utilities/Split/Split.stories.js b/src/stories/Utilities/Advanced/Split/Split.stories.js
similarity index 90%
rename from src/stories/Utilities/Split/Split.stories.js
rename to src/stories/Utilities/Advanced/Split/Split.stories.js
index fb90f668..829e8261 100644
--- a/src/stories/Utilities/Split/Split.stories.js
+++ b/src/stories/Utilities/Advanced/Split/Split.stories.js
@@ -1,7 +1,7 @@
import { createSplit } from './Split.js'
export default {
- title: 'Utilities/Split',
+ title: 'Utilities/Advanced/Split',
render: ({ split, ...args }) => {
return createSplit({ split, ...args })
},
@@ -13,7 +13,7 @@ export default {
},
gap: {
control: { type: 'select' },
- options: ['xxs', 'xs', 'sm', 'md', 'lg', 'xl'],
+ options: ['none', 'xxs', 'xs', 'sm', 'md', 'lg', 'xl'],
},
},
parameters: {
diff --git a/src/stories/Utilities/Stack/Stack.js b/src/stories/Utilities/Advanced/Stack/Stack.js
similarity index 85%
rename from src/stories/Utilities/Stack/Stack.js
rename to src/stories/Utilities/Advanced/Stack/Stack.js
index 68a6e2c3..4f5d3fb2 100644
--- a/src/stories/Utilities/Stack/Stack.js
+++ b/src/stories/Utilities/Advanced/Stack/Stack.js
@@ -1,4 +1,4 @@
-import { createChildren } from '../../helpers/utils'
+import { createChildren } from '../../../helpers/utils'
export const createStack = ({ stack = true, alignItems = '', gap = '' }) => {
const wrapper = document.createElement('div')
diff --git a/src/stories/Utilities/Stack/Stack.mdx b/src/stories/Utilities/Advanced/Stack/Stack.mdx
similarity index 96%
rename from src/stories/Utilities/Stack/Stack.mdx
rename to src/stories/Utilities/Advanced/Stack/Stack.mdx
index ca014144..278f3d39 100644
--- a/src/stories/Utilities/Stack/Stack.mdx
+++ b/src/stories/Utilities/Advanced/Stack/Stack.mdx
@@ -1,6 +1,6 @@
import { Meta, Story, Canvas, Controls } from '@storybook/addon-docs/blocks'
import * as StackStories from './Stack.stories'
-import { createSourceCodeLink } from '../../helpers/sourceCodeLink.js'
+import { createSourceCodeLink } from '../../../helpers/sourceCodeLink.js'
diff --git a/src/stories/Utilities/Stack/Stack.stories.js b/src/stories/Utilities/Advanced/Stack/Stack.stories.js
similarity index 90%
rename from src/stories/Utilities/Stack/Stack.stories.js
rename to src/stories/Utilities/Advanced/Stack/Stack.stories.js
index 53aaa95e..67e6968b 100644
--- a/src/stories/Utilities/Stack/Stack.stories.js
+++ b/src/stories/Utilities/Advanced/Stack/Stack.stories.js
@@ -1,7 +1,7 @@
import { createStack } from './Stack.js'
export default {
- title: 'Utilities/Stack',
+ title: 'Utilities/Advanced/Stack',
render: ({ stack, ...args }) => {
return createStack({ stack, ...args })
},
@@ -13,7 +13,7 @@ export default {
},
gap: {
control: { type: 'select' },
- options: ['xxs', 'xs', 'sm', 'md', 'lg', 'xl'],
+ options: ['none', 'xxs', 'xs', 'sm', 'md', 'lg', 'xl'],
},
},
parameters: {
diff --git a/src/stories/Utilities/Gap/Gap.mdx b/src/stories/Utilities/Gap/Gap.mdx
index 6b46dbff..6692b25b 100644
--- a/src/stories/Utilities/Gap/Gap.mdx
+++ b/src/stories/Utilities/Gap/Gap.mdx
@@ -78,3 +78,9 @@ When using a gap utility, `--op-gap` will be set to the same spacing value as ga
`.gap-xl` This will use `--op-space-xl` for the item spacing.
+
+## None
+
+`.gap-none` This useful for removing a default gap. Especially useful for the [Advanced Utilities](?path=/docs/utilities-advanced-cluster--docs) which have a default gap of `--op-space-medium`.
+
+
diff --git a/src/stories/Utilities/Gap/Gap.stories.js b/src/stories/Utilities/Gap/Gap.stories.js
index 77cac679..769d8f6c 100644
--- a/src/stories/Utilities/Gap/Gap.stories.js
+++ b/src/stories/Utilities/Gap/Gap.stories.js
@@ -8,11 +8,17 @@ export default {
argTypes: {
size: {
control: { type: 'select' },
- options: ['xxs', 'xs', 'sm', 'md', 'lg', 'xl'],
+ options: ['none', 'xxs', 'xs', 'sm', 'md', 'lg', 'xl'],
},
},
}
+export const None = {
+ args: {
+ size: 'none',
+ },
+}
+
export const ExtraExtraSmall = {
args: {
size: 'xxs',
diff --git a/src/stories/Utilities/Introduction.mdx b/src/stories/Utilities/Introduction.mdx
index 6141a507..43fc88ad 100644
--- a/src/stories/Utilities/Introduction.mdx
+++ b/src/stories/Utilities/Introduction.mdx
@@ -12,9 +12,8 @@ import { createAlert } from '../Components/Alert/Alert.js'
}}
>
-Utility classes are simple CSS classes scoped to a simple style property like flex or gap.
-They can be added together to style a portion of your HTML from scratch.
-This is especially useful for quickly scaffolding out page layouts.
+Utility classes are CSS classes scoped to a simple style property like flex or gap or a collection of related properties.
+They can be combined together to quickly scaffold out page layouts or a portion of your HTML.
Optics provides limited but high value utility classes. Utilities can often and easily lead to poorly written CSS,
inconsistent styling, or unresponsive layouts. However, there are cases where utilities can provide great value.
@@ -69,13 +68,13 @@ This will allow for more complex layout to be managed within a named CSS class a
- If your layout needs to handle breakpoints or special responsive rules, utilities are going to get in the way of making this easy. You probably want to name the concept.
- If a particular collection of utilities is getting used together often, it may point to a UI pattern in your design that should be named.
-### Higher Order Utilities vs Components
+### Advanced Utilities vs Components
While flex utilities are great for moving quickly or for simple layouts, they can easily become
cumbersome to manage and tend to turn into "Flex Spaghetti". In some of these cases, reaching
for named components may make sense. However, there are times when a full component is more
restrictive than you need and hurts productivity. Sometimes you need just a bit more structure
-to your layout, but not a component. [Stack](?path=/docs/utilities-stack--docs), [Cluster](?path=/docs/utilities-cluster--docs), and [Split](?path=/docs/utilities-split--docs)
+to your layout, but not a component. [Stack](?path=/docs/utilities-advanced-stack--docs), [Cluster](?path=/docs/utilities-advanced-cluster--docs), [Split](?path=/docs/utilities-advanced-split--docs), [Flank](?path=/docs/utilities-advanced-flank--docs), and [Grid](?path=/docs/utilities-advanced-grid--docs)
provide a simple way to create readable, flexible layouts without the overhead of a full component.
## A word of warning