@brightspace-ui/core 2.1.2 → 2.2.1
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.
- package/README.md +1 -0
- package/components/filter/README.md +19 -0
- package/components/filter/filter.js +1 -1
- package/components/tag-list/README.md +52 -0
- package/components/tag-list/demo/tag-list.html +32 -0
- package/components/tag-list/tag-list-item-mixin.js +78 -0
- package/components/tag-list/tag-list-item.js +21 -0
- package/components/tag-list/tag-list.js +89 -0
- package/custom-elements.json +65 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,6 +54,7 @@ npm install @brightspace-ui/core
|
|
|
54
54
|
* [Switch](components/switch/): switch component with on/off semantics
|
|
55
55
|
* [Table](components/table/): table styles, column sorting and overflow handling
|
|
56
56
|
* [Tabs](components/tabs/): tab and tab-panel components
|
|
57
|
+
* [Tag List](components/tag-list/): tag-list and tag-list-item components
|
|
57
58
|
* [Tooltip](components/tooltip/): tooltip components
|
|
58
59
|
* [Typography](components/typography/): typography styles and components
|
|
59
60
|
* [Validation](components/validation/): plugin custom validation logic to native and custom form elements
|
|
@@ -131,6 +131,25 @@ Filter with a single dimension:
|
|
|
131
131
|
</div>
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
+
### Iterating Over Dimensions and Values
|
|
135
|
+
|
|
136
|
+
Lit tries to reuse DOM nodes when it can to help with performance, but in this case we don't want unique dimensions and values to be reused - otherwise we can't detect additions/removals properly.
|
|
137
|
+
|
|
138
|
+
If you are going to be constructing your dimensions and/or dimension values by iterating over an array or object (using `forEach,` , `map`, etc.), you'll want to use the [Lit `repeat` directive with a `KeyFn` set](https://lit.dev/docs/templates/directives/#repeat) instead to tell Lit not to reuse a DOM node if the `key` has changed:
|
|
139
|
+
```js
|
|
140
|
+
import { repeat } from 'lit-html/directives/repeat.js';
|
|
141
|
+
...
|
|
142
|
+
return html`<d2l-filter>
|
|
143
|
+
${repeat(this._dimensions, (dim) => dim.key, dim => html`
|
|
144
|
+
<d2l-filter-dimension-set key="${dim.key}" text=${dim.text}>
|
|
145
|
+
${repeat(dim._values, (value) => value.key, value => html`
|
|
146
|
+
<d2l-filter-dimension-set-value key="${value.kay}" text="${value.text}" ?selected="${value.selected}"></d2l-filter-dimension-set-value>
|
|
147
|
+
`)}
|
|
148
|
+
</d2l-filter-dimension-set>
|
|
149
|
+
`)}
|
|
150
|
+
</d2l-filter>`;
|
|
151
|
+
```
|
|
152
|
+
|
|
134
153
|
### Accessibility
|
|
135
154
|
The filter will announce changes to filter selections, search results, and when filters are being cleared. It is up to the consumer to then announce when these changes have propagated and resulted in new/loaded/updated data on the page. This is very important for screenreader users who are not able to visually see the page changing behind the filter control as selections are made.
|
|
136
155
|
|
|
@@ -506,7 +506,7 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
|
|
|
506
506
|
const changes = e.detail.changes;
|
|
507
507
|
const dimension = this._dimensions.find(dimension => dimension.key === e.detail.dimensionKey);
|
|
508
508
|
const value = e.detail.valueKey && dimension.values.find(value => value.key === e.detail.valueKey);
|
|
509
|
-
const toUpdate =
|
|
509
|
+
const toUpdate = e.detail.valueKey ? value : dimension;
|
|
510
510
|
|
|
511
511
|
if (!toUpdate) return;
|
|
512
512
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
# Tag List
|
|
3
|
+
*This component is in progress and the api is not yet stable.*
|
|
4
|
+
|
|
5
|
+
Tag lists are used to present a list of compact, discrete pieces of information.
|
|
6
|
+
|
|
7
|
+
<!-- docs: demo display:block -->
|
|
8
|
+
```html
|
|
9
|
+
<script type="module">
|
|
10
|
+
import '@brightspace-ui/core/components/tag-list/tag-list.js';
|
|
11
|
+
import '@brightspace-ui/core/components/tag-list/tag-list-item.js';
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<d2l-tag-list description="Example Tags">
|
|
15
|
+
<d2l-tag-list-item text="Tag"></d2l-tag-list-item>
|
|
16
|
+
<d2l-tag-list-item text="Another Tag"></d2l-tag-list-item>
|
|
17
|
+
<d2l-tag-list-item text="A Third Very Very Very Long Tag"></d2l-tag-list-item>
|
|
18
|
+
</d2l-tag-list>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Tag List [d2l-tag-list]
|
|
22
|
+
|
|
23
|
+
The `d2l-tag-list` element can take a combination of any type of `d2l-tag-list-item` and adds the appropriate keyboard navigation, list semantics, clearing behaviour and responsive behaviour.
|
|
24
|
+
|
|
25
|
+
<!-- docs: demo live name:d2l-tag-list display:block -->
|
|
26
|
+
```html
|
|
27
|
+
<script type="module">
|
|
28
|
+
import '@brightspace-ui/core/components/tag-list/tag-list.js';
|
|
29
|
+
import '@brightspace-ui/core/components/tag-list/tag-list-item.js';
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<d2l-tag-list description="Example Tags">
|
|
33
|
+
<d2l-tag-list-item text="Tag"></d2l-tag-list-item>
|
|
34
|
+
<d2l-tag-list-item text="Another Tag"></d2l-tag-list-item>
|
|
35
|
+
<d2l-tag-list-item text="A Third Very Very Very Long Tag"></d2l-tag-list-item>
|
|
36
|
+
</d2l-tag-list>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Tag List Item [d2l-tag-list-item]
|
|
40
|
+
The `d2l-tag-list-item` provides the appropriate `listitem` semantics and styling for children within a tag list. Tag List items do not work outside of a Tag List and should not be used on their own.
|
|
41
|
+
|
|
42
|
+
<!-- docs: demo live name:d2l-tag-list-item display:block -->
|
|
43
|
+
```html
|
|
44
|
+
<script type="module">
|
|
45
|
+
import '@brightspace-ui/core/components/tag-list/tag-list.js';
|
|
46
|
+
import '@brightspace-ui/core/components/tag-list/tag-list-item.js';
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<d2l-tag-list description="Example Tags">
|
|
50
|
+
<d2l-tag-list-item text="Tag"></d2l-tag-list-item>
|
|
51
|
+
</d2l-tag-list>
|
|
52
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<link rel="stylesheet" href="../../demo/styles.css" type="text/css">
|
|
7
|
+
<script type="module">
|
|
8
|
+
import '../../demo/demo-page.js';
|
|
9
|
+
import '../tag-list.js';
|
|
10
|
+
import '../tag-list-item.js';
|
|
11
|
+
import '../test/tag-list-item-mixin-consumer.js';
|
|
12
|
+
</script>
|
|
13
|
+
</head>
|
|
14
|
+
<body unresolved>
|
|
15
|
+
<d2l-demo-page page-title="d2l-tag-list">
|
|
16
|
+
|
|
17
|
+
<h2>Basic Tag List</h2>
|
|
18
|
+
<d2l-demo-snippet fullscreen>
|
|
19
|
+
<d2l-tag-list description="A bunch of example tags">
|
|
20
|
+
<d2l-tag-list-item text="Example Tag"></d2l-tag-list-item>
|
|
21
|
+
<d2l-tag-list-item text="Longer Example Tag - much much much much much longer"></d2l-tag-list-item>
|
|
22
|
+
<d2l-tag-list-item text="Another Example Tag"></d2l-tag-list-item>
|
|
23
|
+
<d2l-tag-list-item-mixin-consumer name="Custom Tag List Item"></d2l-tag-list-item-mixin-consumer>
|
|
24
|
+
<d2l-tag-list-item text="Example Tag 5"></d2l-tag-list-item>
|
|
25
|
+
<d2l-tag-list-item text="Example Tag 6"></d2l-tag-list-item>
|
|
26
|
+
<d2l-tag-list-item text="Example Tag 7"></d2l-tag-list-item>
|
|
27
|
+
</d2l-tag-list>
|
|
28
|
+
</d2l-demo-snippet>
|
|
29
|
+
|
|
30
|
+
</d2l-demo-page>
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import '../colors/colors.js';
|
|
2
|
+
import { css, html } from 'lit-element/lit-element.js';
|
|
3
|
+
import { labelStyles } from '../typography/styles.js';
|
|
4
|
+
|
|
5
|
+
export const TagListItemMixin = superclass => class extends superclass {
|
|
6
|
+
|
|
7
|
+
static get properties() {
|
|
8
|
+
return {
|
|
9
|
+
/**
|
|
10
|
+
* @ignore
|
|
11
|
+
*/
|
|
12
|
+
role: { type: String, reflect: true }
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static get styles() {
|
|
17
|
+
return [labelStyles, css`
|
|
18
|
+
:host {
|
|
19
|
+
display: grid;
|
|
20
|
+
outline: none;
|
|
21
|
+
}
|
|
22
|
+
:host([hidden]) {
|
|
23
|
+
display: none;
|
|
24
|
+
}
|
|
25
|
+
.tag-list-item-content {
|
|
26
|
+
height: 1rem;
|
|
27
|
+
margin: auto;
|
|
28
|
+
min-width: 0;
|
|
29
|
+
overflow: hidden;
|
|
30
|
+
text-overflow: ellipsis;
|
|
31
|
+
white-space: nowrap;
|
|
32
|
+
}
|
|
33
|
+
.tag-list-item-container {
|
|
34
|
+
background-color: var(--d2l-color-regolith);
|
|
35
|
+
border-radius: 6px;
|
|
36
|
+
box-shadow: inset 0 0 0 1px var(--d2l-color-gypsum), 0 2px 4px rgba(0, 0, 0, 0.03);
|
|
37
|
+
box-sizing: border-box;
|
|
38
|
+
color: var(--d2l-color-ferrite);
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
display: flex;
|
|
41
|
+
min-width: 0;
|
|
42
|
+
padding: 0.25rem 0.6rem;
|
|
43
|
+
transition: background-color 0.2s ease-out, box-shadow 0.2s ease-out;
|
|
44
|
+
}
|
|
45
|
+
:host(:hover) .tag-list-item-container,
|
|
46
|
+
:host(:focus) .tag-list-item-container {
|
|
47
|
+
background-color: var(--d2l-color-sylvite);
|
|
48
|
+
}
|
|
49
|
+
:host(:hover) .tag-list-item-container {
|
|
50
|
+
box-shadow: inset 0 0 0 1px var(--d2l-color-mica), 0 2px 4px rgba(0, 0, 0, 0.03);
|
|
51
|
+
}
|
|
52
|
+
:host(:focus) .tag-list-item-container {
|
|
53
|
+
box-shadow: inset 0 0 0 2px var(--d2l-color-celestine), 0 2px 4px rgba(0, 0, 0, 0.03);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@media (prefers-reduced-motion: reduce) {
|
|
57
|
+
.tag-list-item-container {
|
|
58
|
+
transition: none;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
`];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
constructor() {
|
|
65
|
+
super();
|
|
66
|
+
/** @ignore */
|
|
67
|
+
this.role = 'listitem';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
_renderTag(tagContent) {
|
|
71
|
+
return html`
|
|
72
|
+
<div class="tag-list-item-container d2l-label-text">
|
|
73
|
+
<div class="tag-list-item-content">${tagContent}</div>
|
|
74
|
+
</div>
|
|
75
|
+
`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { LitElement } from 'lit-element/lit-element.js';
|
|
2
|
+
import { TagListItemMixin } from './tag-list-item-mixin.js';
|
|
3
|
+
|
|
4
|
+
class TagListItem extends TagListItemMixin(LitElement) {
|
|
5
|
+
|
|
6
|
+
static get properties() {
|
|
7
|
+
return {
|
|
8
|
+
/**
|
|
9
|
+
* REQUIRED: Text to display
|
|
10
|
+
* @type {string}
|
|
11
|
+
*/
|
|
12
|
+
text: { type: String }
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
render() {
|
|
17
|
+
return this._renderTag(this.text);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
customElements.define('d2l-tag-list-item', TagListItem);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { css, html, LitElement } from 'lit-element/lit-element.js';
|
|
2
|
+
import { ArrowKeysMixin } from '../../mixins/arrow-keys-mixin.js';
|
|
3
|
+
|
|
4
|
+
class TagList extends ArrowKeysMixin(LitElement) {
|
|
5
|
+
|
|
6
|
+
static get properties() {
|
|
7
|
+
return {
|
|
8
|
+
/**
|
|
9
|
+
* REQUIRED: A description of the tag list for additional accessibility context
|
|
10
|
+
* @type {string}
|
|
11
|
+
*/
|
|
12
|
+
description: { type: String }
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static get styles() {
|
|
17
|
+
return css`
|
|
18
|
+
:host {
|
|
19
|
+
display: block;
|
|
20
|
+
}
|
|
21
|
+
:host([hidden]) {
|
|
22
|
+
display: none;
|
|
23
|
+
}
|
|
24
|
+
.tag-list-container {
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-wrap: wrap;
|
|
27
|
+
margin: -6px -6px 0 0;
|
|
28
|
+
padding: 0;
|
|
29
|
+
position: relative;
|
|
30
|
+
}
|
|
31
|
+
::slotted(*) {
|
|
32
|
+
margin: 6px 6px 0 0;
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
constructor() {
|
|
38
|
+
super();
|
|
39
|
+
/** @ignore */
|
|
40
|
+
this.arrowKeysDirection = 'leftrightupdown';
|
|
41
|
+
this._items = [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
firstUpdated(changedProperties) {
|
|
45
|
+
super.firstUpdated(changedProperties);
|
|
46
|
+
|
|
47
|
+
requestAnimationFrame(() => {
|
|
48
|
+
this._items = this._getTagListItems();
|
|
49
|
+
this._items.forEach((item, index) => {
|
|
50
|
+
item.setAttribute('tabIndex', index === 0 ? 0 : -1);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
render() {
|
|
56
|
+
const list = html`
|
|
57
|
+
<div role="list" class="tag-list-container" aria-describedby="d2l-tag-list-description">
|
|
58
|
+
<slot></slot>
|
|
59
|
+
</div>
|
|
60
|
+
`;
|
|
61
|
+
return html`
|
|
62
|
+
<div role="application">
|
|
63
|
+
${this.arrowKeysContainer(list)}
|
|
64
|
+
<div id="d2l-tag-list-description" hidden>${this.description}</div>
|
|
65
|
+
</div>
|
|
66
|
+
`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async arrowKeysFocusablesProvider() {
|
|
70
|
+
return this._items;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
focus() {
|
|
74
|
+
if (this._items.length > 0) this._items[0].focus();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
_getTagListItems() {
|
|
78
|
+
const slot = this.shadowRoot && this.shadowRoot.querySelector('slot');
|
|
79
|
+
if (!slot) return;
|
|
80
|
+
return slot.assignedNodes({ flatten: true }).filter((node) => {
|
|
81
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return false;
|
|
82
|
+
const role = node.getAttribute('role');
|
|
83
|
+
return (role === 'listitem');
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
customElements.define('d2l-tag-list', TagList);
|
package/custom-elements.json
CHANGED
|
@@ -9766,6 +9766,71 @@
|
|
|
9766
9766
|
}
|
|
9767
9767
|
]
|
|
9768
9768
|
},
|
|
9769
|
+
{
|
|
9770
|
+
"name": "d2l-tag-list-item",
|
|
9771
|
+
"path": "./components/tag-list/tag-list-item.js",
|
|
9772
|
+
"attributes": [
|
|
9773
|
+
{
|
|
9774
|
+
"name": "text",
|
|
9775
|
+
"description": "REQUIRED: Text to display",
|
|
9776
|
+
"type": "string"
|
|
9777
|
+
}
|
|
9778
|
+
],
|
|
9779
|
+
"properties": [
|
|
9780
|
+
{
|
|
9781
|
+
"name": "text",
|
|
9782
|
+
"attribute": "text",
|
|
9783
|
+
"description": "REQUIRED: Text to display",
|
|
9784
|
+
"type": "string"
|
|
9785
|
+
}
|
|
9786
|
+
]
|
|
9787
|
+
},
|
|
9788
|
+
{
|
|
9789
|
+
"name": "d2l-tag-list",
|
|
9790
|
+
"path": "./components/tag-list/tag-list.js",
|
|
9791
|
+
"attributes": [
|
|
9792
|
+
{
|
|
9793
|
+
"name": "description",
|
|
9794
|
+
"description": "REQUIRED: A description of the tag list for additional accessibility context",
|
|
9795
|
+
"type": "string"
|
|
9796
|
+
}
|
|
9797
|
+
],
|
|
9798
|
+
"properties": [
|
|
9799
|
+
{
|
|
9800
|
+
"name": "description",
|
|
9801
|
+
"attribute": "description",
|
|
9802
|
+
"description": "REQUIRED: A description of the tag list for additional accessibility context",
|
|
9803
|
+
"type": "string"
|
|
9804
|
+
},
|
|
9805
|
+
{
|
|
9806
|
+
"name": "arrowKeysDirection",
|
|
9807
|
+
"type": "string",
|
|
9808
|
+
"default": "\"leftright\""
|
|
9809
|
+
},
|
|
9810
|
+
{
|
|
9811
|
+
"name": "arrowKeysNoWrap",
|
|
9812
|
+
"type": "boolean",
|
|
9813
|
+
"default": "false"
|
|
9814
|
+
}
|
|
9815
|
+
]
|
|
9816
|
+
},
|
|
9817
|
+
{
|
|
9818
|
+
"name": "d2l-tag-list-item-mixin-consumer",
|
|
9819
|
+
"path": "./components/tag-list/test/tag-list-item-mixin-consumer.js",
|
|
9820
|
+
"attributes": [
|
|
9821
|
+
{
|
|
9822
|
+
"name": "name",
|
|
9823
|
+
"type": "string"
|
|
9824
|
+
}
|
|
9825
|
+
],
|
|
9826
|
+
"properties": [
|
|
9827
|
+
{
|
|
9828
|
+
"name": "name",
|
|
9829
|
+
"attribute": "name",
|
|
9830
|
+
"type": "string"
|
|
9831
|
+
}
|
|
9832
|
+
]
|
|
9833
|
+
},
|
|
9769
9834
|
{
|
|
9770
9835
|
"name": "d2l-tooltip",
|
|
9771
9836
|
"path": "./components/tooltip/tooltip.js",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "A collection of accessible, free, open-source web components for building Brightspace applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": "https://github.com/BrightspaceUI/core.git",
|