@brightspace-ui/core 3.178.0 → 3.179.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.
@@ -49,6 +49,8 @@ Import and use the `<d2l-link>` web component instead of the native `<a>` elemen
49
49
  |--|--|--|
50
50
  | `aria-label` | String | Label to provide more context for screen reader users when the link text is not enough |
51
51
  | `href` | String, required | URL or URL fragment of the link |
52
+ | `disabled` | Boolean | Disables the link |
53
+ | `disabled-tooltip` | String | Tooltip text when disabled |
52
54
  | `download` | String | If the attribute is provided, it will prompt the user to download the resource instead of navigating to it. Additionally, if the attribute is provided with a value, that value will be used for the filename. |
53
55
  | `main` | Boolean | Whether to apply the "main" link style |
54
56
  | `lines` | Number | The number of lines to display before truncating text with an ellipsis. The text will not be truncated unless a value is specified. |
@@ -92,6 +92,20 @@
92
92
  </template>
93
93
  </d2l-demo-snippet>
94
94
 
95
+ <h2>Disabled</h2>
96
+ <d2l-demo-snippet>
97
+ <template>
98
+ <d2l-link disabled href="https://www.d2l.com" target="_blank">Disabled Link</d2l-link>
99
+ </template>
100
+ </d2l-demo-snippet>
101
+
102
+ <h2>Disabled with Tooltip</h2>
103
+ <d2l-demo-snippet>
104
+ <template>
105
+ <d2l-link disabled disabled-tooltip="This link is disabled because you do not have permission" href="https://www.d2l.com" target="_blank">Disabled Link with Tooltip</d2l-link>
106
+ </template>
107
+ </d2l-demo-snippet>
108
+
95
109
  </d2l-demo-page>
96
110
  </body>
97
111
  </html>
@@ -1,11 +1,13 @@
1
1
  import '../colors/colors.js';
2
2
  import '../icons/icon.js';
3
+ import '../tooltip/tooltip.js';
3
4
  import { css, html, LitElement, nothing } from 'lit';
4
5
  import { getOverflowDeclarations, overflowEllipsisDeclarations } from '../../helpers/overflow.js';
5
6
  import { _generateLinkStyles } from './link-styles.js';
6
7
  import { classMap } from 'lit/directives/class-map.js';
7
8
  import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
8
9
  import { getFlag } from '../../helpers/flags.js';
10
+ import { getUniqueId } from '../../helpers/uniqueId.js';
9
11
  import { ifDefined } from 'lit/directives/if-defined.js';
10
12
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
11
13
  import { offscreenStyles } from '../offscreen/offscreen.js';
