Skip to content

Commit

Permalink
Adds Divider web component (#26901)
Browse files Browse the repository at this point in the history
* Adds Divider component

* Generates change
  • Loading branch information
halerankin authored and radium-v committed May 2, 2024
1 parent 39bf1ee commit 150afea
Show file tree
Hide file tree
Showing 11 changed files with 402 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "feat(divider): Add divider web component",
"packageName": "@fluentui/web-components",
"email": "harankin@microsoft.com",
"dependentChangeType": "patch"
}
4 changes: 4 additions & 0 deletions packages/web-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
"types": "./dist/esm/counter-badge/define.d.ts",
"default": "./dist/esm/counter-badge/define.js"
},
"./divider": {
"types": "./dist/esm/divider/define.d.ts",
"default": "./dist/esm/divider/define.js"
},
"./image": {
"types": "./dist/esm/image/define.d.ts",
"default": "./dist/esm/image/define.js"
Expand Down
4 changes: 4 additions & 0 deletions packages/web-components/src/divider/define.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { FluentDesignSystem } from '../fluent-design-system.js';
import { definition } from './divider.definition.js';

definition.define(FluentDesignSystem.registry);
17 changes: 17 additions & 0 deletions packages/web-components/src/divider/divider.definition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FluentDesignSystem } from '../fluent-design-system.js';
import { Divider } from './divider.js';
import { template } from './divider.template.js';
import { styles } from './divider.styles.js';

/**
* The Fluent Divider Element
*
* @public
* @remarks
* HTML Element: \<fluent-divider\>
*/
export const definition = Divider.compose({
name: `${FluentDesignSystem.prefix}-divider`,
template,
styles,
});
46 changes: 46 additions & 0 deletions packages/web-components/src/divider/divider.options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { DividerOrientation, DividerRole, ValuesOf } from '@microsoft/fast-foundation';

/**
* Fast Foundation DividerRole property
* @public
*/
export { DividerRole };

/**
* Fast Foundation Orientation property
* @public
*/
export { DividerOrientation };

/**
* Align content within divider
* @public
*/
export const DividerAlignContent = {
center: 'center',
start: 'start',
end: 'end',
} as const;

/**
* The types for DividerAlignContent
* @public
*/
export type DividerAlignContent = ValuesOf<typeof DividerAlignContent>;

/**
* DividerAppearance - divider color defined by a design token alias.
* @public
*/
export const DividerAppearance = {
strong: 'strong',
brand: 'brand',
subtle: 'subtle',
default: 'default',
} as const;

/**
* The types for Appearance
* @public
*/
export type DividerAppearance = ValuesOf<typeof DividerAppearance>;
147 changes: 147 additions & 0 deletions packages/web-components/src/divider/divider.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { html } from '@microsoft/fast-element';
import type { Args, Meta } from '@storybook/html';
import { renderComponent } from '../helpers.stories.js';
import type { Divider as FluentDivider } from './divider.js';
import { DividerAlignContent, DividerAppearance, DividerOrientation, DividerRole } from './divider.options.js';
import './define.js';

type DividerStoryArgs = Args & FluentDivider;
type DividerStoryMeta = Meta<DividerStoryArgs>;

const dividerTemplate = html<DividerStoryArgs>`
<div style="border: 30px solid #ccc; height: 9em; display: flex; flex-direction: column; justify-content: center;">
<fluent-divider
align-content=${x => x.alignContent}
appearance=${x => x.appearance}
role=${x => x.role}
?inset=${x => x.inset}
orientation=${x => x.orientation}
>
${x => (x.content ? html`<h3>${x.content}</h3>` : '')}
</fluent-divider>
</div>
`;

