@brightspace-ui/core 2.170.0 → 2.170.2

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.
@@ -1,12 +1,14 @@
1
1
  import '../colors/colors.js';
2
2
  import '../tooltip/tooltip.js';
3
- import { css, html, LitElement, nothing } from 'lit';
3
+ import { css, html, LitElement, nothing, unsafeCSS } from 'lit';
4
4
  import { VisibleOnAncestorMixin, visibleOnAncestorStyles } from '../../mixins/visible-on-ancestor/visible-on-ancestor-mixin.js';
5
5
  import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
6
+ import { getFocusPseudoClass } from '../../helpers/focus.js';
6
7
  import { getUniqueId } from '../../helpers/uniqueId.js';
7
8
  import { ifDefined } from 'lit/directives/if-defined.js';
8
9
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
9
10
  import { PropertyRequiredMixin } from '../../mixins/property-required/property-required-mixin.js';
11
+ import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
10
12
 
11
13
  const MODE = {
12
14
  ICON: 'icon',
@@ -17,14 +19,14 @@ const MODE = {
17
19
  /**
18
20
  * A component for quickly adding items to a specific locaiton.
19
21
  */
20
- class ButtonAdd extends PropertyRequiredMixin(FocusMixin(LocalizeCoreElement(LitElement))) {
22
+ class ButtonAdd extends RtlMixin(PropertyRequiredMixin(FocusMixin(LocalizeCoreElement(LitElement)))) {
21
23
  static get properties() {
22
24
  return {
23
25
  /**
24
26
  * Display mode of the component. Defaults to "icon" (plus icon is always visible). Other options are "icon-and-text" (plus icon and text are always visible), and "icon-when-interacted" (plus icon is only visible when hover or focus).
25
27
  * @type {'icon'|'icon-and-text'|'icon-when-interacted'}
26
28
  */
27
- mode: { type: String },
29
+ mode: { type: String, reflect: true },
28
30
  /**
29
31
  * When text-visible is true, the text to show in the button. When text-visible is false, the text to show in the tooltip.
30
32
  * @type {string}
@@ -35,6 +37,11 @@ class ButtonAdd extends PropertyRequiredMixin(FocusMixin(LocalizeCoreElement(Lit
35
37
 
36
38
  static get styles() {
37
39
  return css`
40
+ :host {
41
+ --d2l-button-add-animation-delay: 50ms;
42
+ --d2l-button-add-animation-duration: 200ms;
43
+ --d2l-button-add-hover-focus-color: var(--d2l-color-celestine-minus-1);
44
+ }
38
45
  button {
39
46
  align-items: center;
40
47
  background-color: transparent;
@@ -53,22 +60,88 @@ class ButtonAdd extends PropertyRequiredMixin(FocusMixin(LocalizeCoreElement(Lit
53
60
  }
54
61
 
55
62
  .line {
56
- border-top: 1px solid var(--d2l-color-mica);
63
+ background: var(--d2l-color-mica);
64
+ height: 1px;
65
+ margin: 3px 0;
57
66
  width: 100%;
58
67
  }
59
68
 
60
69
  button:hover .line,
61
70
  button:focus .line {
62
- border-top-color: var(--d2l-color-celestine-minus-1);
71
+ background: var(--d2l-button-add-hover-focus-color);
72
+ height: 2px;
63
73
  }
64
74
  button:hover d2l-button-add-icon-text,
65
75
  button:focus d2l-button-add-icon-text {
66
- --d2l-button-add-icon-text-color: var(--d2l-color-celestine-minus-1);
76
+ --d2l-button-add-icon-text-color: var(--d2l-button-add-hover-focus-color);
77
+ }
78
+ :host([mode="icon-when-interacted"]) button:hover .line {
79
+ transition-delay: var(--d2l-button-add-animation-delay);
67
80
  }
68
81
 
69
82
  :host([mode="icon-when-interacted"]) button:not(:focus):not(:hover) d2l-button-add-icon-text {
70
83
  position: absolute;
71
84
  }
85
+ :host([mode="icon-when-interacted"]) button:hover d2l-button-add-icon-text,
86
+ :host([mode="icon-when-interacted"]) button:focus d2l-button-add-icon-text {
87
+ animation: position-change-animation var(--d2l-button-add-animation-delay); /* add delay in changing position to avoid flash of missing icon space */
88
+ }
89
+ @keyframes position-change-animation {
90
+ 0% { position: absolute; }
91
+ 100% { position: static; }
92
+ }
93
+
94
+ button:${unsafeCSS(getFocusPseudoClass())} d2l-button-add-icon-text {
95
+ border-radius: 0.3rem;
96
+ box-shadow: 0 0 0 3px var(--d2l-button-add-hover-focus-color);
97
+ }
98
+ :host([mode="icon-when-interacted"]) button:${unsafeCSS(getFocusPseudoClass())} d2l-button-add-icon-text,
99
+ :host([mode="icon"]) button:${unsafeCSS(getFocusPseudoClass())} d2l-button-add-icon-text {
100
+ padding: 0.1rem;
101
+ }
102
+
103
+ @media (prefers-reduced-motion: no-preference) {
104
+ button:hover .line,
105
+ button:focus .line {
106
+ transition: all var(--d2l-button-add-animation-duration) ease-in var(--d2l-button-add-animation-delay);
107
+ }
108
+ button:hover .line,
109
+ button:focus .line,
110
+ :host([dir="rtl"]) button:hover .line-end,
111
+ :host([dir="rtl"]) button:focus .line-end {
112
+ animation: line-start-animation var(--d2l-button-add-animation-duration) ease-in var(--d2l-button-add-animation-delay) 1 forwards;
113
+ }
114
+ button:hover .line-end,
115
+ button:focus .line-end,
116
+ :host([dir="rtl"]) button:hover .line-start,
117
+ :host([dir="rtl"]) button:focus .line-start {
118
+ animation-name: line-end-animation;
119
+ }
120
+ button:${unsafeCSS(getFocusPseudoClass())} d2l-button-add-icon-text {
121
+ transition: all var(--d2l-button-add-animation-duration) ease-in;
122
+ }
123
+
124
+ @keyframes line-start-animation {
125
+ 0% {
126
+ background: linear-gradient(to right, var(--d2l-color-mica) 0%, var(--d2l-color-mica) 11%, var(--d2l-button-add-hover-focus-color) 11%) left center / 113%;
127
+ opacity: 10%;
128
+ }
129
+ 100% {
130
+ background: linear-gradient(to right, var(--d2l-color-mica) 0%, var(--d2l-color-mica) 11%, var(--d2l-button-add-hover-focus-color) 11%) left center / 113%; /* safari */
131
+ background-position: right;
132
+ }
133
+ }
134
+ @keyframes line-end-animation {
135
+ 0% {
136
+ background: linear-gradient(to left, var(--d2l-color-mica) 0%, var(--d2l-color-mica) 11%, var(--d2l-button-add-hover-focus-color) 11%) right center / 113%;
137
+ opacity: 10%;
138
+ }
139
+ 100% {
140
+ background: linear-gradient(to left, var(--d2l-color-mica) 0%, var(--d2l-color-mica) 11%, var(--d2l-button-add-hover-focus-color) 11%) right center / 113%; /* safari */
141
+ background-position: left;
142
+ }
143
+ }
144
+ }
72
145
  `;
73
146
  }
74
147
 
@@ -91,10 +164,10 @@ class ButtonAdd extends PropertyRequiredMixin(FocusMixin(LocalizeCoreElement(Lit
91
164
  const id = !this.mode !== MODE.ICON_AND_TEXT ? this._buttonId : undefined;
92
165
 
93
166
  const content = this.mode !== MODE.ICON_AND_TEXT
94
- ? html`<d2l-button-add-icon-text ?visible-on-ancestor="${this.mode === MODE.ICON_WHEN_INTERACTED}"></d2l-button-add-icon-text>`
167
+ ? html`<d2l-button-add-icon-text ?visible-on-ancestor="${this.mode === MODE.ICON_WHEN_INTERACTED}" animation-type="opacity"></d2l-button-add-icon-text>`
95
168
  : html`<d2l-button-add-icon-text text="${text}"></d2l-button-add-icon-text>`;
96
169
  const tooltip = this.mode !== MODE.ICON_AND_TEXT
97
- ? html`<d2l-tooltip class="vdiff-target" offset="18" for="${this._buttonId}" for-type="label">${text}</d2l-tooltip>`
170
+ ? html`<d2l-tooltip class="vdiff-target" delay="100" offset="18" for="${this._buttonId}" for-type="label">${text}</d2l-tooltip>`
98
171
  : nothing;
99
172
 
100
173
  return html`
@@ -102,14 +175,13 @@ class ButtonAdd extends PropertyRequiredMixin(FocusMixin(LocalizeCoreElement(Lit
102
175
  class="d2l-label-text d2l-visible-on-ancestor-target"
103
176
  id="${ifDefined(id)}"
104
177
  type="button">
105
- <div class="line"></div>
178
+ <div class="line line-start"></div>
106
179
  ${content}
107
- <div class="line"></div>
180
+ <div class="line line-end"></div>
108
181
  </button>
109
182
  ${tooltip}
110
183
  `;
111
184
  }
112
-
113
185
  }
114
186
  customElements.define('d2l-button-add', ButtonAdd);
115
187
 
@@ -129,24 +201,24 @@ class ButtonAddIconText extends VisibleOnAncestorMixin(LitElement) {
129
201
  --d2l-button-add-icon-text-color: var(--d2l-color-galena);
130
202
  align-items: center;
131
203
  display: flex;
204
+ fill: var(--d2l-button-add-icon-text-color);
132
205
  }
206
+ :host([visible-on-ancestor]),
133
207
  :host([text]) {
134
208
  --d2l-button-add-icon-text-color: var(--d2l-color-celestine);
209
+ }
210
+ :host([text]) {
135
211
  color: var(--d2l-button-add-icon-text-color);
136
212
  height: 1.5rem;
137
213
  padding: 0 0.3rem;
138
214
  }
139
215
 
140
- svg {
141
- fill: var(--d2l-button-add-icon-text-color);
142
- }
143
-
144
216
  :host([text]) svg {
145
217
  padding-inline-end: 0.2rem;
146
218
  }
147
219
  :host(:not([text])) svg {
148
- margin: -3px; /** hover/click target */
149
- padding: 3px; /** hover/click target */
220
+ margin: -0.3rem; /** hover/click target */
221
+ padding: 0.3rem; /** hover/click target */
150
222
  }
151
223
 
152
224
  span {
@@ -395,6 +395,11 @@
395
395
  "attribute": "text",
396
396
  "type": "string"
397
397
  },
398
+ {
399
+ "name": "animationType",
400
+ "type": "string",
401
+ "default": "\"opacity-transform\""
402
+ },
398
403
  {
399
404
  "name": "visibleOnAncestor",
400
405
  "type": "boolean",
@@ -490,6 +495,11 @@
490
495
  "type": "boolean",
491
496
  "default": "false"
492
497
  },
498
+ {
499
+ "name": "animationType",
500
+ "type": "string",
501
+ "default": "\"opacity-transform\""
502
+ },
493
503
  {
494
504
  "name": "visibleOnAncestor",
495
505
  "type": "boolean",
@@ -2819,6 +2829,11 @@
2819
2829
  "type": "boolean",
2820
2830
  "default": "false"
2821
2831
  },
2832
+ {
2833
+ "name": "animationType",
2834
+ "type": "string",
2835
+ "default": "\"opacity-transform\""
2836
+ },
2822
2837
  {
2823
2838
  "name": "visibleOnAncestor",
2824
2839
  "type": "boolean",
@@ -3192,6 +3207,11 @@
3192
3207
  "type": "boolean",
3193
3208
  "default": "false"
3194
3209
  },
3210
+ {
3211
+ "name": "animationType",
3212
+ "type": "string",
3213
+ "default": "\"opacity-transform\""
3214
+ },
3195
3215
  {
3196
3216
  "name": "visibleOnAncestor",
3197
3217
  "type": "boolean",
@@ -15,6 +15,17 @@ export const visibleOnAncestorStyles = css`
15
15
  transition: transform 200ms ease-out, opacity 200ms ease-out !important;
16
16
  }
17
17
 
18
+ :host([__voa-state="hidden"][animation-type="opacity"]),
19
+ :host([__voa-state="hiding"][animation-type="opacity"]) {
20
+ transform: none !important;
21
+ }
22
+ :host([__voa-state="showing"][animation-type="opacity"]) {
23
+ transition: opacity 200ms ease-in !important;
24
+ }
25
+ :host([__voa-state="hiding"][animation-type="opacity"]) {
26
+ transition: none !important;
27
+ }
28
+
18
29
  @media only screen and (hover: none), only screen and (-moz-touch-enabled: 1) {
19
30
  :host([__voa-state="hidden"]),
20
31
  :host([__voa-state="hiding"]) {
@@ -34,6 +45,10 @@ export const VisibleOnAncestorMixin = superclass => class extends superclass {
34
45
 
35
46
  static get properties() {
36
47
  return {
48
+ /**
49
+ * @ignore
50
+ */
51
+ animationType: { type: String, reflect: true, attribute: 'animation-type' },
37
52
  /**
38
53
  * @ignore
39
54
  */
@@ -45,6 +60,7 @@ export const VisibleOnAncestorMixin = superclass => class extends superclass {
45
60
  constructor() {
46
61
  super();
47
62
 
63
+ this.animationType = 'opacity-transform';
48
64
  this.visibleOnAncestor = false;
49
65
  }
50
66
 
@@ -97,7 +113,7 @@ export const VisibleOnAncestorMixin = superclass => class extends superclass {
97
113
  this.__voaState = 'hidden';
98
114
  } else {
99
115
  const handleTransitionEnd = (e) => {
100
- if (e.propertyName !== 'transform') return;
116
+ if (e.propertyName !== 'transform' && e.propertyName !== 'opacity') return;
101
117
  this.removeEventListener('transitionend', handleTransitionEnd);
102
118
  this.__voaState = 'hidden';
103
119
  };
@@ -134,11 +150,11 @@ export const VisibleOnAncestorMixin = superclass => class extends superclass {
134
150
  }
135
151
 
136
152
  __voaShow() {
137
- if (reduceMotion) {
153
+ if (reduceMotion && this.animationType !== 'opacity') {
138
154
  this.__voaState = 'shown';
139
155
  } else {
140
156
  const handleTransitionEnd = (e) => {
141
- if (e.propertyName !== 'transform') return;
157
+ if (e.propertyName !== 'transform' && e.propertyName !== 'opacity') return;
142
158
  this.removeEventListener('transitionend', handleTransitionEnd);
143
159
  this.__voaState = 'shown';
144
160
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "2.170.0",
3
+ "version": "2.170.2",
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",