Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds Label as a new web component #27344

Merged
merged 45 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
0107ff2
label init
brianchristopherbrady Feb 10, 2023
8913910
Merge branch 'web-components-v3' into user/brianbrady/label
brianchristopherbrady Feb 16, 2023
6f0cf27
merge web-components-v3
brianchristopherbrady Feb 16, 2023
8896c7b
updates readme
brianchristopherbrady Feb 16, 2023
560d292
updates styles
brianchristopherbrady Feb 16, 2023
2afbf01
adds label styles
brianchristopherbrady Feb 16, 2023
d25354c
removes dead import
brianchristopherbrady Feb 16, 2023
fe5c09c
divides accordion and accordion item readme
brianchristopherbrady Feb 21, 2023
8f52208
updates label docs
brianchristopherbrady Feb 23, 2023
08de7d1
Merge branch 'web-components-v3' of https://github.com/microsoft/flue…
brianchristopherbrady Feb 23, 2023
8255212
Merge branch 'web-components-v3' of https://github.com/microsoft/flue…
brianchristopherbrady Feb 27, 2023
7c54b52
merge
brianchristopherbrady Mar 2, 2023
4a0d4ef
updates label template
brianchristopherbrady Mar 15, 2023
5844949
Merge branch 'web-components-v3' of https://github.com/microsoft/flue…
brianchristopherbrady Mar 21, 2023
2c9bfc1
Merge branch 'web-components-v3' of https://github.com/microsoft/flue…
brianchristopherbrady Mar 27, 2023
595ac88
updates label template and styles
brianchristopherbrady Mar 27, 2023
35b54cc
updates label stories
brianchristopherbrady Mar 27, 2023
dc28a96
label updates per review
brianchristopherbrady Mar 27, 2023
f39d6c1
removes attr decorator on label
brianchristopherbrady Mar 27, 2023
8d43dcf
label: yarn change
brianchristopherbrady Mar 27, 2023
9df4097
radio: updates attribute story names
brianchristopherbrady Mar 27, 2023
7674f05
merge
brianchristopherbrady Mar 27, 2023
13aa25e
label: removes attribute binding on template
brianchristopherbrady Mar 27, 2023
14e74ab
label: removes template tag
brianchristopherbrady Mar 28, 2023
c2ff69b
label: updates per review
brianchristopherbrady Mar 28, 2023
1702192
Merge branch 'web-components-v3' into user/brianbrady/label
brianchristopherbrady Mar 28, 2023
ec67398
label: adds export to root json
brianchristopherbrady Mar 28, 2023
bc99492
adds disabled attr
brianchristopherbrady Mar 28, 2023
1a34439
removes dead code
brianchristopherbrady Mar 28, 2023
d5c7b44
Merge branch 'user/brianbrady/label' of https://github.com/microsoft/…
brianchristopherbrady Mar 28, 2023
2946183
Merge branch 'web-components-v3' of https://github.com/microsoft/flue…
brianchristopherbrady Mar 29, 2023
9b7d93e
Update change/@fluentui-web-components-2b95d12e-1c42-47e8-88da-aa67da…
brianchristopherbrady Mar 31, 2023
e7b2c10
Merge branch 'web-components-v3' of https://github.com/microsoft/flue…
brianchristopherbrady Mar 31, 2023
c64032e
Merge branch 'web-components-v3' into user/brianbrady/label
brianchristopherbrady Mar 31, 2023
d785ad8
label: removes dead import, updates storybook args to use consts
brianchristopherbrady Mar 31, 2023
15ee475
label: removes dead imports
brianchristopherbrady Mar 31, 2023
b02ecee
label: updates asterisk styling
brianchristopherbrady Mar 31, 2023
ba44f5f
label:docs: enumerates rendered element API difs between FUIRv9 and F…
brianchristopherbrady Mar 31, 2023
ab11029
Merge branch 'user/brianbrady/label' of https://github.com/microsoft/…
brianchristopherbrady Mar 31, 2023
1eec0ce
label: updates docs
brianchristopherbrady Mar 31, 2023
bd03b34
label: fixes mispelling in docs
brianchristopherbrady Mar 31, 2023
298c155
label: updates template, docs
brianchristopherbrady Mar 31, 2023
b18a259
label: updates docs
brianchristopherbrady Mar 31, 2023
ecb836c
label: replaces arg values with label options const
brianchristopherbrady Mar 31, 2023
3da8c8b
Merge branch 'web-components-v3' into user/brianbrady/label
brianchristopherbrady Apr 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "feat(label): adds Label as a new web component",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"comment": "feat(label): adds Label as a new web component",
"comment": "feat(label): add label as a new web component",