const dividerSvgTemplate = html<DividerStoryArgs>`
<div style="border: 30px solid #ccc; height: 9em; display: flex; flex-direction: column; justify-content: center;">
<fluent-divider align-content="start" appearance="brand" role="presentation">
<svg width="20px" height="20px" viewBox="0 0 32 33" xmlns="http://www.w3.org/2000/svg">
<path
d="M13 22.0312C13 21.479 12.5523 21.0312 12 21.0312C11.4477 21.0312 11 21.479 11 22.0312V25.0312C11 25.5835 11.4477 26.0312 12 26.0312C12.5523 26.0312 13 25.5835 13 25.0312V22.0312ZM16 15.0312C16.5523 15.0312 17 15.479 17 16.0312V25.0312C17 25.5835 16.5523 26.0312 16 26.0312C15.4477 26.0312 15 25.5835 15 25.0312V16.0312C15 15.479 15.4477 15.0312 16 15.0312ZM21 19.0312C21 18.479 20.5523 18.0312 20 18.0312C19.4477 18.0312 19 18.479 19 19.0312V25.0312C19 25.5835 19.4477 26.0312 20 26.0312C20.5523 26.0312 21 25.5835 21 25.0312V19.0312ZM5 5.03125C5 3.3744 6.34315 2.03125 8 2.03125H18.1716C18.9672 2.03125 19.7303 2.34732 20.2929 2.90993L26.1213 8.73836C26.6839 9.30097 27 10.064 27 10.8597V27.0312C27 28.6881 25.6569 30.0312 24 30.0312H8C6.34315 30.0312 5 28.6881 5 27.0312V5.03125ZM8 4.03125C7.44772 4.03125 7 4.47897 7 5.03125V27.0312C7 27.5835 7.44772 28.0312 8 28.0312H24C24.5523 28.0312 25 27.5835 25 27.0312V12.0312H20C18.3431 12.0312 17 10.6881 17 9.03125V4.03125H8ZM20 10.0312H24.5858L19 4.44546V9.03125C19 9.58353 19.4477 10.0312 20 10.0312Z"
fill="currentColor"
/>
</svg>
</fluent-divider>
</div>
`;

const dividerSvgVerticalTemplate = html<DividerStoryArgs>`
<fluent-divider role=${x => x.role} ?inset=${x => x.inset} orientation="vertical">
<svg width="20px" height="20px" viewBox="0 0 32 33" xmlns="http://www.w3.org/2000/svg">
<path
d="M13 22.0312C13 21.479 12.5523 21.0312 12 21.0312C11.4477 21.0312 11 21.479 11 22.0312V25.0312C11 25.5835 11.4477 26.0312 12 26.0312C12.5523 26.0312 13 25.5835 13 25.0312V22.0312ZM16 15.0312C16.5523 15.0312 17 15.479 17 16.0312V25.0312C17 25.5835 16.5523 26.0312 16 26.0312C15.4477 26.0312 15 25.5835 15 25.0312V16.0312C15 15.479 15.4477 15.0312 16 15.0312ZM21 19.0312C21 18.479 20.5523 18.0312 20 18.0312C19.4477 18.0312 19 18.479 19 19.0312V25.0312C19 25.5835 19.4477 26.0312 20 26.0312C20.5523 26.0312 21 25.5835 21 25.0312V19.0312ZM5 5.03125C5 3.3744 6.34315 2.03125 8 2.03125H18.1716C18.9672 2.03125 19.7303 2.34732 20.2929 2.90993L26.1213 8.73836C26.6839 9.30097 27 10.064 27 10.8597V27.0312C27 28.6881 25.6569 30.0312 24 30.0312H8C6.34315 30.0312 5 28.6881 5 27.0312V5.03125ZM8 4.03125C7.44772 4.03125 7 4.47897 7 5.03125V27.0312C7 27.5835 7.44772 28.0312 8 28.0312H24C24.5523 28.0312 25 27.5835 25 27.0312V12.0312H20C18.3431 12.0312 17 10.6881 17 9.03125V4.03125H8ZM20 10.0312H24.5858L19 4.44546V9.03125C19 9.58353 19.4477 10.0312 20 10.0312Z"
fill="currentColor"
/>
</svg>
</fluent-divider>
`;

export default {
title: 'Components/Divider',
args: {
content: 'Section One',
alignContent: undefined,
appearance: undefined,
role: DividerRole.separator,
inset: false,
orientation: undefined,
},
argTypes: {
content: {
description: 'HTML element wrapping text (e.g. `<h3>Section One</h3>`), Image or SVG',
table: {
defaultValue: {
summary: 'empty',
},
},
},
alignContent: {
description: 'Align content',
table: {
type: {
summary: 'Fluent v9. Determines the alignment of the content within the divider.',
},
defaultValue: {
summary: 'undefined',
},
},
options: Object.values(DividerAlignContent),
control: {
type: 'select',
},
},
appearance: {
description: 'Divider and text colors',
table: {
type: {
summary: 'Fluent v9. A divider can have one of the preset appearances.',
},
defaultValue: {
summary: 'undefined',
},
},
options: Object.values(DividerAppearance),
control: {
type: 'select',
},
},
role: {
description: 'Set role attribute',
table: {
type: {
summary: 'Inherited from FASTDivider. Aria role for the divider.',
},
defaultValue: {
summary: 'separator',
},
},
options: Object.values(DividerRole),
control: {
type: 'select',
},
},
inset: {
description: 'Pad the ends of divider',
table: {
type: {
summary:
'Type: boolean. Fluent v9. Divider layout is block for strict distinctions between items, or inset for closer relationships with neighboring content.',
},
defaultValue: {
summary: false,
},
},
control: 'boolean',
},
orientation: {
description: 'Divider layout',
table: {
type: {
summary:
'Inherited from FASTDivider. Layout can be horizontal or vertical. Adds aria-orientation to component.',
},
defaultValue: {
summary: undefined,
},
},
options: Object.values(DividerOrientation),
control: {
type: 'select',
},
},
},
} as DividerStoryMeta;

