@brightspace-ui/core 3.249.0 → 3.250.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.
@@ -73,10 +73,10 @@ class PageHeaderButton extends FocusMixin(LitElement) {
73
73
 
74
74
  render() {
75
75
  const { ariaLabel, id, text, tooltip } = this.#getRenderSettings();
76
- const highlightBorder = !this.disabled ? html`<span class="d2l-labs-navigation-highlight-border"></span>` : nothing;
76
+ const highlightBorder = !this.disabled ? html`<span class="d2l-page-header-highlight-border"></span>` : nothing;
77
77
  const icon = html`<d2l-icon icon="${this.icon}"></d2l-icon>`;
78
78
  return html`
79
- <button id="${ifDefined(id)}" ?disabled="${this.disabled}" aria-label="${ifDefined(ariaLabel)}" type="button">
79
+ <button class="d2l-page-header-highlight-button" id="${ifDefined(id)}" ?disabled="${this.disabled}" aria-label="${ifDefined(ariaLabel)}" type="button">
80
80
  ${highlightBorder}
81
81
  ${this.iconPosition === 'start' ? icon : nothing}
82
82
  ${text}
@@ -0,0 +1,167 @@
1
+ import '../alert/alert.js';
2
+ import '../colors/colors.js';
3
+ import '../icons/icon.js';
4
+ import './page-header-custom.js';
5
+ import { bodyCompactStyles, heading3Styles, labelStyles } from '../typography/styles.js';
6
+ import { css, html, LitElement } from 'lit';
7
+ import { highlightBorderStyles, highlightLinkStyles } from './page-header-styles.js';
8
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
9
+ import { overflowEllipsisDeclarations } from '../../helpers/overflow.js';
10
+ import { RequesterMixin } from '../../mixins/provider/provider-mixin.js';
11
+
12
+ class PageHeaderImmersive extends RequesterMixin(LocalizeCoreElement(LitElement)) {
13
+
14
+ static get properties() {
15
+ return {
16
+ backHref: { attribute: 'back-href', type: String },
17
+ backCustomText: { attribute: 'back-custom-text', type: String },
18
+ titleText: { attribute: 'title-text', type: String },
19
+ subtitleText: { attribute: 'subtitle-text', type: String },
20
+ _error: { state: true },
21
+ _hasActions: { state: true }
22
+ };
23
+ }
24
+
25
+ static get styles() {
26
+ return [bodyCompactStyles, heading3Styles, labelStyles, highlightBorderStyles, highlightLinkStyles, css`
27
+ :host {
28
+ display: block;
29
+ }
30
+ :host([hidden]),
31
+ .actions[hidden] {
32
+ display: none;
33
+ }
34
+ .container {
35
+ align-items: stretch;
36
+ display: flex;
37
+ gap: 24px;
38
+ height: 3.1rem;
39
+ }
40
+ .title {
41
+ flex: 0 1 auto;
42
+ min-width: 0;
43
+ width: 100%;
44
+ }
45
+ .back,
46
+ .actions {
47
+ flex: 0 0 auto;
48
+ }
49
+ .title,
50
+ .actions {
51
+ border-inline-start: 1px solid var(--d2l-color-gypsum);
52
+ padding-inline-start: 24px;
53
+ }
54
+ .title h1 {
55
+ display: flex;
56
+ flex-direction: column;
57
+ height: 100%;
58
+ justify-content: center;
59
+ margin: 0;
60
+ }
61
+ .actions {
62
+ align-items: center;
63
+ display: flex;
64
+ gap: 0.6rem;
65
+ }
66
+ .title h1 .d2l-heading-3 {
67
+ margin: 0;
68
+ }
69
+ .back-text-short {
70
+ display: none;
71
+ }
72
+ @media (max-width: 615px) {
73
+ .back-text-long {
74
+ display: none;
75
+ }
76
+ .back-text-short {
77
+ display: inline;
78
+ }
79
+ }
80
+ d2l-alert {
81
+ margin: 10px auto;
82
+ }
83
+ .title-text {
84
+ ${overflowEllipsisDeclarations}
85
+ }
86
+ `];
87
+ }
88
+
89
+ constructor() {
90
+ super();
91
+ this._error = false;
92
+ this._hasActions = false;
93
+ }
94
+
95
+ connectedCallback() {
96
+ super.connectedCallback();
97
+ const configurePageHeader = this.requestInstance('d2l-page-header-configure');
98
+ if (configurePageHeader) {
99
+ configurePageHeader({ sticky: true });
100
+ } else {
101
+ this._error = true;
102
+ }
103
+ }
104
+
105
+ render() {
106
+ if (this._error) return this.#renderError();
107
+ return html`
108
+ <d2l-page-header-custom>
109
+ <div class="container" slot="top">
110
+ ${this.#renderBack()}
111
+ ${this.#renderTitle()}
112
+ <div class="actions" ?hidden="${!this._hasActions}">
113
+ <slot name="actions" @slotchange="${this.#handleActionsSlotChange}"></slot>
114
+ </div>
115
+ </div>
116
+ </d2l-page-header-custom>
117
+ `;
118
+ }
119
+
120
+ #handleActionsSlotChange(e) {
121
+ this._hasActions = e.target.assignedNodes({ flatten: true })?.length > 0;
122
+ }
123
+
124
+ #handleBackClick() {
125
+ this.dispatchEvent(
126
+ new CustomEvent(
127
+ 'd2l-page-header-immersive-back-click',
128
+ { bubbles: false, composed: false }
129
+ )
130
+ );
131
+ }
132
+
133
+ #renderBack() {
134
+ const href = this.backHref || 'javascript:void(0);';
135
+ const commonText = this.localizeCommon('navigation:back:title');
136
+ const longText = this.backCustomText || commonText;
137
+ return html`
138
+ <div class="back d2l-body-compact">
139
+ <a class="d2l-page-header-highlight-link" href="${href}" aria-label="${longText}" @click="${this.#handleBackClick}">
140
+ <span class="d2l-page-header-highlight-border"></span>
141
+ <d2l-icon icon="tier1:chevron-left"></d2l-icon>
142
+ <span class="back-text-long">${longText}</span>
143
+ <span class="back-text-short">${commonText}</span>
144
+ </a>
145
+ </div>
146
+ `;
147
+ }
148
+
149
+ #renderError() {
150
+ return html`
151
+ <d2l-alert type="critical">&lt;d2l-page-header-immersive&gt; must be rendered inside a &lt;d2l-page&gt;'s header slot.</d2l-alert>
152
+ `;
153
+ }
154
+
155
+ #renderTitle() {
156
+ const title = this.titleText ? html`<div class="title-text d2l-heading-3">${this.titleText}</div>` : '';
157
+ const subtitle = this.subtitleText ? html`<div class="title-text d2l-label-text">${this.subtitleText}</div>` : '';
158
+ const heading = (title || subtitle) && html`<h1>${title}${subtitle}</h1>`;
159
+ return html`
160
+ <div class="title">
161
+ <slot name="title">${heading}</slot>
162
+ </div>
163
+ `;
164
+ }
165
+
166
+ }
167
+ customElements.define('d2l-page-header-immersive', PageHeaderImmersive);
@@ -2,7 +2,7 @@ import '../colors/colors.js';
2
2
  import { css } from 'lit';
3
3
 
4
4
  export const highlightBorderStyles = css`
5
- .d2l-labs-navigation-highlight-border {
5
+ .d2l-page-header-highlight-border {
6
6
  background: transparent;
7
7
  border-bottom-left-radius: 4px;
8
8
  border-bottom-right-radius: 4px;
@@ -12,15 +12,15 @@ export const highlightBorderStyles = css`
12
12
  position: absolute;
13
13
  top: 0;
14
14
  }
15
- *:focus > .d2l-labs-navigation-highlight-border,
16
- *:hover > .d2l-labs-navigation-highlight-border,
17
- *[active] > .d2l-labs-navigation-highlight-border {
15
+ *:focus > .d2l-page-header-highlight-border,
16
+ *:hover > .d2l-page-header-highlight-border,
17
+ *[active] > .d2l-page-header-highlight-border {
18
18
  background: var(--d2l-color-celestine);
19
19
  }
20
20
  `;
21
21
 
22
22
  export const highlightButtonStyles = css`
23
- button {
23
+ button.d2l-page-header-highlight-button {
24
24
  align-items: center;
25
25
  background: transparent;
26
26
  border: none;
@@ -41,18 +41,39 @@ export const highlightButtonStyles = css`
41
41
  white-space: nowrap;
42
42
  }
43
43
  /* Firefox includes a hidden border which messes up button dimensions */
44
- button::-moz-focus-inner {
44
+ button.d2l-page-header-highlight-button::-moz-focus-inner {
45
45
  border: 0;
46
46
  }
47
- button:not([disabled]):hover,
48
- button:not([disabled]):focus,
49
- button[active] {
47
+ button.d2l-page-header-highlight-button:not([disabled]):hover,
48
+ button.d2l-page-header-highlight-button:not([disabled]):focus,
49
+ button.d2l-page-header-highlight-button[active] {
50
50
  --d2l-icon-fill-color: var(--d2l-color-celestine);
51
51
  color: var(--d2l-color-celestine);
52
52
  outline: none;
53
53
  }
54
- button[disabled] {
54
+ button.d2l-page-header-highlight-button[disabled] {
55
55
  cursor: default;
56
56
  opacity: 0.5;
57
57
  }
58
58
  `;
59
+
60
+ export const highlightLinkStyles = css`
61
+ a.d2l-page-header-highlight-link {
62
+ align-items: center;
63
+ color: var(--d2l-color-ferrite);
64
+ display: inline-flex;
65
+ gap: 6px;
66
+ height: 100%;
67
+ min-height: 40px;
68
+ position: relative;
69
+ text-decoration: none;
70
+ vertical-align: middle;
71
+ white-space: nowrap;
72
+ }
73
+ a.d2l-page-header-highlight-link:hover,
74
+ a.d2l-page-header-highlight-link:focus {
75
+ --d2l-icon-fill-color: var(--d2l-color-celestine);
76
+ color: var(--d2l-color-celestine);
77
+ outline: none;
78
+ }
79
+ `;
@@ -3,6 +3,7 @@ import '../button/floating-buttons.js';
3
3
  import { css, html, LitElement, nothing } from 'lit';
4
4
  import { classMap } from 'lit/directives/class-map.js';
5
5
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
6
+ import { ProviderMixin } from '../../mixins/provider/provider-mixin.js';
6
7
 
7
8
  /**
8
9
  * Component for laying out a page, with header, optional footer and optional navigation or supporting panels
@@ -12,7 +13,7 @@ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
12
13
  * @slot supporting - The supporting content of the page (expecting d2l-page-supporting)
13
14
  * @slot footer - The footer content of the page (expecting d2l-page-footer)
14
15
  */
15
- class Page extends LocalizeCoreElement(LitElement) {
16
+ class Page extends ProviderMixin(LocalizeCoreElement(LitElement)) {
16
17
 
17
18
  static properties = {
18
19
  /**
@@ -127,6 +128,9 @@ class Page extends LocalizeCoreElement(LitElement) {
127
128
  }
128
129
  }
129
130
  });
131
+ this.provideInstance('d2l-page-header-configure', (options) => {
132
+ this._headerIsSticky = options.sticky;
133
+ });
130
134
  }
131
135
 
132
136
  disconnectedCallback() {
@@ -162,12 +166,6 @@ class Page extends LocalizeCoreElement(LitElement) {
162
166
 
163
167
  #resizeObserver;
164
168
 
165
- #handleHeaderSlotChange(e) {
166
- const nodes = e.target.assignedNodes();
167
- //this._headerIsSticky = nodes.some(node => node.tagName.toLowerCase() === 'd2l-page-header-immersive');
168
- this._headerIsSticky = nodes.some(node => node.id === 'immersive-nav'); // temp until the official component exists
169
- }
170
-
171
169
  #handleSlotVisibilityChange(e) {
172
170
  const key = e.target.name;
173
171
  const nodes = e.target.assignedNodes();
@@ -200,7 +198,7 @@ class Page extends LocalizeCoreElement(LitElement) {
200
198
  return html`
201
199
  <header class="header">
202
200
  <nav aria-label="${this.localize('components.page.header-nav-label')}">
203
- <slot name="header" @slotchange="${this.#handleHeaderSlotChange}"></slot>
201
+ <slot name="header"></slot>
204
202
  </nav>
205
203
  </header>
206
204
  `;
@@ -12266,7 +12266,6 @@
12266
12266
  {
12267
12267
  "name": "d2l-page-demo",
12268
12268
  "path": "./components/page/demo/page-component.js",
12269
- "description": "Component for d2l-page demos and tests",
12270
12269
  "properties": [
12271
12270
  {
12272
12271
  "name": "properties",
@@ -12276,7 +12275,7 @@
12276
12275
  {
12277
12276
  "name": "styles",
12278
12277
  "type": "CSSResult[]",
12279
- "default": "[\"navStyles\",\"selectStyles\",\"tableStyles\",null]"
12278
+ "default": "[\"selectStyles\",\"tableStyles\",null]"
12280
12279
  },
12281
12280
  {
12282
12281
  "name": "demoMode",
@@ -12325,6 +12324,17 @@
12325
12324
  }
12326
12325
  ]
12327
12326
  },
12327
+ {
12328
+ "name": "d2l-page-header-full-demo",
12329
+ "path": "./components/page/demo/page-header-full.js",
12330
+ "properties": [
12331
+ {
12332
+ "name": "styles",
12333
+ "type": "CSSResult",
12334
+ "default": "\"css`\\n\\t\\t.full-nav-header {\\n\\t\\t\\talign-items: center;\\n\\t\\t\\tdisplay: flex;\\n\\t\\t\\theight: 90px;\\n\\t\\t}\\n\\t\\t.full-nav-header-left {\\n\\t\\t\\talign-items: center;\\n\\t\\t\\tdisplay: flex;\\n\\t\\t\\tflex: 0 1 auto;\\n\\t\\t\\tgap: 5px;\\n\\t\\t\\theight: 100%;\\n\\t\\t}\\n\\t\\t.full-nav-header-spacer {\\n\\t\\t\\tflex: 1 1 auto;\\n\\t\\t\\tmin-width: 30px;\\n\\t\\t}\\n\\t\\t.full-nav-header-right {\\n\\t\\t\\talign-items: center;\\n\\t\\t\\tdisplay: flex;\\n\\t\\t\\tflex: 0 0 auto;\\n\\t\\t\\theight: 100%;\\n\\t\\t}\\n\\t\\t.full-nav-header-right d2l-page-header-button {\\n\\t\\t\\tmargin-inline: 15px;\\n\\t\\t}\\n\\t\\t.full-nav-logo {\\n\\t\\t\\tbackground-color: var(--d2l-color-celestine);\\n\\t\\t\\tborder-radius: 4px;\\n\\t\\t\\tcolor: white;\\n\\t\\t\\tfont-size: 0.8rem;\\n\\t\\t\\tfont-weight: 700;\\n\\t\\t\\tpadding: 8px 14px;\\n\\t\\t}\\n\\t\\t.full-nav-footer-inner {\\n\\t\\t\\talign-items: center;\\n\\t\\t\\tdisplay: flex;\\n\\t\\t\\tflex-wrap: wrap;\\n\\t\\t\\tgap: 20px;\\n\\t\\t}\\n\\t\\t.full-nav-footer-link {\\n\\t\\t\\tborder-bottom: 4px solid transparent;\\n\\t\\t\\tcolor: var(--d2l-color-ferrite);\\n\\t\\t\\tdisplay: inline-block;\\n\\t\\t\\tpadding: 8px 0;\\n\\t\\t\\ttext-decoration: none;\\n\\t\\t}\\n\\t\\t.full-nav-footer-link:hover,\\n\\t\\t.full-nav-footer-link:focus-visible {\\n\\t\\t\\tborder-bottom-color: var(--d2l-color-celestine);\\n\\t\\t\\tcolor: var(--d2l-color-celestine);\\n\\t\\t}\\n\\t`\""
12335
+ }
12336
+ ]
12337
+ },
12328
12338
  {
12329
12339
  "name": "d2l-page-footer",
12330
12340
  "path": "./components/page/page-footer.js",
@@ -12469,6 +12479,55 @@
12469
12479
  }
12470
12480
  ]
12471
12481
  },
12482
+ {
12483
+ "name": "d2l-page-header-immersive",
12484
+ "path": "./components/page/page-header-immersive.js",
12485
+ "attributes": [
12486
+ {
12487
+ "name": "back-href",
12488
+ "type": "string"
12489
+ },
12490
+ {
12491
+ "name": "back-custom-text",
12492
+ "type": "string"
12493
+ },
12494
+ {
12495
+ "name": "title-text",
12496
+ "type": "string"
12497
+ },
12498
+ {
12499
+ "name": "subtitle-text",
12500
+ "type": "string"
12501
+ }
12502
+ ],
12503
+ "properties": [
12504
+ {
12505
+ "name": "backHref",
12506
+ "attribute": "back-href",
12507
+ "type": "string"
12508
+ },
12509
+ {
12510
+ "name": "backCustomText",
12511
+ "attribute": "back-custom-text",
12512
+ "type": "string"
12513
+ },
12514
+ {
12515
+ "name": "titleText",
12516
+ "attribute": "title-text",
12517
+ "type": "string"
12518
+ },
12519
+ {
12520
+ "name": "subtitleText",
12521
+ "attribute": "subtitle-text",
12522
+ "type": "string"
12523
+ }
12524
+ ],
12525
+ "events": [
12526
+ {
12527
+ "name": "d2l-page-header-immersive-back-click"
12528
+ }
12529
+ ]
12530
+ },
12472
12531
  {
12473
12532
  "name": "d2l-page-header-separator",
12474
12533
  "path": "./components/page/page-header-separator.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.249.0",
3
+ "version": "3.250.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",
@@ -66,7 +66,7 @@
66
66
  "rollup-plugin-copy": "^3",
67
67
  "rollup-plugin-delete": "^3",
68
68
  "sass": "^1",
69
- "sinon": "^21",
69
+ "sinon": "^22",
70
70
  "stylelint": "^17",
71
71
  "web-component-analyzer": "^2"
72
72
  },