@brightspace-ui/core 2.143.1 → 2.145.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.
@@ -101,6 +101,24 @@ To make your `d2l-button-subtle` accessible, use the following properties when a
101
101
  | `aria-haspopup` | [Indicate clicking the button opens a menu](https://www.w3.org/WAI/PF/aria/states_and_properties#aria-haspopup). Example: [d2l-dropdown](https://github.com/BrightspaceUI/core/blob/main/components/dropdown/dropdown-opener-mixin.js#L46). |
102
102
  | `description` | Use when text on button does not provide enough context. |
103
103
 
104
+ ### Subtle Button with Custom Icon
105
+
106
+ <!-- docs: demo code -->
107
+ ```html
108
+ <script type="module">
109
+ import '@brightspace-ui/core/components/button/button-subtle.js';
110
+ import '@brightspace-ui/core/components/icons/icon-custom.js';
111
+ </script>
112
+ <d2l-button-subtle text="Subtle Button">
113
+ <d2l-icon-custom slot="icon">
114
+ <svg xmlns="http://www.w3.org/2000/svg" mirror-in-rtl="true">
115
+ <path fill="#494c4e" d="M18 12v5a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-5a1 1 0 0 1 2 0v4h14v-4a1 1 0 0 1 2 0z"/>
116
+ <path fill="#494c4e" d="M13.85 3.15l-2.99-3A.507.507 0 0 0 10.5 0H5.4A1.417 1.417 0 0 0 4 1.43v11.14A1.417 1.417 0 0 0 5.4 14h7.2a1.417 1.417 0 0 0 1.4-1.43V3.5a.47.47 0 0 0-.15-.35zM7 2h1a1 1 0 0 1 0 2H7a1 1 0 0 1 0-2zm4 10H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2zm0-4H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z"/>
117
+ </svg>
118
+ </d2l-icon-custom>
119
+ </d2l-button-subtle>
120
+ ```
121
+
104
122
  ## Icon Button [d2l-button-icon]
105
123
 
106
124
  The `d2l-button-icon` element can be used just like the native `button`, for instances where only an icon is displayed.
@@ -139,6 +157,24 @@ To make your `d2l-button-icon` accessible, use the following properties when app
139
157
  | `aria-label` | Acts as a primary label. If `text` AND `aria-label` are provided, `aria-label` is used as the primary label, `text` is used as the tooltip. |
140
158
  | `description` | Use when text on button does not provide enough context. |
141
159
 
160
+ ### Icon Button with Custom Icon
161
+
162
+ <!-- docs: demo code -->
163
+ ```html
164
+ <script type="module">
165
+ import '@brightspace-ui/core/components/button/button-icon.js';
166
+ import '@brightspace-ui/core/components/icons/icon-custom.js';
167
+ </script>
168
+ <d2l-button-icon text="Custom Icon Button">
169
+ <d2l-icon-custom slot="icon">
170
+ <svg xmlns="http://www.w3.org/2000/svg" mirror-in-rtl="true">
171
+ <path fill="#494c4e" d="M18 12v5a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-5a1 1 0 0 1 2 0v4h14v-4a1 1 0 0 1 2 0z"/>
172
+ <path fill="#494c4e" d="M13.85 3.15l-2.99-3A.507.507 0 0 0 10.5 0H5.4A1.417 1.417 0 0 0 4 1.43v11.14A1.417 1.417 0 0 0 5.4 14h7.2a1.417 1.417 0 0 0 1.4-1.43V3.5a.47.47 0 0 0-.15-.35zM7 2h1a1 1 0 0 1 0 2H7a1 1 0 0 1 0-2zm4 10H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2zm0-4H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z"/>
173
+ </svg>
174
+ </d2l-icon-custom>
175
+ </d2l-button-icon>
176
+ ```
177
+
142
178
  ## Floating Buttons [d2l-floating-buttons]
143
179
 
144
180
  See [floating buttons](https://github.com/BrightspaceUI/core/tree/main/components/button/floating-buttons.md).
@@ -1,7 +1,7 @@
1
1
  import '../colors/colors.js';
2
2
  import '../icons/icon.js';
3
3
  import '../tooltip/tooltip.js';
4
- import { css, html, LitElement, unsafeCSS } from 'lit';
4
+ import { css, html, LitElement, nothing, unsafeCSS } from 'lit';
5
5
  import { VisibleOnAncestorMixin, visibleOnAncestorStyles } from '../../mixins/visible-on-ancestor/visible-on-ancestor-mixin.js';
6
6
  import { ButtonMixin } from './button-mixin.js';
7
7
  import { buttonStyles } from './button-styles.js';
@@ -13,6 +13,7 @@ import { ThemeMixin } from '../../mixins/theme/theme-mixin.js';
13
13
 
14
14
  /**
15
15
  * A button component that can be used just like the native button for instances where only an icon is displayed.
16
+ * @slot icon - Optional slot for a custom icon
16
17
  */
17
18
  class ButtonIcon extends ThemeMixin(ButtonMixin(VisibleOnAncestorMixin(RtlMixin(LitElement)))) {
18
19
 
@@ -117,7 +118,15 @@ class ButtonIcon extends ThemeMixin(ButtonMixin(VisibleOnAncestorMixin(RtlMixin(
117
118
  box-shadow: var(--d2l-button-icon-focus-box-shadow);
118
119
  }
119
120
 
120
- .d2l-button-icon {
121
+ slot[name="icon"]::slotted(*) {
122
+ display: none;
123
+ }
124
+ slot[name="icon"]::slotted(d2l-icon-custom) {
125
+ display: inline-flex;
126
+ }
127
+
128
+ d2l-icon,
129
+ slot[name="icon"]::slotted(d2l-icon-custom) {
121
130
  height: 0.9rem;
122
131
  width: 0.9rem;
123
132
  }
@@ -155,6 +164,7 @@ class ButtonIcon extends ThemeMixin(ButtonMixin(VisibleOnAncestorMixin(RtlMixin(
155
164
  }
156
165
 
157
166
  render() {
167
+ const icon = this.icon ? html`<d2l-icon icon="${this.icon}"></d2l-icon>` : nothing;
158
168
  return html`
159
169
  <button
160
170
  aria-describedby="${ifDefined(this.description ? this._describedById : undefined)}"
@@ -174,7 +184,7 @@ class ButtonIcon extends ThemeMixin(ButtonMixin(VisibleOnAncestorMixin(RtlMixin(
174
184
  name="${ifDefined(this.name)}"
175
185
  title="${ifDefined(this.text)}"
176
186
  type="${this._getType()}">
177
- <d2l-icon icon="${ifDefined(this.icon)}" class="d2l-button-icon"></d2l-icon>
187
+ <slot name="icon">${icon}</slot>
178
188
  </button>
179
189
  ${this.description ? html`<span id="${this._describedById}" hidden>${this.description}</span>` : null}
180
190
  ${this.disabled && this.disabledTooltip ? html`<d2l-tooltip for="${this._buttonId}">${this.disabledTooltip}</d2l-tooltip>` : ''}
@@ -1,18 +1,19 @@
1
1
  import '../icons/icon.js';
2
2
  import '../tooltip/tooltip.js';
3
- import { css, html, LitElement } from 'lit';
3
+ import { css, html, LitElement, nothing } from 'lit';
4
4
  import { ButtonMixin } from './button-mixin.js';
5
5
  import { buttonStyles } from './button-styles.js';
6
+ import { classMap } from 'lit/directives/class-map.js';
6
7
  import { getUniqueId } from '../../helpers/uniqueId.js';
7
8
  import { ifDefined } from 'lit/directives/if-defined.js';
8
9
  import { labelStyles } from '../typography/styles.js';
9
- import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
10
10
 
11
11
  /**
12
12
  * A button component that can be used just like the native button, but for advanced or de-emphasized actions.
13
13
  * @slot - Default content placed inside of the button
14
+ * @slot icon - Optional slot for a custom icon
14
15
  */
15
- class ButtonSubtle extends ButtonMixin(RtlMixin(LitElement)) {
16
+ class ButtonSubtle extends ButtonMixin(LitElement) {
16
17
 
17
18
  static get properties() {
18
19
  return {
@@ -50,7 +51,8 @@ class ButtonSubtle extends ButtonMixin(RtlMixin(LitElement)) {
50
51
  * REQUIRED: Text for the button
51
52
  * @type {string}
52
53
  */
53
- text: { type: String, reflect: true }
54
+ text: { type: String, reflect: true },
55
+ _hasCustomIcon: { state: true }
54
56
  };
55
57
  }
56
58
 
@@ -70,36 +72,31 @@ class ButtonSubtle extends ButtonMixin(RtlMixin(LitElement)) {
70
72
  background-color: transparent;
71
73
  border-color: transparent;
72
74
  font-family: inherit;
73
- padding: 0 var(--d2l-button-subtle-padding-inline-end) 0 var(--d2l-button-subtle-padding-inline-start);
75
+ padding-block-end: 0;
76
+ padding-block-start: 0;
77
+ padding-inline-end: var(--d2l-button-subtle-padding-inline-end);
78
+ padding-inline-start: var(--d2l-button-subtle-padding-inline-start);
74
79
  position: relative;
75
80
  }
76
81
 
77
- :host([dir="rtl"]) button {
78
- padding: 0 var(--d2l-button-subtle-padding-inline-start) 0 var(--d2l-button-subtle-padding-inline-end);
79
- }
80
-
81
82
  :host([slim]) button {
82
83
  --d2l-button-subtle-padding-inline-start: 0.5rem;
83
84
  --d2l-button-subtle-padding-inline-end: 0.5rem;
84
85
  min-height: 1.5rem;
85
86
  }
86
87
 
87
- :host([slim][icon]) button {
88
+ :host([slim]) button.d2l-button-subtle-has-icon {
88
89
  --d2l-button-subtle-padding-inline-start: 0.4rem;
89
90
  --d2l-button-subtle-padding-inline-end: 0.5rem;
90
91
  }
91
92
 
92
- :host([slim][icon][icon-right]) button {
93
+ :host([slim][icon-right]) button.d2l-button-subtle-has-icon {
93
94
  --d2l-button-subtle-padding-inline-start: 0.5rem;
94
95
  --d2l-button-subtle-padding-inline-end: 0.4rem;
95
96
  }
96
97
 
97
98
  :host([h-align="text"]) button {
98
- left: calc(var(--d2l-button-subtle-padding-inline-start) * -1);
99
- }
100
- :host([dir="rtl"][h-align="text"]) button {
101
- left: 0;
102
- right: calc(var(--d2l-button-subtle-padding-inline-start) * -1);
99
+ inset-inline-start: calc(var(--d2l-button-subtle-padding-inline-start) * -1);
103
100
  }
104
101
 
105
102
  /* Firefox includes a hidden border which messes up button dimensions */
@@ -125,20 +122,21 @@ class ButtonSubtle extends ButtonMixin(RtlMixin(LitElement)) {
125
122
  :host([active]:not([disabled])) button .d2l-button-subtle-content {
126
123
  color: var(--d2l-color-celestine-minus-1);
127
124
  }
128
- :host([icon]) .d2l-button-subtle-content,
129
- :host([dir="rtl"][icon][icon-right]) .d2l-button-subtle-content {
130
- padding-left: 1.2rem;
131
- padding-right: 0;
125
+ .d2l-button-subtle-has-icon .d2l-button-subtle-content {
126
+ padding-inline: 1.2rem 0;
132
127
  }
133
- :host([dir="rtl"][icon]) .d2l-button-subtle-content,
134
- :host([icon][icon-right]) .d2l-button-subtle-content {
135
- padding-left: 0;
136
- padding-right: 1.2rem;
128
+ :host([icon-right]) .d2l-button-subtle-has-icon .d2l-button-subtle-content {
129
+ padding-inline: 0 1.2rem;
137
130
  }
138
131
 
139
- d2l-icon.d2l-button-subtle-icon {
140
- color: var(--d2l-color-celestine);
132
+ slot[name="icon"]::slotted(*) {
141
133
  display: none;
134
+ }
135
+
136
+ d2l-icon.d2l-button-subtle-icon,
137
+ slot[name="icon"]::slotted(d2l-icon-custom) {
138
+ color: var(--d2l-color-celestine);
139
+ display: inline-block;
142
140
  height: 0.9rem;
143
141
  position: absolute;
144
142
  top: 50%;
@@ -148,19 +146,16 @@ class ButtonSubtle extends ButtonMixin(RtlMixin(LitElement)) {
148
146
 
149
147
  button:hover:not([disabled]) d2l-icon.d2l-button-subtle-icon,
150
148
  button:focus:not([disabled]) d2l-icon.d2l-button-subtle-icon,
151
- :host([active]:not([disabled])) button d2l-icon.d2l-button-subtle-icon {
149
+ :host([active]:not([disabled])) button d2l-icon.d2l-button-subtle-icon,
150
+ button:hover:not([disabled]) slot[name="icon"]::slotted(d2l-icon-custom),
151
+ button:focus:not([disabled]) slot[name="icon"]::slotted(d2l-icon-custom),
152
+ :host([active]:not([disabled])) slot[name="icon"]::slotted(d2l-icon-custom) {
152
153
  color: var(--d2l-color-celestine-minus-1);
153
154
  }
154
155
 
155
- :host([icon]) d2l-icon.d2l-button-subtle-icon {
156
- display: inline-block;
157
- }
158
- :host([icon][icon-right]) d2l-icon.d2l-button-subtle-icon {
159
- right: var(--d2l-button-subtle-padding-inline-end);
160
- }
161
- :host([dir="rtl"][icon][icon-right]) d2l-icon.d2l-button-subtle-icon {
162
- left: var(--d2l-button-subtle-padding-inline-end);
163
- right: auto;
156
+ :host([icon-right]) .d2l-button-subtle-has-icon d2l-icon.d2l-button-subtle-icon,
157
+ :host([icon-right]) slot[name="icon"]::slotted(d2l-icon-custom) {
158
+ inset-inline-end: var(--d2l-button-subtle-padding-inline-end);
164
159
  }
165
160
 
166
161
  :host([disabled]) button {
@@ -176,15 +171,17 @@ class ButtonSubtle extends ButtonMixin(RtlMixin(LitElement)) {
176
171
  this.iconRight = false;
177
172
  this.slim = false;
178
173
 
179
- /** @internal */
180
174
  this._buttonId = getUniqueId();
181
- /** @internal */
182
175
  this._describedById = getUniqueId();
176
+ this._hasCustomIcon = false;
183
177
  }
184
178
 
185
179
  render() {
186
- const icon = this.icon ?
187
- html`<d2l-icon icon="${this.icon}" class="d2l-button-subtle-icon"></d2l-icon>` : '';
180
+ const icon = this.icon ? html`<d2l-icon icon="${this.icon}" class="d2l-button-subtle-icon"></d2l-icon>` : nothing;
181
+ const buttonClasses = {
182
+ 'd2l-button-subtle-has-icon': this._hasCustomIcon || this.icon,
183
+ 'd2l-label-text': true
184
+ };
188
185
  return html`
189
186
  <button
190
187
  aria-describedby="${ifDefined(this.description ? this._describedById : undefined)}"
@@ -193,7 +190,7 @@ class ButtonSubtle extends ButtonMixin(RtlMixin(LitElement)) {
193
190
  aria-haspopup="${ifDefined(this.ariaHaspopup)}"
194
191
  aria-label="${ifDefined(this.ariaLabel)}"
195
192
  ?autofocus="${this.autofocus}"
196
- class="d2l-label-text"
193
+ class="${classMap(buttonClasses)}"
197
194
  ?disabled="${this.disabled && !this.disabledTooltip}"
198
195
  form="${ifDefined(this.form)}"
199
196
  formaction="${ifDefined(this.formaction)}"
@@ -204,7 +201,7 @@ class ButtonSubtle extends ButtonMixin(RtlMixin(LitElement)) {
204
201
  id="${this._buttonId}"
205
202
  name="${ifDefined(this.name)}"
206
203
  type="${this._getType()}">
207
- ${icon}
204
+ <slot name="icon" @slotchange="${this._handleIconSlotChange}">${icon}</slot>
208
205
  <span class="d2l-button-subtle-content">${this.text}</span>
209
206
  <slot></slot>
210
207
  </button>
@@ -213,6 +210,13 @@ class ButtonSubtle extends ButtonMixin(RtlMixin(LitElement)) {
213
210
  `;
214
211
  }
215
212
 
213
+ _handleIconSlotChange(e) {
214
+ const icon = e && e.target && e.target.assignedNodes({ flatten: true }).filter((node) => {
215
+ return node.nodeType === Node.ELEMENT_NODE && node.tagName === 'D2L-ICON-CUSTOM';
216
+ });
217
+ this._hasCustomIcon = icon.length === 1;
218
+ }
219
+
216
220
  }
217
221
 
218
222
  customElements.define('d2l-button-subtle', ButtonSubtle);
@@ -6,6 +6,7 @@
6
6
  <link rel="stylesheet" href="../../demo/styles.css" type="text/css">
7
7
  <script type="module">
8
8
  import '../../demo/demo-page.js';
9
+ import '../../icons/icon-custom.js';
9
10
  import '../button-icon.js';
10
11
  </script>
11
12
  <style>
@@ -137,6 +138,21 @@
137
138
  <d2l-button-icon icon="tier1:search" text="Search" class="custom"></d2l-button-icon>
138
139
  </template>
139
140
  </d2l-demo-snippet>
141
+
142
+ <h2>Icon Button with Custom Icon</h2>
143
+
144
+ <d2l-demo-snippet>
145
+ <template>
146
+ <d2l-button-icon text="Custom Icon Button">
147
+ <d2l-icon-custom slot="icon">
148
+ <svg xmlns="http://www.w3.org/2000/svg" mirror-in-rtl="true">
149
+ <path fill="#494c4e" d="M18 12v5a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-5a1 1 0 0 1 2 0v4h14v-4a1 1 0 0 1 2 0z"/>
150
+ <path fill="#494c4e" d="M13.85 3.15l-2.99-3A.507.507 0 0 0 10.5 0H5.4A1.417 1.417 0 0 0 4 1.43v11.14A1.417 1.417 0 0 0 5.4 14h7.2a1.417 1.417 0 0 0 1.4-1.43V3.5a.47.47 0 0 0-.15-.35zM7 2h1a1 1 0 0 1 0 2H7a1 1 0 0 1 0-2zm4 10H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2zm0-4H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z"/>
151
+ </svg>
152
+ </d2l-icon-custom>
153
+ </d2l-button-icon>
154
+ </template>
155
+ </d2l-demo-snippet>
140
156
  </d2l-demo-page>
141
157
 
142
158
  <script>
@@ -74,6 +74,38 @@
74
74
  </template>
75
75
  </d2l-demo-snippet>
76
76
 
77
+ <h2>Subtle Button with Slot Content</h2>
78
+
79
+ <d2l-demo-snippet>
80
+ <template>
81
+ <d2l-button-subtle text="Subtle Button">Slot Content</d2l-button-subtle>
82
+ <d2l-button-subtle slim text="Slim Subtle Button">Slim Slot Content</d2l-button-subtle>
83
+ </template>
84
+ </d2l-demo-snippet>
85
+
86
+ <h2>Subtle Button with Custom Icon</h2>
87
+
88
+ <d2l-demo-snippet>
89
+ <template>
90
+ <d2l-button-subtle text="Subtle Button">
91
+ <d2l-icon-custom slot="icon">
92
+ <svg xmlns="http://www.w3.org/2000/svg" mirror-in-rtl="true">
93
+ <path fill="#494c4e" d="M18 12v5a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-5a1 1 0 0 1 2 0v4h14v-4a1 1 0 0 1 2 0z"/>
94
+ <path fill="#494c4e" d="M13.85 3.15l-2.99-3A.507.507 0 0 0 10.5 0H5.4A1.417 1.417 0 0 0 4 1.43v11.14A1.417 1.417 0 0 0 5.4 14h7.2a1.417 1.417 0 0 0 1.4-1.43V3.5a.47.47 0 0 0-.15-.35zM7 2h1a1 1 0 0 1 0 2H7a1 1 0 0 1 0-2zm4 10H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2zm0-4H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z"/>
95
+ </svg>
96
+ </d2l-icon-custom>
97
+ </d2l-button-subtle>
98
+ <d2l-button-subtle slim text="Slim Subtle Button">
99
+ <d2l-icon-custom slot="icon">
100
+ <svg xmlns="http://www.w3.org/2000/svg" mirror-in-rtl="true">
101
+ <path fill="#494c4e" d="M18 12v5a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-5a1 1 0 0 1 2 0v4h14v-4a1 1 0 0 1 2 0z"/>
102
+ <path fill="#494c4e" d="M13.85 3.15l-2.99-3A.507.507 0 0 0 10.5 0H5.4A1.417 1.417 0 0 0 4 1.43v11.14A1.417 1.417 0 0 0 5.4 14h7.2a1.417 1.417 0 0 0 1.4-1.43V3.5a.47.47 0 0 0-.15-.35zM7 2h1a1 1 0 0 1 0 2H7a1 1 0 0 1 0-2zm4 10H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2zm0-4H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z"/>
103
+ </svg>
104
+ </d2l-icon-custom>
105
+ </d2l-button-subtle>
106
+ </template>
107
+ </d2l-demo-snippet>
108
+
77
109
  </d2l-demo-page>
78
110
 
79
111
  <script>
@@ -436,6 +436,12 @@
436
436
  "type": "boolean",
437
437
  "default": "false"
438
438
  }
439
+ ],
440
+ "slots": [
441
+ {
442
+ "name": "icon",
443
+ "description": "Optional slot for a custom icon"
444
+ }
439
445
  ]
440
446
  },
441
447
  {
@@ -646,6 +652,10 @@
646
652
  {
647
653
  "name": "",
648
654
  "description": "Default content placed inside of the button"
655
+ },
656
+ {
657
+ "name": "icon",
658
+ "description": "Optional slot for a custom icon"
649
659
  }
650
660
  ]
651
661
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "2.143.1",
3
+ "version": "2.145.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",