@fluentui/web-components 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/CHANGELOG.json +69 -1
  2. package/CHANGELOG.md +38 -2
  3. package/dist/dts/anchor/anchor.stories.d.ts +1 -1
  4. package/dist/dts/badge/badge.stories.d.ts +1 -1
  5. package/dist/dts/button/button.stories.d.ts +1 -1
  6. package/dist/dts/component-definitions.d.ts +2 -1
  7. package/dist/dts/custom-elements.d.ts +14 -12
  8. package/dist/dts/index.d.ts +1 -0
  9. package/dist/dts/listbox/index.d.ts +3 -6
  10. package/dist/dts/listbox/listbox.stories.d.ts +1 -1
  11. package/dist/dts/menu/menu.stories.d.ts +1 -1
  12. package/dist/dts/search/index.d.ts +38 -0
  13. package/dist/dts/search/search.stories.d.ts +75 -0
  14. package/dist/dts/search/search.styles.d.ts +4 -0
  15. package/dist/dts/search/search.template.d.ts +6 -0
  16. package/dist/dts/text-area/text-area.stories.d.ts +1 -1
  17. package/dist/dts/text-field/text-field.stories.d.ts +1 -1
  18. package/dist/dts/tooltip/tooltip.stories.d.ts +1 -1
  19. package/dist/esm/accordion/accordion-item/accordion-item.styles.js +6 -5
  20. package/dist/esm/component-definitions.js +2 -0
  21. package/dist/esm/custom-elements.js +3 -1
  22. package/dist/esm/flipper/flipper.styles.js +1 -0
  23. package/dist/esm/index.js +1 -0
  24. package/dist/esm/listbox/index.js +3 -6
  25. package/dist/esm/search/index.js +52 -0
  26. package/dist/esm/search/search.stories.js +83 -0
  27. package/dist/esm/search/search.styles.js +108 -0
  28. package/dist/esm/search/search.template.js +82 -0
  29. package/dist/esm/search/search.vscode.definition.json +145 -0
  30. package/dist/esm/tabs/tabs.stories.js +56 -2
  31. package/dist/esm/tabs/tabs.styles.js +1 -0
  32. package/dist/fluent-web-components.api.json +280 -15
  33. package/dist/web-components.d.ts +51 -2
  34. package/dist/web-components.js +711 -245
  35. package/dist/web-components.min.js +142 -132
  36. package/docs/api-report.md +34 -9
  37. package/package.json +2 -3
