@brightspace-ui/core 2.144.0 → 2.145.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.
@@ -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.
@@ -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-wrapper {
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-wrapper {
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,15 +201,24 @@ class ButtonSubtle extends ButtonMixin(RtlMixin(LitElement)) {
204
201
  id="${this._buttonId}"
205
202
  name="${ifDefined(this.name)}"
206
203
  type="${this._getType()}">
207
- ${icon}
208
- <span class="d2l-button-subtle-content">${this.text}</span>
209
- <slot></slot>
204
+ <slot name="icon" @slotchange="${this._handleIconSlotChange}">${icon}</slot>
205
+ <span class="d2l-button-subtle-content-wrapper">
206
+ <span class="d2l-button-subtle-content">${this.text}</span>
207
+ <slot></slot>
208
+ </span>
210
209
  </button>
211
210
  ${this.description ? html`<span id="${this._describedById}" hidden>${this.description}</span>` : null}
212
211
  ${this.disabled && this.disabledTooltip ? html`<d2l-tooltip for="${this._buttonId}">${this.disabledTooltip}</d2l-tooltip>` : ''}
213
212
  `;
214
213
  }
215
214
 
215
+ _handleIconSlotChange(e) {
216
+ const icon = e && e.target && e.target.assignedNodes({ flatten: true }).filter((node) => {
217
+ return node.nodeType === Node.ELEMENT_NODE && node.tagName === 'D2L-ICON-CUSTOM';
218
+ });
219
+ this._hasCustomIcon = icon.length === 1;
220
+ }
221
+
216
222
  }
217
223
 
218
224
  customElements.define('d2l-button-subtle', ButtonSubtle);
@@ -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>
@@ -108,7 +108,7 @@ class DescriptionListWrapper extends LitElement {
108
108
  if (!entries || entries.length === 0) return;
109
109
  const entry = entries[0];
110
110
 
111
- this._stacked = entry.contentRect.width < this.breakpoint;
111
+ requestAnimationFrame(() => this._stacked = entry.contentRect.width < this.breakpoint);
112
112
  }
113
113
  }
114
114
 
@@ -652,6 +652,10 @@
652
652
  {
653
653
  "name": "",
654
654
  "description": "Default content placed inside of the button"
655
+ },
656
+ {
657
+ "name": "icon",
658
+ "description": "Optional slot for a custom icon"
655
659
  }
656
660
  ]
657
661
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "2.144.0",
3
+ "version": "2.145.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",