export const Divider = renderComponent(dividerTemplate).bind({});
export const DividerWithSvg = renderComponent(dividerSvgTemplate).bind({});
export const VerticalDividerWithSvg = renderComponent(dividerSvgVerticalTemplate).bind({});
124 changes: 124 additions & 0 deletions packages/web-components/src/divider/divider.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { css } from '@microsoft/fast-element';
import { display } from '@microsoft/fast-foundation';
import {
colorBrandForeground1,
colorBrandStroke1,
colorNeutralForeground1,
colorNeutralForeground2,
colorNeutralForeground3,
colorNeutralStroke1,
colorNeutralStroke2,
colorNeutralStroke3,
fontFamilyBase,
fontSizeBase200,
fontWeightRegular,
strokeWidthThin,
} from '../theme/design-tokens.js';

/** Divider styles
* @public
*/
export const styles = css`
${display('flex')}
:host::after,
:host::before {
align-self: center;
background: ${colorNeutralStroke2};
box-sizing: border-box;
content: '';
display: flex;
flex-grow: 1;
height: ${strokeWidthThin};
}
:host([inset]) {
padding: 0 12px;
}
:host ::slotted(*) {
color: ${colorNeutralForeground2};
font-family: ${fontFamilyBase};
font-size: ${fontSizeBase200};
font-weight: ${fontWeightRegular};
margin: 0;
padding: 0 12px;
}
:host([align-content='start'])::before,
:host([align-content='end'])::after {
flex-basis: 12px;
flex-grow: 0;
flex-shrink: 0;
}
:host([orientation='vertical']) {
height: 100%;
min-height: 84px;
}
:host([orientation='vertical']):empty {
min-height: 20px;
}
:host([orientation='vertical']) {
flex-direction: column;
align-items: center;
}
:host([orientation='vertical'][inset])::before {
margin-top: 12px;
}
:host([orientation='vertical'][inset])::after {
margin-bottom: 12px;
}
:host([orientation='vertical']):empty::before,
:host([orientation='vertical']):empty::after {
height: 10px;
min-height: 10px;
flex-grow: 0;
}
:host([orientation='vertical'])::before,
:host([orientation='vertical'])::after {
width: ${strokeWidthThin};
min-height: 20px;
height: 100%;
}
:host([orientation='vertical']) ::slotted(*) {
display: flex;
flex-direction: column;
padding: 12px 0;
line-height: 20px;
}
:host([orientation='vertical'][align-content='start'])::before {
min-height: 8px;
}
:host([orientation='vertical'][align-content='end'])::after {
min-height: 8px;
}
:host([appearance='strong'])::before,
:host([appearance='strong'])::after {
background: ${colorNeutralStroke1};
}
:host([appearance='strong']) ::slotted(*) {
color: ${colorNeutralForeground1};
}
:host([appearance='brand'])::before,
:host([appearance='brand'])::after {
background: ${colorBrandStroke1};
}
:host([appearance='brand']) ::slotted(*) {
color: ${colorBrandForeground1};
}
:host([appearance='subtle'])::before,
:host([appearance='subtle'])::after {
background: ${colorNeutralStroke3};
}
:host([appearance='subtle']) ::slotted(*) {
color: ${colorNeutralForeground3};
}
`;
9 changes: 9 additions & 0 deletions packages/web-components/src/divider/divider.template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ElementViewTemplate } from '@microsoft/fast-element';
import { dividerTemplate } from '@microsoft/fast-foundation';
import type { Divider } from './divider.js';

/**
* Template for the Divider component
* @public
*/
export const template: ElementViewTemplate<Divider> = dividerTemplate();
Loading

0 comments on commit 150afea

Please sign in to comment.