@vaadin/app-layout 24.6.5 → 24.7.0-alpha10

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/app-layout",
3
- "version": "24.6.5",
3
+ "version": "24.7.0-alpha10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -35,18 +35,19 @@
35
35
  "polymer"
36
36
  ],
37
37
  "dependencies": {
38
+ "@open-wc/dedupe-mixin": "^1.3.0",
38
39
  "@polymer/polymer": "^3.0.0",
39
- "@vaadin/a11y-base": "~24.6.5",
40
- "@vaadin/button": "~24.6.5",
41
- "@vaadin/component-base": "~24.6.5",
42
- "@vaadin/vaadin-lumo-styles": "~24.6.5",
43
- "@vaadin/vaadin-material-styles": "~24.6.5",
44
- "@vaadin/vaadin-themable-mixin": "~24.6.5",
40
+ "@vaadin/a11y-base": "24.7.0-alpha10",
41
+ "@vaadin/button": "24.7.0-alpha10",
42
+ "@vaadin/component-base": "24.7.0-alpha10",
43
+ "@vaadin/vaadin-lumo-styles": "24.7.0-alpha10",
44
+ "@vaadin/vaadin-material-styles": "24.7.0-alpha10",
45
+ "@vaadin/vaadin-themable-mixin": "24.7.0-alpha10",
45
46
  "lit": "^3.0.0"
46
47
  },
47
48
  "devDependencies": {
48
- "@vaadin/chai-plugins": "~24.6.5",
49
- "@vaadin/test-runner-commands": "~24.6.5",
49
+ "@vaadin/chai-plugins": "24.7.0-alpha10",
50
+ "@vaadin/test-runner-commands": "24.7.0-alpha10",
50
51
  "@vaadin/testing-helpers": "^1.1.0",
51
52
  "sinon": "^18.0.0"
52
53
  },
@@ -54,5 +55,5 @@
54
55
  "web-types.json",
55
56
  "web-types.lit.json"
56
57
  ],
