| Version | Tag | Status | API |
|---|---|---|---|
| v2 | <oc-row-v2> |
Stable, allowed for generation | RowV2 |
Overview (v2)
Source: ./src/components/row/v2/Overview.mdx
Row
The row component provides a flexible row layout with multiple variants, including label, image, headline, and two-columns. It supports interactive features such as clickable rows, selectable states, and customizable icons and images.
Default variation
Story Default:
<oc-row-v2><oc-placeholder-v1>PLACEHOLDER</oc-placeholder-v1></oc-row-v2>
Configuration
The Row component offers a variety of styling variants such as ... This component is highly configurable, allowing you to tailor its features and appearance to your specific needs. To explore all the available options and adjust the component, use the component configurator and see the changes affect the component in real-time.
Usage guidelines
Before integrating the Row component into your project, make sure you have correctly installed the OTTO components package. Look through the variations page for examples of possible component variations. Here, you can discover both common and specific variations that address different use cases.
Info
See the Row UX documentation for detailed user experience guidelines.
Layout considerations
This component has visual overflow in certain states.
When the component is in the hover or active states, it extends beyond its bounding box and is clipped by parent containers with overflow: hidden.
Ensure the parent container has sufficient padding to accommodate the component's full visual area.
Accessibility
The row component comes with a set of built-in accessibility features to ensure a seamless experience for all users.
Use oc-aria-label
To make the row recognizable for screen readers, use the oc-aria-label attribute to provide clear and descriptive context information.
See the general accessibility documentation for guidance on using oc-aria-label, including how it works with link and masked link behavior.
Configuration (v2)
Source: ./src/components/row/v2/Configuration.mdx
Row configuration
Configure the Row component with the controls below and see the changes live in the preview canvas. Click the Show code button within the preview canvas to see the source code for the current component configuration.
Story Default:
<oc-row-v2><oc-placeholder-v1>PLACEHOLDER</oc-placeholder-v1></oc-row-v2>
Interactive configurator (Storybook controls); every option is listed in the API section of this file.
Migration (v2)
Source: ./src/components/row/v2/Migration.mdx
Migration from Row v1 to v2
The oc-row component has been updated from oc-row-v1 to oc-row-v2.
This migration guide provides a step-by-step guide to update your project to the latest version.
The new oc-row-v2 component supports many use cases out of the box, eliminating the need for custom styles that were necessary with the previous version.
Skip to:
What's new
Web component
The row is now a proper web component instead of a CSS-only class, providing:
- Encapsulated styling
- Built-in icon support via
icon-leftandicon-rightattributes - Multiple variants (
default,image,headline,two-columns) - Native support for list views
API changes
Changed structure
| v1 (CSS class) | v2 (Web Component) | Notes |
|---|---|---|
<div class="oc-row-v1"> |
<oc-row-v2> |
Component-based |
oc-row-v1--hide-divider |
hide-divider |
No change |
oc-row-v1--selected |
selected |
No change |
oc-row-v1--interactive |
Not needed | Automatically applied with as-button or href |
How to migrate
Instead of using a div (or a different HTML element) with the oc-row-v1 class, use the
<oc-row-v2> tag.
Here's a table mapping deprecated CSS classes to their corresponding replacement attributes in the new version:
| CSS class (v1) | Attribute (v2) | Notes |
|---|---|---|
oc-row-v1--hide-divider |
hide-divider |
No change |
oc-row-v1--selected |
selected |
No change |
The oc-row-v1--interactive class does not need a corresponding attribute.
Use the as-button or href attributes as you would on any other component, and the row will become interactive automatically.
Refer to the section Migrate an interactive row for more details.
Migrate a basic row
To migrate a basic row, replace the container element <div> using the oc-link-v1 class with the new <oc-row-v2> element.
<!-- From: -->
<div class="oc-row-v1">Row content</div>
<!-- To: -->
<oc-row-v2>Row content</oc-row-v2>
Migrate an interactive row
For interactive rows using an anchor tag <a>, replace the anchor tag with <oc-row-v2>,
remove the deprecated CSS classes, and keep the href attribute.
<!-- From: -->
<a class="oc-row-v1 oc-row-v1--interactive" href="#">Label</a>
<!-- To: -->
<oc-row-v2>
<a href="#">My Link</a>
Label
</oc-row-v2>
For interactive rows using a click handler on a button tag <button>, replace the button tag by <oc-row-v2>, remove the deprecated CSS classes, and set the as-button attribute.
<!-- From: -->
<button class="oc-row-v1 oc-row-v1--interactive">Label</button>
<!-- To: -->
<oc-row-v2 as-button>Label</oc-row-v2>
Migrate a row with icons
The new oc-row-v2 component natively supports displaying icons on the left, right, or both sides of the row.
Story Container with icons:
<oc-row-v2 as-button icon-left="smiley-positive" icon-right="arrow-right">Label</oc-row-v2>
Consider migrating to the built-in positioning styles.
As shown below, place the label of the row in the default slot, and use the icon-left and icon-right to set your icons:
<oc-row-v2 icon-left="smiley-positive" icon-right="arrow-right">
<a href="#">My Link</a>
Label
</oc-row-v2>
Migrate a row with an image
The oc-row-v2 component natively supports displaying an image to the left, optionally with an icon to the right.
Story Image and icon:
<oc-row-v2 variant="image" as-button icon-right="arrow-right">
<oc-placeholder-v1 slot="image" variant="image" border-radius="4px" width="40" height="40"></oc-placeholder-v1>
Label
</oc-row-v2>
Consider migrating to the built-in positioning styles.
As shown below, set the variant attribute to the value image, place the image in the image slot, and use the icon-right attribute to set the icon:
<oc-row-v2 variant="image" icon-right="arrow-right">
<img slot="image" src="https://www.example.com" alt="Product image" />
<a href="#">My Link</a>
Label
</oc-row-v2>
Migrate list views
The oc-row-v2 component natively supports list views.
Story List view demo:
<div class="oc-block-v1">
<oc-row-v2 variant="headline">Details</oc-row-v2>
<ul>
<li>
<oc-row-v2 variant="two-columns">
<span slot="column-label">Funktionen</span>
<span slot="column-text">3D-Audio<br />Mikrofon integriert</span>
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="two-columns">
<span slot="column-label">Sensoren</span>
<span slot="column-text">Magnetometer</span>
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="two-columns">
<span slot="column-label">Bedienelemente</span>
<span slot="column-text">Stick<br />Tasten<br />Touch Plus Controller</span>
</oc-row-v2>
</li>
</ul>
</div>
For the headline of the list view, use the headline variant:
<oc-row-v2 variant="headline">Headline</oc-row-v2>
For the rows of the list view, use the two-columns variant. Put the label into the column-label slot,
and the text content into the column-text slot.
Important
Do not use
<dl>,<dd>and<dt>elements; they are used internally, and repeating them results in redundancy.
<oc-row-v2 variant="two-columns">
<span slot="column-label">Label</span>
<span slot="column-text">Text content</span>
</oc-row-v2>
API v2
Source: ./src/components/row/v2/RowV2.API.g.mdx
Row v2 API
API: <oc-row-v2> (RowV2)
The row component provides a flexible row layout with multiple variants, including label, image, headline, and two-columns. It supports interactive features such as clickable rows, selectable states, and customizable icons and images.
Attributes / properties
| Attribute | Type | Default | Required | Description |
|---|---|---|---|---|
variant |
"container" | "image" | "headline" | "two-columns" |
"container" |
no | Specifies which row layout variant to use. Can be one of: container, image, headline, two-columns. |
headline-level |
1 | 2 | 3 | 4 | 5 | 6 |
undefined |
no | If set, renders the headline content inside a heading tag with the specified level. Only applies to variant headline.The heading level has no visual effect but provides semantic structure for screen readers. If not set, renders a div instead of a heading tag. |
icon-left |
icon name (428 values; see Icon list in `storybook/components/icon/README.md`) |
no | Sets an icon that shows on the left side of the row. Only applicable to variant container. |
|
icon-right |
icon name (428 values; see Icon list in `storybook/components/icon/README.md`) |
no | Sets an icon that shows on the right side of the row. Only applicable to variants container and image. |
|
hide-divider |
boolean |
false |
no | When set to true, hides the divider line at the top of the row. |
selected |
boolean |
false |
no | When set to true, displays the row with a blue background, indicating that it is selected. |
href |
string |
undefined |
no | Deprecated: Use an a tag in the default slot instead.Visit SEO optimization techniques for more information. |
base64-href |
string |
undefined |
no | The same as href, except base64-encoded. This is used to mask links in the markup. |
target |
"_blank" | "_self" | "_parent" | "_top" |
undefined |
no | Determines the target of the link when the row is clicked. Note Only applies when href or base64-href is set. |
rel |
string |
undefined |
no | Sets the rel attribute to determine the relationship between the current document and the linked document.Note Only applies when href or base64-href is set. |
as-button |
boolean |
undefined |
no | When set, this row becomes interactive, and clicking it will trigger a listenable event. |
oc-aria-label |
string |
undefined |
no | Sets the ARIA label when the row is interactive. This property should be used when the text content of the row is not enough to deduce its interaction, and should contain a description of that interaction. |
oc-aria-expanded |
boolean |
undefined |
no | Sets the ARIA expanded property for usage as a header in an Accordion for example. This should only be used if the row works as a button and reveals more content on interaction. |
Slots
| Slot | Required | Description |
|---|---|---|
default |
no | Sets the main content of the row. Only applicable to variants container, image, and headline. |
column-label |
no | Sets the content of the label column on the left. Only applicable to variant two-columns.Example: <span slot="column-label">Label</span> |
column-text |
no | Sets the content of the text column on the right. Only applicable to variant two-columns.Example: <span slot="column-text">Label</span> |
image |
no | Sets the image that is shown on the left side of the row. Only applicable to variant image.Example: <img slot="column-text" src="https://example.com" alt="Some image"> |
primary-action |
no | Add an empty tag to change the default behavior of the row component. - empty a tag: the card component behaves as a link (SEO relevant) |
Events
| Event | Detail type | Description |
|---|---|---|
oc-property-change |
OcRowV2Events["oc-property-change"] |
Whenever a property value changes, this event triggers. Use this event to track all property changes within the component. Refer to the Events documentation for more information. |
oc-mount |
{ component: string; } |
Fired when the component is mounted to the DOM. The event is fired when the onMount hook of the component is called by the runtime. |
oc-unmount |
{ component: string; } |
Fired when the component is unmounted from the DOM. The event is fired when the function returned by the onMount hook of the component is called by the runtime. |
CSS custom properties
| Custom property | Default | Description |
|---|---|---|
--custom-spacing-x |
undefined |
Sets the custom horizontal spacing of the row content. |
--custom-spacing-y |
undefined |
Sets the custom vertical spacing of the row content. |
--align-items |
flex-start |
Changes the item alignment in the row. Use center (vertical aligned) or flex-end (aligned to bottom) to overwrite the default |
Variations (v2)
Source: ./src/components/row/v2/Variations.mdx
Variations
Listed below are the most common variations of the Row component as well as specific component variations for different use cases.
You can explore all available options using the component configurator, adjust the component to your needs, and see the changes live in a preview canvas.
Default
Story: components-row-variations--default · tags: components, row, v1
The default configuration of the row component.
<oc-row-v2><oc-placeholder-v1>PLACEHOLDER</oc-placeholder-v1></oc-row-v2>
Hidden divider
Story: components-row-variations--hide-divider · tags: components, row, v1
Variation with the hide-divider attribute, hiding the top divider.
Args: hide-divider=true
<oc-row-v2 hide-divider><oc-placeholder-v1>PLACEHOLDER</oc-placeholder-v1></oc-row-v2>
With button behavior
Story: components-row-variations--with-button-behavior · tags: components, row, v1
Variation with the as-button attribute, making it focusable, and giving it hover and active styles.
Args: as-button=true
<oc-row-v2 as-button><oc-placeholder-v1>PLACEHOLDER</oc-placeholder-v1></oc-row-v2>
With link behavior
Story: components-row-variations--with-link-behavior · tags: components, row, v1
The row component with a link as primary action. Search engines will detect the href.
Args: primaryActionSlot=(see snippet)
<oc-row-v2>
<!--The <a> tag should be placed inside the light DOM to improve SEO.--><a href="#" slot="primary-action" aria-label="placeholder link"></a>
<oc-placeholder-v1>PLACEHOLDER</oc-placeholder-v1>
</oc-row-v2>
With masked link behavior
Story: components-row-variations--with-masked-link-behavior · tags: components, row, v1
The row component as a masked link. Search engines will not detect the href.
Args: base64-href=Iw==
<oc-row-v2 base64-href="Iw=="><oc-placeholder-v1>PLACEHOLDER</oc-placeholder-v1></oc-row-v2>
With link switch behavior
Story: components-row-variations--with-link-switch-behavior · tags: components, row, v1
The row component as a link with switch behavior. Search engines will detect the href, while users receive the Base64-encoded version.
Args: base64-href=Iz92YXJpYW50PWZvbw==, primaryActionSlot=(see snippet)
<oc-row-v2 base64-href="Iz92YXJpYW50PWZvbw==">
<!--Search engines will detect the href, while users receive the Base64-encoded version.--><a href='#' slot="primary-action" aria-label='Row'></a>
<oc-placeholder-v1>PLACEHOLDER</oc-placeholder-v1>
</oc-row-v2>
Selected
Story: components-row-variations--interactive-selected · tags: components, row, v1
An interactive row with the selected attribute, changing the background color to blue.
Args: as-button=true, selected=true
<oc-row-v2 selected as-button><oc-placeholder-v1>PLACEHOLDER</oc-placeholder-v1></oc-row-v2>
Container with icons
Story: components-row-variations--container-icons · tags: components, row, v1
The container variant with icons to the left and right.
Args: as-button=true, defaultSlot=Label, icon-left=smiley-positive, icon-right=arrow-right
<oc-row-v2 as-button icon-left="smiley-positive" icon-right="arrow-right">Label</oc-row-v2>
Image and icon
Story: components-row-variations--image · tags: components, row, v1
The image variant with an image to the left and an icon to the right.
Args: variant=image, as-button=true, defaultSlot=Label, imageSlot=<oc-placeholder-v1 slot="image" variant="image" border-radius="4px" width="40" height="40"></oc-placeholder-v1>, icon-right=arrow-right
<oc-row-v2 variant="image" as-button icon-right="arrow-right">
<oc-placeholder-v1 slot="image" variant="image" border-radius="4px" width="40" height="40"></oc-placeholder-v1>
Label
</oc-row-v2>
Headline
Story: components-row-variations--headline · tags: components, row, v1
The headline variant is for use at the top of a list of stacked rows.
Args: variant=headline, defaultSlot=Headline
<oc-row-v2 variant="headline">Headline</oc-row-v2>
Two columns
Story: components-row-variations--two-columns · tags: components, row, v1
The two-columns variant displays a label column and a text column.
Args: variant=two-columns, columnLabelSlot=<oc-placeholder-v1 slot="column-label" style="height: 4rem">PLACEHOLDER</oc-placeholder-v1>, columnTextSlot=<oc-placeholder-v1 slot="column-text" style="height: 4rem">PLACEHOLDER</oc-placeholder-v1>
<oc-row-v2 variant="two-columns">
<oc-placeholder-v1 slot="column-label" style="height: 4rem">PLACEHOLDER</oc-placeholder-v1>
<oc-placeholder-v1 slot="column-text" style="height: 4rem">PLACEHOLDER</oc-placeholder-v1>
<oc-placeholder-v1>PLACEHOLDER</oc-placeholder-v1>
</oc-row-v2>
Navigation demo
Story: components-row-variations--demo-navigation · tags: components, row, v1
A list of interactive rows with arrow icons, one of which is selected.
<ul class="oc-block-v1">
<li>
<oc-row-v2 as-button icon-right="arrow-right" selected>Label</oc-row-v2>
</li>
<li>
<oc-row-v2 as-button icon-right="arrow-right">Label</oc-row-v2>
</li>
<li>
<oc-row-v2 as-button icon-right="arrow-right">Label</oc-row-v2>
</li>
<li>
<oc-row-v2 as-button icon-right="arrow-right">Label</oc-row-v2>
</li>
<li>
<oc-row-v2 as-button icon-right="arrow-right">Label</oc-row-v2>
</li>
<li>
<oc-row-v2 as-button icon-right="arrow-right">Label</oc-row-v2>
</li>
</ul>
Story source (TypeScript, verbatim from Storybook)
{
name: "Navigation demo",
parameters: {
controls: {
disabled: true
},
backgrounds: {
value: "frame"
}
},
render: () => {
return html`
<ul class="oc-block-v1">
<li>
<oc-row-v2 as-button icon-right="arrow-right" selected>Label</oc-row-v2>
</li>
<li>
<oc-row-v2 as-button icon-right="arrow-right">Label</oc-row-v2>
</li>
<li>
<oc-row-v2 as-button icon-right="arrow-right">Label</oc-row-v2>
</li>
<li>
<oc-row-v2 as-button icon-right="arrow-right">Label</oc-row-v2>
</li>
<li>
<oc-row-v2 as-button icon-right="arrow-right">Label</oc-row-v2>
</li>
<li>
<oc-row-v2 as-button icon-right="arrow-right">Label</oc-row-v2>
</li>
</ul>
`;
},
argTypes: hideControlsBadge(Metadata)
}
Interactive list demo
Story: components-row-variations--demo-interactive-list-with-images · tags: components, row, v1
A list of interactive rows with images and arrow icons, one of which is selected.
<ul class="oc-block-v1">
<li>
<oc-row-v2 variant="image" as-button selected>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="image" as-button>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="image" as-button>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="image" as-button>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="image" as-button>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="image" as-button>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
</ul>
Story source (TypeScript, verbatim from Storybook)
{
name: "Interactive list demo",
parameters: {
controls: {
disabled: true
},
backgrounds: {
value: "frame"
}
},
render: () => {
return html`
<ul class="oc-block-v1">
<li>
<oc-row-v2 variant="image" as-button selected>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="image" as-button>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="image" as-button>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="image" as-button>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="image" as-button>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="image" as-button>
<oc-placeholder-v1
slot="image"
variant="image"
border-radius="4px"
width="40"
height="40"
></oc-placeholder-v1>
<oc-icon-v1 slot="icon-right" type="arrow-right" size="100"></oc-icon-v1>
Label
</oc-row-v2>
</li>
</ul>
`;
},
argTypes: hideControlsBadge(Metadata)
}
List view demo
Story: components-row-variations--demo-list-view · tags: components, row, v1
A list of basic rows containing a custom layout.
<div class="oc-block-v1">
<oc-row-v2 variant="headline">Details</oc-row-v2>
<ul>
<li>
<oc-row-v2 variant="two-columns">
<span slot="column-label">Funktionen</span>
<span slot="column-text">3D-Audio<br />Mikrofon integriert</span>
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="two-columns">
<span slot="column-label">Sensoren</span>
<span slot="column-text">Magnetometer</span>
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="two-columns">
<span slot="column-label">Bedienelemente</span>
<span slot="column-text">Stick<br />Tasten<br />Touch Plus Controller</span>
</oc-row-v2>
</li>
</ul>
</div>
Story source (TypeScript, verbatim from Storybook)
{
name: "List view demo",
parameters: {
controls: {
disabled: true
},
backgrounds: {
value: "frame"
}
},
render: () => {
return html`
<div class="oc-block-v1">
<oc-row-v2 variant="headline">Details</oc-row-v2>
<ul>
<li>
<oc-row-v2 variant="two-columns">
<span slot="column-label">Funktionen</span>
<span slot="column-text">3D-Audio<br />Mikrofon integriert</span>
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="two-columns">
<span slot="column-label">Sensoren</span>
<span slot="column-text">Magnetometer</span>
</oc-row-v2>
</li>
<li>
<oc-row-v2 variant="two-columns">
<span slot="column-label">Bedienelemente</span>
<span slot="column-text">Stick<br />Tasten<br />Touch Plus Controller</span>
</oc-row-v2>
</li>
</ul>
</div>
`;
},
argTypes: hideControlsBadge(Metadata)
}
Custom spacings demo
Story: components-row-variations--demo-custom-spacings · tags: components, row, v1
A list of basic rows containing a custom layout with adjustable sliders for custom spacings.
<div
style="display: flex; border: 1px solid var(--oc-base-color-gray-200); border-radius: 8px; width: fit-content; "
>
<oc-row-v2>
<oc-placeholder-v1 style="width: 200px">PLACEHOLDER</oc-placeholder-v1>
</oc-row-v2>
</div>
<div style="display: flex; flex-direction: column; gap: 16px; margin-top: 32px;">
<div style="display: flex; gap: 16px; align-items: center;">
<label for="horizontal-slider">Horizontal Spacing</label>
<input
type="range"
name="horizontal-slider"
id="horizontal-slider"
min="0"
max="64"
value="0"
/>
<span id="horizontal-slider-value">0px</span>
</div>
<div style="display: flex; gap: 16px; align-items: center;">
<label for="vertical-slider">Vertical Spacing</label>
<input
type="range"
name="vertical-slider"
id="vertical-slider"
min="0"
max="64"
value="16"
/>
<span id="vertical-slider-value">16px</span>
</div>
</div>
<script>
(() => {
const row = document.querySelector("oc-row-v2");
const horizontalSlider = document.getElementById("horizontal-slider");
const horizontalSliderValue = document.getElementById("horizontal-slider-value");
const verticalSlider = document.getElementById("vertical-slider");
const verticalSliderValue = document.getElementById("vertical-slider-value");
horizontalSlider.addEventListener("input", (event) => {
const value = event.target.value + "px";
row.style.setProperty("--custom-spacing-x", value);
horizontalSliderValue.textContent = value;
});
verticalSlider.addEventListener("input", (event) => {
const value = event.target.value + "px";
row.style.setProperty("--custom-spacing-y", value);
verticalSliderValue.textContent = value;
});
})();
</script>
Story source (TypeScript, verbatim from Storybook)
{
name: "Custom spacings demo",
parameters: {
controls: {
disabled: true
},
backgrounds: {
value: "frame"
},
chromatic: {
hideInChromatic: true
}
},
render: () => {
return html`
<div
style="display: flex; border: 1px solid var(--oc-base-color-gray-200); border-radius: 8px; width: fit-content; "
>
<oc-row-v2>
<oc-placeholder-v1 style="width: 200px">PLACEHOLDER</oc-placeholder-v1>
</oc-row-v2>
</div>
<div style="display: flex; flex-direction: column; gap: 16px; margin-top: 32px;">
<div style="display: flex; gap: 16px; align-items: center;">
<label for="horizontal-slider">Horizontal Spacing</label>
<input
type="range"
name="horizontal-slider"
id="horizontal-slider"
min="0"
max="64"
value="0"
/>
<span id="horizontal-slider-value">0px</span>
</div>
<div style="display: flex; gap: 16px; align-items: center;">
<label for="vertical-slider">Vertical Spacing</label>
<input
type="range"
name="vertical-slider"
id="vertical-slider"
min="0"
max="64"
value="16"
/>
<span id="vertical-slider-value">16px</span>
</div>
</div>
<script>
(() => {
const row = document.querySelector("oc-row-v2");
const horizontalSlider = document.getElementById("horizontal-slider");
const horizontalSliderValue = document.getElementById("horizontal-slider-value");
const verticalSlider = document.getElementById("vertical-slider");
const verticalSliderValue = document.getElementById("vertical-slider-value");
horizontalSlider.addEventListener("input", (event) => {
const value = event.target.value + "px";
row.style.setProperty("--custom-spacing-x", value);
horizontalSliderValue.textContent = value;
});
verticalSlider.addEventListener("input", (event) => {
const value = event.target.value + "px";
row.style.setProperty("--custom-spacing-y", value);
verticalSliderValue.textContent = value;
});
})();
</script>
`;
},
argTypes: hideControlsBadge(Metadata)
}