@@ -28,6 +30,16 @@ class Link extends LocalizeCoreElement(FocusMixin(LitElement)) {
28
30
  * @type {string}
29
31
  */
30
32
  ariaLabel: { type: String, attribute: 'aria-label' },
33
+ /**
34
+ * Disables the link
35
+ * @type {boolean}
36
+ */
37
+ disabled: { type: Boolean, reflect: true },
38
+ /**
39
+ * Tooltip text when disabled
40
+ * @type {string}
41
+ */
42
+ disabledTooltip: { type: String, attribute: 'disabled-tooltip', reflect: true },
31
43
  /**
32
44
  * Download a URL instead of navigating to it
33
45
  * @type {boolean}
@@ -113,6 +125,24 @@ class Link extends LocalizeCoreElement(FocusMixin(LitElement)) {
113
125
  --d2l-icon-fill-color: var(--d2l-color-celestine-minus-1);
114
126
  }
115
127
 
128
+ :host([disabled]:not([disabled-tooltip])) a:hover {
129
+ color: var(--d2l-color-celestine);
130
+ text-decoration: none;
131
+ }
132
+ :host([disabled]:not([disabled-tooltip])) a:hover d2l-icon {
133
+ --d2l-icon-fill-color: var(--d2l-color-celestine);
134
+ }
135
+ a[aria-disabled="true"],
136
+ a[aria-disabled="true"]:active {
137
+ cursor: default;
138
+ }
139
+ a[aria-disabled="true"] .d2l-link-content {
140
+ opacity: 0.74;
141
+ }
142
+ a[aria-disabled="true"] d2l-icon {
143
+ opacity: 0.64;
144
+ }
145
+
116
146
  @media print {
117
147
  d2l-icon {
118
148
  display: none;
@@ -124,6 +154,7 @@ class Link extends LocalizeCoreElement(FocusMixin(LitElement)) {
124
154
 
125
155
  constructor() {
126
156
  super();
157
+ this.disabled = false;
127
158
  this.download = false;
128
159
  this.main = false;
129
160
  this.small = false;
@@ -141,6 +172,7 @@ class Link extends LocalizeCoreElement(FocusMixin(LitElement)) {
141
172
  'd2l-link-small': this.small
142
173
  };
143
174
  const spanClasses = {
175
+ 'd2l-link-content': true,
144
176
  'truncate': this.lines > 1,
145
177
  'truncate-one': this.lines === 1
146
178
  };
@@ -148,6 +180,9 @@ class Link extends LocalizeCoreElement(FocusMixin(LitElement)) {
148
180
  const newWindowElements = (this.target === '_blank')
149
181
  ? html`<span id="new-window"><span style="font-size: 0;">&nbsp;</span><d2l-icon icon="tier1:new-window"></d2l-icon></span><span class="d2l-offscreen">${this.localize('components.link.open-in-new-window')}</span>`
150
182
  : nothing;
183
+ const disabledTooltip = this.disabled && this.disabledTooltip
184
+ ? html`<d2l-tooltip class="vdiff-target" for="${this.#linkId}">${this.disabledTooltip}</d2l-tooltip>`
185
+ : nothing;
151
186
 
152
187
  /*
153
188
  * NOTICE:
@@ -155,14 +190,27 @@ class Link extends LocalizeCoreElement(FocusMixin(LitElement)) {
155
190
  * Do not modify for readability!
156
191
  */
157
192
  return html`<a
193
+ aria-disabled="${ifDefined(this.disabled ? 'true' : undefined)}"
158
194
  aria-label="${ifDefined(this.ariaLabel)}"
159
195
  class="${classMap(linkClasses)}"
196
+ @click="${this.#handleClick}"
160
197
  ?download="${this.download}"
161
- href="${ifDefined(this.href)}"
198
+ href="${ifDefined(!this.disabled ? this.href : undefined)}"
199
+ id="${this.#linkId}"
200
+ tabindex="${ifDefined(this.disabled && this.disabledTooltip ? 0 : undefined)}"
162
201
  target="${ifDefined(this.target)}"
163
202
  ><span
164
203
  class="${classMap(spanClasses)}"
165
- style="${styleMap(styles)}"><slot></slot></span>${newWindowElements}</a>`;
204
+ style="${styleMap(styles)}"><slot></slot></span>${newWindowElements}</a>${disabledTooltip}`;
205
+ }
206
+
207
+ #linkId = getUniqueId();
208
+
209
+ #handleClick(e) {
210
+ if (this.disabled) {
211
+ e.stopPropagation();
212
+ e.preventDefault();
213
+ }
166
214
  }
167
215
 
168
216
  }
@@ -8483,6 +8483,11 @@
8483
8483
  "description": "ACCESSIBILITY: Label to provide more context for screen reader users when the link text is not enough",
8484
8484
  "type": "string"
8485
8485
  },
8486
+ {
8487
+ "name": "disabled-tooltip",
8488
+ "description": "Tooltip text when disabled",
8489
+ "type": "string"
8490
+ },
8486
8491
  {
8487
8492
  "name": "href",
8488
8493
  "description": "REQUIRED: URL or URL fragment of the link",
@@ -8493,6 +8498,12 @@
8493
8498
  "description": "Where to display the linked URL",
8494
8499
  "type": "string"
8495
8500
  },
8501
+ {
8502
+ "name": "disabled",
8503
+ "description": "Disables the link",
8504
+ "type": "boolean",
8505
+ "default": "false"
8506
+ },
8496
8507
  {
8497
8508
  "name": "download",
8498
8509
  "description": "Download a URL instead of navigating to it",
@@ -8525,6 +8536,12 @@
8525
8536
  "description": "ACCESSIBILITY: Label to provide more context for screen reader users when the link text is not enough",
8526
8537
  "type": "string"
8527
8538
  },
8539
+ {
8540
+ "name": "disabledTooltip",
8541
+ "attribute": "disabled-tooltip",
8542
+ "description": "Tooltip text when disabled",
8543
+ "type": "string"
8544
+ },
8528
8545
  {
8529
8546
  "name": "href",
8530
8547
  "attribute": "href",
@@ -8537,6 +8554,13 @@
8537
8554
  "description": "Where to display the linked URL",
8538
8555
  "type": "string"
8539
8556
  },
8557
+ {
8558
+ "name": "disabled",
8559
+ "attribute": "disabled",
8560
+ "description": "Disables the link",
8561
+ "type": "boolean",
8562
+ "default": "false"
8563
+ },
8540
8564
  {
8541
8565
  "name": "download",
8542
8566
  "attribute": "download",
@@ -35,7 +35,7 @@ export function isInteractive(ele, elems, roles) {
35
35
  return true;
36
36
  }
37
37
  const role = (ele.getAttribute('role') || '');
38
- return (nodeName === 'a' && ele.hasAttribute('href')) || roles[role] || false;
38
+ return (nodeName === 'a' && (ele.hasAttribute('href') || ele.getAttribute('tabindex') === '0')) || roles[role] || false;
39
39
  }
40
40
 
41
41
  export function isInteractiveInComposedPath(composedPath, predicate, options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.178.0",
3
+ "version": "3.179.0",
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",