57
- "gitHead": "fc109a4234a1f60e89717ab1c0dc8fb4451aa418"
58
+ "gitHead": "c0f8933df2a6a40648d3fb9cfbae6bbf86a8aa90"
58
59
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2018 - 2024 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { isIOS } from '@vaadin/component-base/src/browser-utils.js';
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 2025 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { I18nMixinClass, PartialI18n } from '@vaadin/component-base/src/i18n-mixin.js';
8
+
9
+ export type AppLayoutI18n = PartialI18n<{
10
+ drawer: string;
11
+ }>;
12
+
13
+ export declare function AppLayoutMixin<T extends Constructor<HTMLElement>>(
14
+ base: T,
15
+ ): Constructor<AppLayoutMixinClass> & Constructor<I18nMixinClass<AppLayoutI18n>> & T;
16
+
17
+ export declare class AppLayoutMixinClass {
18
+ /**
19
+ * The object used to localize this component. To change the default
20
+ * localization, replace this with an object that provides all properties, or
21
+ * just the individual properties you want to change.
22
+ *
23
+ * The object has the following structure and default values:
24
+ * ```
25
+ * {
26
+ * drawer: 'Drawer'
27
+ * }
28
+ * ```
29
+ */
30
+ i18n: AppLayoutI18n;
31
+
32
+ /**
33
+ * Defines whether navbar or drawer will come first visually.
34
+ * - By default (`primary-section="navbar"`), the navbar takes the full available width and moves the drawer down.
35
+ * - If `primary-section="drawer"` is set, then the drawer will move the navbar, taking the full available height.
36
+ * @attr {navbar|drawer} primary-section
37
+ */
38
+ primarySection: 'drawer' | 'navbar';
39
+
40
+ /**
41
+ * Controls whether the drawer is opened (visible) or not.
42
+ * Its default value depends on the viewport:
43
+ * - `true`, for desktop size views
44
+ * - `false`, for mobile size views
45
+ * @attr {boolean} drawer-opened
46
+ */
47
+ drawerOpened: boolean;
48
+
49
+ /**
50
+ * Drawer is an overlay on top of the content
51
+ * Controlled via CSS using `--vaadin-app-layout-drawer-overlay: true|false`;
52
+ */
53
+ readonly overlay: boolean;
54
+
55
+ /**
56
+ * A global event that causes the drawer to close (be hidden) when it is in overlay mode.
57
+ * - The default is `vaadin-router-location-changed` dispatched by Vaadin Router
58
+ *
59
+ * @attr {string} close-drawer-on
60
+ */
61
+ closeDrawerOn: string;
62
+ }
@@ -0,0 +1,526 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 2025 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { afterNextRender, beforeNextRender } from '@polymer/polymer/lib/utils/render-status.js';
7
+ import { AriaModalController } from '@vaadin/a11y-base/src/aria-modal-controller.js';
8
+ import { FocusTrapController } from '@vaadin/a11y-base/src/focus-trap-controller.js';
9
+ import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
10
+
11
+ /**
12
+ * @typedef {import('./vaadin-app-layout.js').AppLayoutI18n} AppLayoutI18n
13
+ */
14
+
15
+ const DEFAULT_I18N = {
16
+ drawer: 'Drawer',
17
+ };
18
+
19
+ /**
20
+ * @polymerMixin
21
+ * @mixes I18nMixin
22
+ */
23
+ export const AppLayoutMixin = (superclass) =>
24
+ class AppLayoutMixinClass extends I18nMixin(DEFAULT_I18N, superclass) {
25
+ static get properties() {
26
+ return {
27
+ /**
28
+ * Defines whether navbar or drawer will come first visually.
29
+ * - By default (`primary-section="navbar"`), the navbar takes the full available width and moves the drawer down.
30
+ * - If `primary-section="drawer"` is set, then the drawer will move the navbar, taking the full available height.
31
+ * @attr {navbar|drawer} primary-section
32
+ * @type {!PrimarySection}
33
+ */
34
+ primarySection: {
35
+ type: String,
36
+ value: 'navbar',
37
+ notify: true,
38
+ reflectToAttribute: true,
39
+ observer: '__primarySectionChanged',
40
+ sync: true,
41
+ },
42
+
43
+ /**
44
+ * Controls whether the drawer is opened (visible) or not.
45
+ * Its default value depends on the viewport:
46
+ * - `true`, for desktop size views
47
+ * - `false`, for mobile size views
48
+ * @attr {boolean} drawer-opened
49
+ * @type {boolean}
50
+ */
51
+ drawerOpened: {
52
+ type: Boolean,
53
+ notify: true,
54
+ value: true,
55
+ reflectToAttribute: true,
56
+ observer: '__drawerOpenedChanged',
57
+ sync: true,
58
+ },
59
+
60
+ /**
61
+ * Drawer is an overlay on top of the content
62
+ * Controlled via CSS using `--vaadin-app-layout-drawer-overlay: true|false`;
63
+ * @type {boolean}
64
+ */
65
+ overlay: {
66
+ type: Boolean,
67
+ notify: true,
68
+ readOnly: true,
69
+ value: false,
70
+ reflectToAttribute: true,
71
+ sync: true,
72
+ },
73
+
74
+ /**
75
+ * A global event that causes the drawer to close (be hidden) when it is in overlay mode.
76
+ * - The default is `vaadin-router-location-changed` dispatched by Vaadin Router
77
+ *
78
+ * @attr {string} close-drawer-on
79
+ * @type {string}
80
+ */
81
+ closeDrawerOn: {
82
+ type: String,
83
+ value: 'vaadin-router-location-changed',
84
+ observer: '_closeDrawerOnChanged',
85
+ },
86
+ };
87
+ }
88
+
89
+ static get observers() {
90
+ return ['__i18nChanged(__effectiveI18n)'];
91
+ }
92
+
93
+ /**
94
+ * Helper static method that dispatches a `close-overlay-drawer` event
95
+ */
96
+ static dispatchCloseOverlayDrawerEvent() {
97
+ window.dispatchEvent(new CustomEvent('close-overlay-drawer'));
98
+ }
99
+
100
+ /**
101
+ * The object used to localize this component. To change the default
102
+ * localization, replace this with an object that provides all properties, or
103
+ * just the individual properties you want to change.
104
+ *
105
+ * The object has the following structure and default values:
106
+ * ```
107
+ * {
108
+ * drawer: 'Drawer'
109
+ * }
110
+ * ```
111
+ * @return {!AppLayoutI18n}
112
+ */
113
+ get i18n() {
114
+ return super.i18n;
115
+ }
116
+
117
+ set i18n(value) {
118
+ super.i18n = value;
119
+ }
120
+
121
+ constructor() {
122
+ super();
123
+ // TODO(jouni): might want to debounce
124
+ this.__boundResizeListener = this._resize.bind(this);
125
+ this.__drawerToggleClickListener = this._drawerToggleClick.bind(this);
126
+ this.__onDrawerKeyDown = this.__onDrawerKeyDown.bind(this);
127
+ this.__closeOverlayDrawerListener = this.__closeOverlayDrawer.bind(this);
128
+ this.__trapFocusInDrawer = this.__trapFocusInDrawer.bind(this);
129
+ this.__releaseFocusFromDrawer = this.__releaseFocusFromDrawer.bind(this);
130
+
131
+ // Hide all the elements except the drawer toggle and drawer content
132
+ this.__ariaModalController = new AriaModalController(this, () => [
133
+ ...this.querySelectorAll('vaadin-drawer-toggle, [slot="drawer"]'),
134
+ ]);
135
+ this.__focusTrapController = new FocusTrapController(this);
136
+ }
137
+
138
+ /** @protected */
139
+ connectedCallback() {
140
+ super.connectedCallback();
141
+
142
+ this._blockAnimationUntilAfterNextRender();
143
+
144
+ window.addEventListener('resize', this.__boundResizeListener);
145
+ this.addEventListener('drawer-toggle-click', this.__drawerToggleClickListener);
146
+
147
+ beforeNextRender(this, this._afterFirstRender);
148
+
149
+ this._updateTouchOptimizedMode();
150
+ this._updateDrawerSize();
151
+ this._updateOverlayMode();
152
+
153
+ this._navbarSizeObserver = new ResizeObserver(() => {
154
+ requestAnimationFrame(() => {
155
+ // Prevent updating offset size multiple times
156
+ // during the drawer open / close transition.
157
+ if (this.__isDrawerAnimating) {
158
+ this.__updateOffsetSizePending = true;
159
+ } else {
160
+ this._updateOffsetSize();
161
+ }
162
+ });
163
+ });
164
+ this._navbarSizeObserver.observe(this.$.navbarTop);
165
+ this._navbarSizeObserver.observe(this.$.navbarBottom);
166
+
167
+ window.addEventListener('close-overlay-drawer', this.__closeOverlayDrawerListener);
168
+ window.addEventListener('keydown', this.__onDrawerKeyDown);
169
+ }
170
+
171
+ /** @protected */
172
+ ready() {
173
+ super.ready();
174
+ this.addController(this.__focusTrapController);
175
+ this.__setAriaExpanded();
176
+
177
+ this.$.drawer.addEventListener('transitionstart', () => {
178
+ this.__isDrawerAnimating = true;
179
+ });
180
+
181
+ this.$.drawer.addEventListener('transitionend', () => {
182
+ // Update offset size after drawer animation.
183
+ if (this.__updateOffsetSizePending) {
184
+ this.__updateOffsetSizePending = false;
185
+ this._updateOffsetSize();
186
+ }
187
+
188
+ // Delay resetting the flag until animation frame
189
+ // to avoid updating offset size again on resize.
190
+ requestAnimationFrame(() => {
191
+ this.__isDrawerAnimating = false;
192
+ });
193
+ });
194
+ }
195
+
196
+ /** @protected */
197
+ disconnectedCallback() {
198
+ super.disconnectedCallback();
199
+
200
+ window.removeEventListener('resize', this.__boundResizeListener);
201
+ this.removeEventListener('drawer-toggle-click', this.__drawerToggleClickListener);
202
+ window.removeEventListener('close-overlay-drawer', this.__drawerToggleClickListener);
203
+ window.removeEventListener('keydown', this.__onDrawerKeyDown);
204
+ }
205
+
206
+ /**
207
+ * A callback for the `primarySection` property observer.
208
+ *
209
+ * Ensures the property is set to its default value `navbar`
210
+ * whenever the new value is not one of the valid values: `navbar`, `drawer`.
211
+ *
212
+ * @param {string} value
213
+ * @private
214
+ */
215
+ __primarySectionChanged(value) {
216
+ const isValid = ['navbar', 'drawer'].includes(value);
217
+ if (!isValid) {
218
+ this.primarySection = 'navbar';
219
+ }
220
+ }
221
+
222
+ /**
223
+ * A callback for the `drawerOpened` property observer.
224
+ *
225
+ * When the drawer opens, the method ensures the drawer has a proper height and sets focus on it.
226
+ * As long as the drawer is open, the focus is trapped within the drawer.
227
+ *
228
+ * When the drawer closes, the method releases focus from the drawer, setting focus on the drawer toggle.
229
+ *
230
+ * @param {boolean} drawerOpened
231
+ * @param {boolean} oldDrawerOpened
232
+ * @private
233
+ */
234
+ __drawerOpenedChanged(drawerOpened, oldDrawerOpened) {
235
+ if (this.overlay) {
236
+ if (drawerOpened) {
237
+ this.__trapFocusInDrawer();
238
+ } else if (oldDrawerOpened) {
239
+ this.__releaseFocusFromDrawer();
240
+ }
241
+ }
242
+
243
+ this.__setAriaExpanded();
244
+ }
245
+
246
+ /**
247
+ * A callback for the `i18n` property observer.
248
+ *
249
+ * The method ensures the drawer has ARIA attributes updated
250
+ * once the `i18n` property changes.
251
+ *
252
+ * @private
253
+ */
254
+ __i18nChanged() {
255
+ this.__updateDrawerAriaAttributes();
256
+ }
257
+
258
+ /** @protected */
259
+ _afterFirstRender() {
260
+ this._blockAnimationUntilAfterNextRender();
261
+ this._updateOffsetSize();
262
+ }
263
+
264
+ /** @private */
265
+ _drawerToggleClick(e) {
266
+ e.stopPropagation();
267
+ this.drawerOpened = !this.drawerOpened;
268
+ }
269
+
270
+ /** @private */
271
+ __closeOverlayDrawer() {
272
+ if (this.overlay) {
273
+ this.drawerOpened = false;
274
+ }
275
+ }
276
+
277
+ /** @private */
278
+ __setAriaExpanded() {
279
+ const toggle = this.querySelector('vaadin-drawer-toggle');
280
+ if (toggle) {
281
+ toggle.setAttribute('aria-expanded', this.drawerOpened);
282
+ }
283
+ }
284
+
285
+ /** @protected */
286
+ _updateDrawerSize() {
287
+ const childCount = this.querySelectorAll('[slot=drawer]').length;
288
+ const drawer = this.$.drawer;
289
+
290
+ if (childCount === 0) {
291
+ drawer.setAttribute('hidden', '');
292
+ this.style.setProperty('--_vaadin-app-layout-drawer-width', 0);
293
+ } else {
294
+ drawer.removeAttribute('hidden');
295
+ this.style.removeProperty('--_vaadin-app-layout-drawer-width');
296
+ }
297
+ this._updateOffsetSize();
298
+ }
299
+
300
+ /** @private */
301
+ _resize() {
302
+ this._blockAnimationUntilAfterNextRender();
303
+ this._updateTouchOptimizedMode();
304
+ this._updateOverlayMode();
305
+ }
306
+
307
+ /** @protected */
308
+ _updateOffsetSize() {
309
+ const navbar = this.$.navbarTop;
310
+ const navbarRect = navbar.getBoundingClientRect();
311
+
312
+ const navbarBottom = this.$.navbarBottom;
313
+ const navbarBottomRect = navbarBottom.getBoundingClientRect();
314
+
315
+ const drawer = this.$.drawer;
316
+ const drawerRect = drawer.getBoundingClientRect();
317
+
318
+ this.style.setProperty('--_vaadin-app-layout-navbar-offset-size', `${navbarRect.height}px`);
319
+ this.style.setProperty('--_vaadin-app-layout-navbar-offset-size-bottom', `${navbarBottomRect.height}px`);
320
+ this.style.setProperty('--_vaadin-app-layout-drawer-offset-size', `${drawerRect.width}px`);
321
+ }
322
+
323
+ /** @protected */
324
+ _updateOverlayMode() {
325
+ const overlay = this._getCustomPropertyValue('--vaadin-app-layout-drawer-overlay') === 'true';
326
+
327
+ if (!this.overlay && overlay) {
328
+ // Changed from not overlay to overlay
329
+ this._drawerStateSaved = this.drawerOpened;
330
+ this.drawerOpened = false;
331
+ }
332
+
333
+ this._setOverlay(overlay);
334
+
335
+ if (!this.overlay && this._drawerStateSaved) {
336
+ this.drawerOpened = this._drawerStateSaved;
337
+ this._drawerStateSaved = null;
338
+ }
339
+
340
+ this.__updateDrawerAriaAttributes();
341
+ }
342
+
343
+ /**
344
+ * Updates ARIA attributes on the drawer depending on the drawer mode.
345
+ *
346
+ * - In the overlay mode, the method marks the drawer with ARIA attributes as a dialog
347
+ * labelled with the `i18n.drawer` property.
348
+ * - In the normal mode, the method removes the ARIA attributes that has been set for the overlay mode.
349
+ *
350
+ * @private
351
+ */
352
+ __updateDrawerAriaAttributes() {
353
+ const drawer = this.$.drawer;
354
+ if (this.overlay) {
355
+ drawer.setAttribute('role', 'dialog');
356
+ drawer.setAttribute('aria-modal', 'true');
357
+ drawer.setAttribute('aria-label', this.__effectiveI18n.drawer);
358
+ } else {
359
+ drawer.removeAttribute('role');
360
+ drawer.removeAttribute('aria-modal');
361
+ drawer.removeAttribute('aria-label');
362
+ }
363
+ }
364
+
365
+ /**
366
+ * Returns a promise that resolves when the drawer opening/closing CSS transition ends.
367
+ *
368
+ * The method relies on the `--vaadin-app-layout-transition` CSS variable to detect whether
369
+ * the drawer has a CSS transition that needs to be awaited. If the CSS variable equals `none`,
370
+ * the promise resolves immediately.
371
+ *
372
+ * @return {Promise}
373
+ * @private
374
+ */
375
+ __drawerTransitionComplete() {
376
+ return new Promise((resolve) => {
377
+ if (this._getCustomPropertyValue('--vaadin-app-layout-transition') === 'none') {
378
+ resolve();
379
+ return;
380
+ }
381
+
382
+ this.$.drawer.addEventListener('transitionend', resolve, { once: true });
383
+ });
384
+ }
385
+
386
+ /** @private */
387
+ async __trapFocusInDrawer() {
388
+ // Wait for the drawer CSS transition before focusing the drawer
389
+ // in order for VoiceOver to have a proper outline.
390
+ await this.__drawerTransitionComplete();
391
+
392
+ if (!this.drawerOpened) {
393
+ // The drawer has been closed during the CSS transition.
394
+ return;
395
+ }
396
+
397
+ this.$.drawer.setAttribute('tabindex', '0');
398
+
399
+ this.__ariaModalController.showModal();
400
+ this.__focusTrapController.trapFocus(this.$.drawer);
401
+ }
402
+
403
+ /** @private */
404
+ async __releaseFocusFromDrawer() {
405
+ // Wait for the drawer CSS transition in order to restore focus to the toggle
406
+ // only after `visibility` becomes `hidden`, that is, the drawer becomes inaccessible by the tabbing navigation.
407
+ await this.__drawerTransitionComplete();
408
+
409
+ if (this.drawerOpened) {
410
+ // The drawer has been opened during the CSS transition.
411
+ return;
412
+ }
413
+
414
+ this.__ariaModalController.close();
415
+ this.__focusTrapController.releaseFocus();
416
+ this.$.drawer.removeAttribute('tabindex');
417
+
418
+ // Move focus to the drawer toggle when closing the drawer.
419
+ const toggle = this.querySelector('vaadin-drawer-toggle');
420
+ if (toggle) {
421
+ toggle.focus();
422
+ toggle.setAttribute('focus-ring', 'focus');
423
+ }
424
+ }
425
+
426
+ /**
427
+ * Closes the drawer on Escape press if it has been opened in the overlay mode.
428
+ *
429
+ * @param {KeyboardEvent} event
430
+ * @private
431
+ */
432
+ __onDrawerKeyDown(event) {
433
+ if (event.key === 'Escape' && this.overlay) {
434
+ this.drawerOpened = false;
435
+ }
436
+ }
437
+
438
+ /** @private */
439
+ _closeDrawerOnChanged(closeDrawerOn, oldCloseDrawerOn) {
440
+ if (oldCloseDrawerOn) {
441
+ window.removeEventListener(oldCloseDrawerOn, this.__closeOverlayDrawerListener);
442
+ }
443
+ if (closeDrawerOn) {
444
+ window.addEventListener(closeDrawerOn, this.__closeOverlayDrawerListener);
445
+ }
446
+ }
447
+
448
+ /** @private */
449
+ _onBackdropClick() {
450
+ this._close();
451
+ }
452
+
453
+ /** @private */
454
+ _onBackdropTouchend(event) {
455
+ // Prevent the click event from being fired
456
+ // on clickable element behind the backdrop
457
+ event.preventDefault();
458
+
459
+ this._close();
460
+ }
461
+
462
+ /** @protected */
463
+ _close() {
464
+ this.drawerOpened = false;
465
+ }
466
+
467
+ /** @private */
468
+ _getCustomPropertyValue(customProperty) {
469
+ const customPropertyValue = getComputedStyle(this).getPropertyValue(customProperty);
470
+ return (customPropertyValue || '').trim().toLowerCase();
471
+ }
472
+
473
+ /** @protected */
474
+ _updateTouchOptimizedMode() {
475
+ const touchOptimized = this._getCustomPropertyValue('--vaadin-app-layout-touch-optimized') === 'true';
476
+
477
+ const navbarItems = this.querySelectorAll('[slot*="navbar"]');
478
+
479
+ if (navbarItems.length > 0) {
480
+ Array.from(navbarItems).forEach((navbar) => {
481
+ if (navbar.getAttribute('slot').indexOf('touch-optimized') > -1) {
482
+ navbar.__touchOptimized = true;
483
+ }
484
+
485
+ if (touchOptimized && navbar.__touchOptimized) {
486
+ navbar.setAttribute('slot', 'navbar-bottom');
487
+ } else {
488
+ navbar.setAttribute('slot', 'navbar');
489
+ }
490
+ });
491
+ }
492
+
493
+ if (this.$.navbarTop.querySelector('[name=navbar]').assignedNodes().length === 0) {
494
+ this.$.navbarTop.setAttribute('hidden', '');
495
+ } else {
496
+ this.$.navbarTop.removeAttribute('hidden');
497
+ }
498
+
499
+ if (this.$.navbarBottom.querySelector('[name=navbar-bottom]').assignedNodes().length === 0) {
500
+ this.$.navbarBottom.setAttribute('hidden', '');
501
+ } else {
502
+ this.$.navbarBottom.removeAttribute('hidden');
503
+ }
504
+
505
+ this._updateOffsetSize();
506
+ }
507
+
508
+ /** @protected */
509
+ _blockAnimationUntilAfterNextRender() {
510
+ this.setAttribute('no-anim', '');
511
+ afterNextRender(this, () => {
512
+ this.removeAttribute('no-anim');
513
+ });
514
+ }
515
+
516
+ /**
517
+ * App Layout listens to `close-overlay-drawer` on the window level.
518
+ * A custom event can be dispatched and the App Layout will close the drawer in overlay.
519
+ *
520
+ * That can be used, for instance, when a navigation occurs when user clicks in a menu item inside the drawer.
521
+ *
522
+ * See `dispatchCloseOverlayDrawerEvent()` helper method.
523
+ *
524
+ * @event close-overlay-drawer
525
+ */
526
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 2025 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import type { CSSResult } from 'lit';
7
+
8
+ export const appLayoutStyles: CSSResult;