@@ -0,0 +1,52 @@
1
+ import { __decorate } from "tslib";
2
+ import { attr } from '@microsoft/fast-element';
3
+ import { Search as FoundationSearch } from '@microsoft/fast-foundation';
4
+ import { searchTemplate as template } from './search.template';
5
+ import { searchStyles as styles } from './search.styles';
6
+ /**
7
+ * The Fluent search class
8
+ * @internal
9
+ */
10
+ export class Search extends FoundationSearch {
11
+ constructor() {
12
+ super(...arguments);
13
+ /**
14
+ * The appearance of the element.
15
+ *
16
+ * @public
17
+ * @remarks
18
+ * HTML Attribute: appearance
19
+ */
20
+ this.appearance = 'outline';
21
+ }
22
+ }
23
+ __decorate([
24
+ attr
25
+ ], Search.prototype, "appearance", void 0);
26
+ /**
27
+ * The Fluent Search Custom Element. Implements {@link @microsoft/fast-foundation#Search},
28
+ * {@link @microsoft/fast-foundation#searchTemplate}
29
+ *
30
+ *
31
+ * @public
32
+ * @remarks
33
+ * HTML Element: \<fluent-search\>
34
+ *
35
+ * {@link https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/delegatesFocus | delegatesFocus}
36
+ */
37
+ export const fluentSearch = Search.compose({
38
+ baseName: 'search',
39
+ baseClass: FoundationSearch,
40
+ template,
41
+ styles,
42
+ start: `<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg%22%3E"><path d="M8.5 3a5.5 5.5 0 0 1 4.23 9.02l4.12 4.13a.5.5 0 0 1-.63.76l-.07-.06-4.13-4.12A5.5 5.5 0 1 1 8.5 3Zm0 1a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9Z"/></svg>`,
43
+ shadowOptions: {
44
+ delegatesFocus: true,
45
+ },
46
+ });
47
+ export * from './search.template';
48
+ /**
49
+ * Styles for Search
50
+ * @public
51
+ */
52
+ export const searchStyles = styles;
@@ -0,0 +1,83 @@
1
+ import { fluentSearch } from './index';
2
+ export default {
3
+ title: 'Components/Search',
4
+ component: fluentSearch,
5
+ argTypes: {
6
+ appearance: {
7
+ options: ['filled', 'outline'],
8
+ defaultValue: 'outline',
9
+ control: { type: 'radio' },
10
+ },
11
+ autoFocus: {
12
+ description: 'Automatically focuses the control',
13
+ control: { type: 'boolean' },
14
+ },
15
+ disabled: {
16
+ description: 'The search box should be submitted with the form but should not be editable',
17
+ control: { type: 'boolean' },
18
+ },
19
+ list: {
20
+ control: { type: 'text' },
21
+ },
22
+ maxlength: {
23
+ control: { type: 'number' },
24
+ },
25
+ name: {
26
+ control: { type: 'text' },
27
+ },
28
+ minlength: {
29
+ control: { type: 'number' },
30
+ },
31
+ pattern: {
32
+ description: `A regular expression the input's contents must match in order to be valid`,
33
+ control: { type: 'text' },
34
+ },
35
+ placeholder: {
36
+ description: 'An exemplar value to display in the input field whenever it is empty',
37
+ defaultValue: 'Placeholder',
38
+ control: { type: 'text' },
39
+ },
40
+ readonly: {
41
+ control: { type: 'boolean' },
42
+ },
43
+ required: {
44
+ control: { type: 'boolean' },
45
+ },
46
+ spellcheck: {
47
+ control: { type: 'boolean' },
48
+ },
49
+ },
50
+ };
51
+ const SearchTemplate = ({ appearance, autoFocus, disabled, list, maxlength, name, minlength, pattern, placeholder, readonly, required, size, spellcheck, }) => `<fluent-search
52
+ ${appearance ? `appearance="${appearance}"` : ''}
53
+ ${autoFocus ? 'autofocus' : ''}
54
+ ${disabled ? 'disabled' : ''}
55
+ ${list ? `list="${list}"` : ''}
56
+ ${maxlength ? `maxlength="${maxlength}"` : ''}
57
+ ${name ? `name="${name}"` : ''}
58
+ ${minlength ? `minlength="${minlength}"` : ''}
59
+ ${pattern ? `pattern="${pattern}"` : ''}
60
+ ${placeholder ? `placeholder="${placeholder}"` : ''}
61
+ ${readonly ? 'readonly' : ''}
62
+ ${required ? 'required' : ''}
63
+ ${spellcheck ? `spellcheck="${spellcheck}"` : ''}
64
+ ${size ? `size="${size}"` : ''}
65
+ ></fluent-search>`;
66
+ export const Search = SearchTemplate.bind({});
67
+ Search.args = {
68
+ placeholder: 'placeholder',
69
+ autoFocus: false,
70
+ disabled: false,
71
+ readonly: false,
72
+ required: false,
73
+ };
74
+ const example = `
75
+ <fluent-search appearance="outline"></fluent-search>
76
+ `;
77
+ Search.parameters = {
78
+ docs: {
79
+ source: {
80
+ code: example,
81
+ },
82
+ },
83
+ };
@@ -0,0 +1,108 @@
1
+ import { css } from '@microsoft/fast-element';
2
+ import { Button, DesignToken, display, forcedColorsStylesheetBehavior, } from '@microsoft/fast-foundation';
3
+ import { heightNumber, inputFilledForcedColorStyles, inputFilledStyles, inputForcedColorStyles, inputStateStyles, inputStyles, } from '../styles';
4
+ import { appearanceBehavior } from '../utilities/behaviors';
5
+ import { bodyFont, controlCornerRadius, density, designUnit, neutralFillInputRecipe, neutralFillStealthRecipe, neutralForegroundRest, typeRampBaseFontSize, typeRampBaseLineHeight } from '../design-tokens';
6
+ const clearButtonHover = DesignToken.create("clear-button-hover").withDefault((target) => {
7
+ const buttonRecipe = neutralFillStealthRecipe.getValueFor(target);
8
+ const inputRecipe = neutralFillInputRecipe.getValueFor(target);
9
+ return buttonRecipe.evaluate(target, inputRecipe.evaluate(target).focus).hover;
10
+ });
11
+ const clearButtonActive = DesignToken.create("clear-button-active").withDefault((target) => {
12
+ const buttonRecipe = neutralFillStealthRecipe.getValueFor(target);
13
+ const inputRecipe = neutralFillInputRecipe.getValueFor(target);
14
+ return buttonRecipe.evaluate(target, inputRecipe.evaluate(target).focus).active;
15
+ });
16
+ export const searchFilledStyles = (context, definition) => css `
17
+ ${inputFilledStyles(context, definition, '.root')}
18
+ `.withBehaviors(forcedColorsStylesheetBehavior(css `
19
+ ${inputFilledForcedColorStyles(context, definition, '.root')}
20
+ `));
21
+ export const searchStyles = (context, definition) => css `
22
+ ${display('inline-block')}
23
+ ${inputStyles(context, definition, '.root')}
24
+ ${inputStateStyles(context, definition, '.root')}
25
+ .root {
26
+ display: flex;
27
+ flex-direction: row;
28
+ }
29
+ .control {
30
+ -webkit-appearance: none;
31
+ color: inherit;
32
+ background: transparent;
33
+ border: 0;
34
+ height: calc(100% - 4px);
35
+ margin-top: auto;
36
+ margin-bottom: auto;
37
+ padding: 0 calc(${designUnit} * 2px + 1px);
38
+ font-family: inherit;
39
+ font-size: inherit;
40
+ line-height: inherit;
41
+ }
42
+ .clear-button {
43
+ display: inline-flex;
44
+ align-items: center;
45
+ margin: 1px;
46
+ height: calc(100% - 2px);
47
+ opacity: 0;
48
+ background: transparent;
49
+ color: ${neutralForegroundRest};
50
+ fill: currentcolor;
51
+ border: none;
52
+ border-radius: calc(${controlCornerRadius} * 1px);
53
+ min-width: calc(${heightNumber} * 1px);
54
+ font-size: ${typeRampBaseFontSize};
55
+ line-height: ${typeRampBaseLineHeight};
56
+ outline: none;
57
+ font-family: ${bodyFont};
58
+ padding: 0 calc((10 + (${designUnit} * 2 * ${density})) * 1px);
59
+ }
60
+ .clear-button:hover {
61
+ background: ${clearButtonHover};
62
+ }
63
+ .clear-button:active {
64
+ background: ${clearButtonActive};
65
+ }
66
+ :host(:hover:not([disabled], [readOnly])) .clear-button,
67
+ :host(:active:not([disabled], [readOnly])) .clear-button,
68
+ :host(:focus-within:not([disabled], [readOnly])) .clear-button {
69
+ opacity: 1;
70
+ }
71
+ :host(:hover:not([disabled], [readOnly])) .clear-button__hidden,
72
+ :host(:active:not([disabled], [readOnly])) .clear-button__hidden,
73
+ :host(:focus-within:not([disabled], [readOnly])) .clear-button__hidden {
74
+ opacity: 0;
75
+ }
76
+ .control::-webkit-search-cancel-button {
77
+ -webkit-appearance: none;
78
+ }
79
+ .input-wrapper {
80
+ display: flex;
81
+ position: relative;
82
+ width: 100%;
83
+ }
84
+ .start,
85
+ .end {
86
+ display: flex;
87
+ margin: 1px;
88
+ align-items: center;
89
+ }
90
+ .start {
91
+ display: flex;
92
+ margin-inline-start: 11px;
93
+ }
94
+ ::slotted([slot="end"]) {
95
+ height: 100%
96
+ }
97
+ .clear-button__hidden {
98
+ opacity: 0;
99
+ }
100
+ .end {
101
+ margin-inline-end: 11px;
102
+ }
103
+ ::slotted(${context.tagFor(Button)}) {
104
+ margin-inline-end: 1px;
105
+ }
106
+ `.withBehaviors(appearanceBehavior('filled', searchFilledStyles(context, definition)), forcedColorsStylesheetBehavior(css `
107
+ ${inputForcedColorStyles(context, definition, '.root')}
108
+ `));
@@ -0,0 +1,82 @@
1
+ import { html, ref, slotted } from '@microsoft/fast-element';
2
+ import { endSlotTemplate, startSlotTemplate, whitespaceFilter, } from '@microsoft/fast-foundation';
3
+ /**
4
+ * @public
5
+ */
6
+ export const searchTemplate = (context, definition) => html `
7
+ <template
8
+ class="
9
+ ${x => (x.readOnly ? 'readonly' : '')}
10
+ "
11
+ >
12
+ <label
13
+ part="label"
14
+ for="control"
15
+ class="${x => (x.defaultSlottedNodes && x.defaultSlottedNodes.length ? 'label' : 'label label__hidden')}"
16
+ >
17
+ <slot ${slotted({ property: 'defaultSlottedNodes', filter: whitespaceFilter })}></slot>
18
+ </label>
19
+ <div class="root" part="root" ${ref('root')}>
20
+ ${startSlotTemplate(context, definition)}
21
+ <div class="input-wrapper" part="input-wrapper">
22
+ <input
23
+ class="control"
24
+ part="control"
25
+ id="control"
26
+ @input="${x => x.handleTextInput()}"
27
+ @change="${x => x.handleChange()}"
28
+ ?autofocus="${x => x.autofocus}"
29
+ ?disabled="${x => x.disabled}"
30
+ list="${x => x.list}"
31
+ maxlength="${x => x.maxlength}"
32
+ minlength="${x => x.minlength}"
33
+ pattern="${x => x.pattern}"
34
+ placeholder="${x => x.placeholder}"
35
+ ?readonly="${x => x.readOnly}"
36
+ ?required="${x => x.required}"
37
+ size="${x => x.size}"
38
+ ?spellcheck="${x => x.spellcheck}"
39
+ :value="${x => x.value}"
40
+ type="search"
41
+ aria-atomic="${x => x.ariaAtomic}"
42
+ aria-busy="${x => x.ariaBusy}"
43
+ aria-controls="${x => x.ariaControls}"
44
+ aria-current="${x => x.ariaCurrent}"
45
+ aria-describedby="${x => x.ariaDescribedby}"
46
+ aria-details="${x => x.ariaDetails}"
47
+ aria-disabled="${x => x.ariaDisabled}"
48
+ aria-errormessage="${x => x.ariaErrormessage}"
49
+ aria-flowto="${x => x.ariaFlowto}"
50
+ aria-haspopup="${x => x.ariaHaspopup}"
51
+ aria-hidden="${x => x.ariaHidden}"
52
+ aria-invalid="${x => x.ariaInvalid}"
53
+ aria-keyshortcuts="${x => x.ariaKeyshortcuts}"
54
+ aria-label="${x => x.ariaLabel}"
55
+ aria-labelledby="${x => x.ariaLabelledby}"
56
+ aria-live="${x => x.ariaLive}"
57
+ aria-owns="${x => x.ariaOwns}"
58
+ aria-relevant="${x => x.ariaRelevant}"
59
+ aria-roledescription="${x => x.ariaRoledescription}"
60
+ ${ref('control')}
61
+ />
62
+ <slot name="clear-button">
63
+ <button
64
+ class="clear-button ${x => (x.value ? '' : 'clear-button__hidden')}"
65
+ part="clear-button"
66
+ tabindex="-1"
67
+ @click=${x => x.handleClearInput()}
68
+ >
69
+ <slot name="clear-glyph">
70
+ <svg width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
71
+ <path
72
+ d="m2.09 2.22.06-.07a.5.5 0 0 1 .63-.06l.07.06L6 5.29l3.15-3.14a.5.5 0 1 1 .7.7L6.71 6l3.14 3.15c.18.17.2.44.06.63l-.06.07a.5.5 0 0 1-.63.06l-.07-.06L6 6.71 2.85 9.85a.5.5 0 0 1-.7-.7L5.29 6 2.15 2.85a.5.5 0 0 1-.06-.63l.06-.07-.06.07Z"
73
+ />
74
+ </svg>
75
+ </slot>
76
+ </button>
77
+ </slot>
78
+ </div>
79
+ ${endSlotTemplate(context, definition)}
80
+ </div>
81
+ </template>
82
+ `;
@@ -0,0 +1,145 @@
1
+ {
2
+ "version": 1.1,
3
+ "tags": [
4
+ {
5
+ "name": "fluent-search",
6
+ "title": "Search",
7
+ "description": "The Fluent UI search element",
8
+ "attributes": [
9
+ {
10
+ "name": "value",
11
+ "title": "Value",
12
+ "description": "The HTML value attribute of the search",
13
+ "required": false,
14
+ "type": "string"
15
+ },
16
+ {
17
+ "name": "appearance",
18
+ "title": "Appearance",
19
+ "description": "The field's visual treatment",
20
+ "default": "outline",
21
+ "values": [{ "name": "outline" }, { "name": "filled" }],
22
+ "type": "string",
23
+ "required": false
24
+ },
25
+ {
26
+ "name": "autofocus",
27
+ "title": "Autofocus",
28
+ "description": "Determines if the element should receive document focus on page load",
29
+ "required": false,
30
+ "type": "boolean",
31
+ "default": false
32
+ },
33
+ {
34
+ "name": "placeholder",
35
+ "title": "Placeholder",
36
+ "description": "Sets the placeholder value of the element, generally used to provide a hint to the user",
37
+ "required": false,
38
+ "type": "string"
39
+ },
40
+ {
41
+ "name": "list",
42
+ "title": "List ID",
43
+ "description": "Allows associating a datalist to the component",
44
+ "required": false,
45
+ "type": "string",
46
+ "default": ""
47
+ },
48
+ {
49
+ "name": "maxlength",
50
+ "title": "Maximum length",
51
+ "description": "The maximum number of characters a user can enter",
52
+ "required": false,
53
+ "type": "number"
54
+ },
55
+ {
56
+ "name": "minlength",
57
+ "title": "Minimum length",
58
+ "description": "The minimum number of characters a user can enter",
59
+ "required": false,
60
+ "type": "number"
61
+ },
62
+ {
63
+ "name": "pattern",
64
+ "title": "Validation pattern",
65
+ "description": "A regular expression that the value must match to pass validation",
66
+ "required": false,
67
+ "type": "string"
68
+ },
69
+ {
70
+ "name": "size",
71
+ "title": "Size",
72
+ "description": "Sets the width of the element to a specified number of characters",
73
+ "required": false,
74
+ "type": "number"
75
+ },
76
+ {
77
+ "name": "spellcheck",
78
+ "title": "Spellcheck",
79
+ "description": "Controls whether or not to enable spell checking for the input field, or if the default spell checking configuration should be used",
80
+ "required": false,
81
+ "type": "boolean"
82
+ },
83
+ {
84
+ "name": "name",
85
+ "title": "Name",
86
+ "description": "This element's value will be surfaced during form submission under the provided name",
87
+ "type": "string",
88
+ "default": "",
89
+ "required": false
90
+ },
91
+ {
92
+ "name": "required",
93
+ "title": "Required",
94
+ "description": "Require the field to be completed prior to form submission",
95
+ "type": "boolean",
96
+ "default": false,
97
+ "required": false
98
+ },
99
+ {
100
+ "name": "disabled",
101
+ "title": "Disabled",
102
+ "description": "Sets the disabled state of the field",
103
+ "type": "boolean",
104
+ "default": false,
105
+ "required": false
106
+ },
107
+ {
108
+ "name": "readonly",
109
+ "title": "Readonly",
110
+ "description": "When true, the control will be immutable by user interaction",
111
+ "type": "boolean",
112
+ "default": false,
113
+ "required": false
114
+ }
115
+ ],
116
+ "slots": [
117
+ {
118
+ "name": "",
119
+ "title": "Default slot",
120
+ "description": "The content of the field represents its visual label"
121
+ },
122
+ {
123
+ "name": "start",
124
+ "title": "Start slot",
125
+ "description": "Contents of the start slot are positioned before the input area"
126
+ },
127
+ {
128
+ "name": "end",
129
+ "title": "End slot",
130
+ "description": "Contents of the end slot are positioned after the input area"
131
+ },
132
+ {
133
+ "name": "clear-button",
134
+ "title": "Clear button slot",
135
+ "description": "Contents of the clear button slot are positioned after the content and is what clears the value when a value is set"
136
+ },
137
+ {
138
+ "name": "clear-glyph",
139
+ "title": "Clear glyph slot",
140
+ "description": "Contents of the clear button"
141
+ }
142
+ ]
143
+ }
144
+ ]
145
+ }
@@ -21,9 +21,63 @@ const TabsTemplate = ({ activeId, activeIndicator, orientation }) => `
21
21
  <fluent-tab id="TabOne">Tab one</fluent-tab>
22
22
  <fluent-tab id="TabTwo">Tab two</fluent-tab>
23
23
  <fluent-tab id="TabThree">Tab three</fluent-tab>
24
- <fluent-tab-panel> Tab one content. This is for testing. </fluent-tab-panel>
24
+ <fluent-tab-panel>
25
+ Tab one content. This is for testing. Tab three content. This is for testing.
26
+ <br />
27
+ Tab one content. This is for testing.
28
+ <br />
29
+ Tab one content. This is for testing.
30
+ <br />
31
+ Tab one content. This is for testing.
32
+ <br />
33
+ Tab one content. This is for testing.
34
+ <br />
35
+ Tab one content. This is for testing.
36
+ <br />
37
+ Tab one content. This is for testing.
38
+ <br />
39
+ Tab one content. This is for testing.
40
+ <br />
41
+ Tab one content. This is for testing.
42
+ <br />
43
+ Tab one content. This is for testing.
44
+ <br />
45
+ Tab one content. This is for testing.
46
+ <br />
47
+ Tab one content. This is for testing.
48
+ <br />
49
+ Tab one content. This is for testing.
50
+ <br />
51
+ </fluent-tab-panel>
25
52
  <fluent-tab-panel> Tab two content. This is for testing. </fluent-tab-panel>
26
- <fluent-tab-panel> Tab three content. This is for testing. </fluent-tab-panel>
53
+ <fluent-tab-panel>
54
+ Tab three content. This is for testing. Tab three content. This is for testing.
55
+ <br />
56
+ Tab three content. This is for testing.
57
+ <br />
58
+ Tab three content. This is for testing.
59
+ <br />
60
+ Tab three content. This is for testing.
61
+ <br />
62
+ Tab three content. This is for testing.
63
+ <br />
64
+ Tab three content. This is for testing.
65
+ <br />
66
+ Tab three content. This is for testing.
67
+ <br />
68
+ Tab three content. This is for testing.
69
+ <br />
70
+ Tab three content. This is for testing.
71
+ <br />
72
+ Tab three content. This is for testing.
73
+ <br />
74
+ Tab three content. This is for testing.
75
+ <br />
76
+ Tab three content. This is for testing.
77
+ <br />
78
+ Tab three content. This is for testing.
79
+ <br />
80
+ </fluent-tab-panel>
27
81
  </fluent-tabs>`;
28
82
  export const Tabs = TabsTemplate.bind({});
29
83
  Tabs.args = {
@@ -63,6 +63,7 @@ export const tabsStyles = (context, definition) => css `
63
63
  position: relative;
64
64
  width: max-content;
65
65
  justify-self: end;
66
+ align-self: flex-start;
66
67
  width: 100%;
67
68
  }
68
69