"packageName": "@fluentui/web-components",
"email": "brianbrady@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 @@ -56,6 +56,10 @@
"types": "./dist/esm/image/define.d.ts",
"default": "./dist/esm/image/define.js"
},
"./label": {
"types": "./dist/esm/label/define.d.ts",
"default": "./dist/esm/label/define.js"
},
"./menu-button": {
"types": "./dist/esm/menu-button/define.d.ts",
"default": "./dist/esm/menu-button/define.js"
Expand Down
1 change: 1 addition & 0 deletions packages/web-components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './button/index.js';
export * from './counter-badge/index.js';
export * from './divider/index.js';
export * from './image/index.js';
export * from './label/index.js';
export * from './menu-button/index.js';
export * from './progress-bar/index.js';
export * from './slider/index.js';
Expand Down
123 changes: 123 additions & 0 deletions packages/web-components/src/label/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Label

> A label represents a caption for an item in a user interface.
<br />

## **Design Spec**

[Link to Label Design Spec in Figma](https://www.figma.com/file/jpWO2FMBefirTyThf5Rg2P/Label?node-id=2%3A476&t=QCdofuTbXkUjMS4d-0)

<br />

## **Engineering Spec**

<br />

The fluent-label has several visual font size (small, medium, large) and font weight(regular, semibold) options. The fluent-label also provides appearances for required and disabled states.

<br />

_Note about form association_

In web components, when using the shadow DOM, it's not feasible to associate elements across the shadow DOM boundary using the traditional `for` attribute, since the shadow DOM creates a boundary that prevents the label element from accessing the input element's id attribute. Instead, the WC3 Label component uses the `aria-labelledby` attribute to associate the label element with the input element. This attribute has a value that matches the id of another element on the page, which serves as a label for the input element.

<br />

### Use Case

Creating a simple label element with an optional info icon and optional required state

<br />

## Class: `Label`

<br />

### **Variables**

<br />

### **Fields**

| Name | Privacy | Type | Default | Description |
| ---------- | ------- | ------------------------------ | ----------- | ------------------------------------ |
| `required` | public | `boolean` | `false` | Specifies required styling for label |
| `disabled` | public | `boolean` | `false` | Sets disabled state for label |
| `size` | public | `"small"` `"medium"` `"large"` | `"medium"` | Specifies font size for label |
| `weight` | public | `"regular"` `"semibold"` | `"regular"` | Specifies font weight for label |

<br />

### **Methods**

<br />

### **Events**

<br />

### **Attributes**

| Name | Field |
| ---------- | -------- |
| `required` | required |
| `disabled` | disabled |
| `size` | size |
| `weight` | weight |

<br />

### **Slots**

| Name | Description |
| ---- | -------------------------------------- |
| | Default slotted content for label text |

<br />

### **Template**

```html
<slot></slot> <span part="asterisk" class="asterisk" ?hidden="${x => !x.required}">*</span>
```

## **Accessibility**

[W3 Label Spec](https://www.w3.org/WAI/tutorials/forms/labels/)

<br />

### **WAI-ARIA Roles, States, and Properties**

<br />

- [`aria-labelledby`](https://www.w3.org/TR/wai-aria-1.2/#aria-labelledby)

<br />
<hr />
<br />

## **Preparation**

<br />

### **Fluent Web Component v3 v.s Fluent React 9**

<br />

**Component and Slot Mapping**

| Fluent UI React 9 | Fluent Web Components 3 |
| ----------------- | ----------------------- |
| `<Label>` | `<fluent-label>` |

<br />

**Additional Deltas**
| | Fluent UI React 9 | Fluent Web Components 3 |
|---------------------| --------------------------------------------------------------------------------------- |---------------------------------------------------------------------------------------- |
| Renders | `HTMLLabelElement` | `HTMLElement` |
| API | [`HTMLLabelElement` Spec](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement) | [`HTMLElement` Spec](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement) |
| Shadow DOM | n/a | uses Shadow DOM |
| Accessibility | Uses `for` attribute to associate with form elements | Uses `aria-labelledby` to associate with form elements, does not have a `for` attribute |
4 changes: 4 additions & 0 deletions packages/web-components/src/label/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 './label.definition.js';

definition.define(FluentDesignSystem.registry);
4 changes: 4 additions & 0 deletions packages/web-components/src/label/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './label.js';
export { definition as LabelDefinition } from './label.definition.js';
export { styles as LabelStyles } from './label.styles.js';
export { template as LabelTemplate } from './label.template.js';
18 changes: 18 additions & 0 deletions packages/web-components/src/label/label.definition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { FluentDesignSystem } from '../fluent-design-system.js';
import { Label } from './label.js';
import { styles } from './label.styles.js';
import { template } from './label.template.js';

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

/**
* A Labels font size can be small, medium, or large
*/
export const LabelSize = {
small: 'small',
medium: 'medium',
large: 'large',
} as const;

/**
* Applies font size to label
* @public
*/
export type LabelSize = ValuesOf<typeof LabelSize>;

/**
* A label can have a font weight of regular or strong
*/
export const LabelWeight = {
regular: 'regular',
semibold: 'semibold',
} as const;

/**
* Applies font weight to label
* @public
*/
export type LabelWeight = ValuesOf<typeof LabelWeight>;
93 changes: 93 additions & 0 deletions packages/web-components/src/label/label.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { html } from '@microsoft/fast-element';
import type { Args, Meta } from '@storybook/html';
import { renderComponent } from '../helpers.stories.js';
import type { Label as FluentLabel } from './label.js';
import './define.js';
import { LabelSize, LabelWeight } from './label.options.js';

type LabelStoryArgs = Args & FluentLabel;
type LabelStoryMeta = Meta<LabelStoryArgs>;

const storyTemplate = html<LabelStoryArgs>`
<fluent-label
weight="${x => x.weight}"
size="${x => x.size}"
?required="${x => x.required}"
?disabled="${x => x.disabled}"
>Label</fluent-label
>
`;

export default {
title: 'Components/Label',
args: {
required: false,
size: LabelSize.medium,
weight: LabelWeight.regular,
},
argTypes: {
required: {
description: 'Sets required field styling',
table: {
defaultValue: { summary: false },
},
control: {
type: 'boolean',
},
defaultValue: false,
},
disabled: {
description: 'Sets disabled styling',
table: {
defaultValue: { summary: false },
},
control: {
type: 'boolean',
},
defaultValue: false,
},
size: {
description: 'Sets label font size',
table: {
defaultValue: { summary: LabelSize.medium },
},
control: {
type: 'select',
options: Object.values(LabelSize),
},
defaultValue: LabelSize.medium,
},
weight: {
description: 'Sets label font weight',
table: {
defaultValue: { summary: LabelWeight.regular },
},
control: {
type: 'select',
options: Object.values(LabelWeight),
},
defaultValue: LabelWeight.regular,
},
},
} as LabelStoryMeta;

export const Label = renderComponent(storyTemplate).bind({});

export const Size = renderComponent(html<LabelStoryArgs>`
<div style="display: flex; flex-direction: row; justify-content: space-around; align-items: center; gap: 10px;">
<fluent-label size="small">Small Label</fluent-label>
<fluent-label size="medium">Medium Label</fluent-label>
<fluent-label size="large">Large Label</fluent-label>
</div>
`);

export const Weight = renderComponent(html<LabelStoryArgs>`
<div style="display: flex; flex-direction: row; justify-content: space-around; align-items: center; gap: 10px;">
<fluent-label weight="regular">Regular Label</fluent-label>
<fluent-label weight="semibold">Semibold Label</fluent-label>
</div>
`);

export const Required = renderComponent(html<LabelStoryArgs>` <fluent-label required>Required Label</fluent-label> `);

export const Disabled = renderComponent(html<LabelStoryArgs>` <fluent-label disabled>Disabled Label</fluent-label> `);
52 changes: 52 additions & 0 deletions packages/web-components/src/label/label.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { css } from '@microsoft/fast-element';
import { display } from '@microsoft/fast-foundation';
import {
colorNeutralForeground1,
colorNeutralForegroundDisabled,
colorPaletteRedForeground1,
fontFamilyBase,
fontSizeBase200,
fontSizeBase300,
fontSizeBase400,
fontWeightRegular,
fontWeightSemibold,
lineHeightBase200,
lineHeightBase300,
lineHeightBase400,
spacingHorizontalXS,
} from '../theme/design-tokens.js';

/** Label styles
* @public
*/
export const styles = css`
${display('flex')}
:host {
font-family: ${fontFamilyBase};
font-size: ${fontSizeBase300};
line-height: ${lineHeightBase300};
font-weight: ${fontWeightRegular};
color: ${colorNeutralForeground1};
}
.asterisk {
color: ${colorPaletteRedForeground1};
margin-left: ${spacingHorizontalXS};
}
:host([size='small']) {
font-size: ${fontSizeBase200};
line-height: ${lineHeightBase200};
}
:host([size='large']) {
font-size: ${fontSizeBase400};
line-height: ${lineHeightBase400};
font-weight: ${fontWeightSemibold};
}
:host([weight='semibold']) {
font-weight: ${fontWeightSemibold};
}
chrisdholt marked this conversation as resolved.
Show resolved Hide resolved
:host([disabled]),
:host([disabled]) .asterisk {
color: ${colorNeutralForegroundDisabled};
}
`;
15 changes: 15 additions & 0 deletions packages/web-components/src/label/label.template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ElementViewTemplate, html } from '@microsoft/fast-element';
import { Label } from './label.js';

/**
* The template for the Fluent label web-component.
* @public
*/
export function labelTemplate<T extends Label>(): ElementViewTemplate<T> {
return html<T>`
<slot></slot>
<span part="asterisk" class="asterisk" ?hidden="${x => !x.required}">*</span>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for me to learn - is it better to use hidden attribute than conditionally rendering the span?

`;
}

export const template: ElementViewTemplate<Label> = labelTemplate();
Loading