Compare commits

...

12 Commits

Author SHA1 Message Date
konnorrogers
123d32f00a prettier 2024-12-10 13:45:47 -05:00
konnorrogers
8b3db8fa14 minor fixes 2024-12-10 13:45:35 -05:00
konnorrogers
e96d7362b3 Add comment 2024-12-10 13:30:20 -05:00
konnorrogers
ccc204fdd4 prettier 2024-12-10 13:28:01 -05:00
konnorrogers
0cc98fda8b fix up page stuff 2024-12-10 13:27:46 -05:00
konnorrogers
525ba6edce prettier 2024-12-10 12:58:04 -05:00
konnorrogers
efd5576b49 add comments / docs 2024-12-10 12:57:20 -05:00
konnorrogers
f175745dfd prettier 2024-12-10 12:38:32 -05:00
konnorrogers
69d1ddde8d fix comments 2024-12-10 12:38:18 -05:00
konnorrogers
64ba44549f fix comments 2024-12-10 12:36:19 -05:00
konnorrogers
1a7cac6265 Merge branch 'next' of https://github.com/shoelace-style/webawesome into konnorrogers/add-layout-toggling 2024-12-10 12:34:35 -05:00
konnorrogers
20ba055c3a Add nav toggling 2024-12-10 12:34:28 -05:00
5 changed files with 79 additions and 6 deletions

View File

@@ -85,7 +85,7 @@
</head>
<body class="layout-{{ layout | stripExtension }}">
<!-- use view="desktop" as default to reduce layout jank on desktop site. -->
<wa-page view="desktop">
<wa-page view="desktop" disable-navigation-toggle="">
<header slot="header">
{# Logo #}
<div id="docs-branding">
@@ -93,6 +93,7 @@
<wa-button appearance="text" size="small" data-toggle-nav>
<wa-icon name="bars" label="Toggle navigation"></wa-icon>
</wa-button>
<a href="/" aria-label="Web Awesome">
<span class="only-desktop">{% include "logo.njk" %}</span>
<span class="only-mobile">{% include "logo-simple.njk" %}</span>

View File

@@ -6,7 +6,7 @@
<legend>Slots</legend>
<div class="options">
{% for slot in slots %}
{% if slot.name != "skip-to-content" %}
{% if (slot.name != "skip-to-content") and (slot.name != "navigation-toggle-icon") %}
<wa-checkbox name="slot" value="{{ slot.name }}" {{ 'checked' if slot.name != "menu" | safe}} class="{{ 'default' if not slot.name }}"
data-description="{{ slot.description | inlineMarkdown }}" title="{{ slot.description | inlineMarkdown | striptags | safe }}">
{{ slot.name or "(default)" }}

View File

@@ -46,7 +46,7 @@ The following sections of a page are "sticky" by default, meaning they remain in
- `banner`
- `header`
- `sub-header`
- `navigation` (or `menu`)
- `menu` (`navigation` itself is not sticky, but its parent `menu` is)
- `aside`
This is often desirable, but you can change this behavior using the `disable-sticky` attribute. Use a space-delimited list of names to tell the page which sections should not be sticky.
@@ -795,4 +795,4 @@ A sample media app page using `header`, `navigation-header`, `main-header`, and
padding: 1.5rem;
}
</style>
```
```

View File

@@ -48,6 +48,7 @@ export default css`
flex-wrap: wrap;
gap: var(--wa-space-m);
padding: var(--wa-space-m);
flex: 1 1 auto;
}
::slotted([slot='subheader']) {
@@ -169,6 +170,12 @@ export default css`
}
[part~='header'] {
top: var(--banner-height);
/** Make the header flex so that you don't unexpectedly have the default toggle button appearing above a slotted div because block elements are fun. */
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
[part~='subheader'] {
top: calc(var(--header-height) + var(--banner-height));
@@ -246,12 +253,34 @@ export default css`
[part~='drawer']::part(dialog) {
background-color: var(--wa-color-surface-default);
}
/* Set these on the slot because we don't always control the navigation-toggle since that may be slotted. */
slot[name~='navigation-toggle'],
:host([disable-navigation-toggle]) slot[name~='navigation-toggle'] {
display: none;
}
/* Sometimes the media query in the viewport is stubborn in iframes. This is an extra check to make it behave properly. */
:host(:not([disable-navigation-toggle])[view='mobile']) slot[name~='navigation-toggle'] {
display: contents;
}
[part~='navigation-toggle'] {
/* Use only a margin-inline-start because the slotted header is expected to have default padding so it looks really awkward if this sets a margin-inline-end and the slotted header has a padding-inline-start. */
margin-inline-start: var(--wa-space-m);
}
`;
export const mobileStyles = (breakpoint: number) => `
@media screen and (
max-width: ${(Number.isSafeInteger(breakpoint) ? breakpoint.toString() : '768') + 'px'}
) {
[part~='navigation'] { display: none; }
[part~='navigation'] {
display: none;
}
:host(:not([disable-navigation-toggle])) slot[name~='navigation-toggle'] {
display: contents;
}
}
`;

View File

@@ -36,6 +36,8 @@ if (typeof ResizeObserver === 'undefined') {
* @slot navigation-header - The header for a navigation area. On mobile this will be the header for `<wa-drawer>`.
* @slot navigation - The main content to display in the navigation area. This is displayed on the left side of the page, if `menu` is not used. This section "sticks" to the top as the page scrolls.
* @slot navigation-footer - The footer for a navigation area. On mobile this will be the footer for `<wa-drawer>`.
* @slot navigation-toggle - Use this slot to slot in your own button + icon for toggling the navigation drawer. By default it is a `<wa-button>` + a 3 bars `<wa-icon>`
* @slot navigation-toggle-icon - Use this to slot in your own icon for toggling the navigation drawer. By default it is 3 bars `<wa-icon>`.
* @slot main-header - Header to display inline above the main content.
* @slot main-footer - Footer to display inline below the main content.
* @slot aside - Content to be shown on the right side of the page. Typically contains a table of contents, ads, etc. This section "sticks" to the top as the page scrolls.
@@ -48,8 +50,11 @@ if (typeof ResizeObserver === 'undefined') {
* @csspart subheader - Shown below the header, usually intended for things like breadcrumbs and other page level navigation.
* @csspart body - The wrapper around menu, main, and aside.
* @csspart menu - The left hand side of the page. Generally intended for navigation.
* @csspart navigation - The `<nav>` that wraps the navigation slots on desktop viewports.
* @csspart navigation-header - The header for a navigation area. On mobile this will be the header for `<wa-drawer>`.
* @csspart navigation-footer - The footer for a navigation area. On mobile this will be the footer for `<wa-drawer>`.
* @csspart navigation-toggle - The default `<wa-button>` that will toggle the `<wa-drawer>` for mobile viewports.
* @csspart navigation-toggle-icon - The default `<wa-icon>` displayed inside of the navigation-toggle button.
* @csspart main-header - The header above main content.
* @csspart main-content - The main content.
* @csspart main-footer - The footer below main content.
@@ -89,10 +94,24 @@ export default class WaPage extends WebAwesomeElement {
private handleNavigationToggle = (e: Event) => {
// Don't toggle the nav when we're in desktop mode
if (this.view === 'desktop') {
// Just in case, try to hide the navigation.
this.hideNavigation();
return;
}
if (e.composedPath().find((el: Element) => el.hasAttribute?.('data-toggle-nav'))) {
const path = e.composedPath();
const navigationToggleSlot = this.navigationToggleSlot;
if (
path.find((el: Element) => {
return (
el.hasAttribute?.('data-toggle-nav') ||
el.assignedSlot === navigationToggleSlot ||
el === navigationToggleSlot
);
})
) {
e.preventDefault();
this.toggleNavigation();
}
@@ -103,6 +122,7 @@ export default class WaPage extends WebAwesomeElement {
@query("[part~='footer']") footer: HTMLElement;
@query("[part~='banner']") banner: HTMLElement;
@query("[part~='drawer']") navigationDrawer: WaDrawer;
@query("slot[name~='navigation-toggle']") navigationToggleSlot: HTMLSlotElement;
/**
* The view is a reflection of the "mobileBreakpoint", when the page is larger than the `mobile-breakpoint` (768px by
@@ -127,6 +147,12 @@ export default class WaPage extends WebAwesomeElement {
*/
@property({ attribute: 'navigation-placement', reflect: true }) navigationPlacement: 'start' | 'end' = 'start';
/**
* Determines whether or not to hide the default hamburger button. This will automatically flip to "true" if you add an element with `data-toggle-nav` anywhere in the element light DOM. Generally this will be set for you and you don't need to do anything, unless you're using SSR, in which case you should set this manually for initial page loads.
*/
@property({ attribute: 'disable-navigation-toggle', reflect: true, type: Boolean }) disableNavigationToggle: boolean =
false;
pageResizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
if (entry.contentBoxSize) {
@@ -168,11 +194,21 @@ export default class WaPage extends WebAwesomeElement {
this.pageResizeObserver.observe(this);
const navQuery = ":not([slot='toggle-navigation']) [data-toggle-nav]";
// check once on initial connect
// eslint-disable-next-line
this.disableNavigationToggle = Boolean(this.querySelector(navQuery));
setTimeout(() => {
this.headerResizeObserver.observe(this.header);
this.subheaderResizeObserver.observe(this.subheader);
this.bannerResizeObserver.observe(this.banner);
this.footerResizeObserver.observe(this.footer);
// Check again when the element updates
// eslint-disable-next-line
this.disableNavigationToggle = Boolean(this.querySelector(navQuery));
});
}
@@ -235,6 +271,13 @@ export default class WaPage extends WebAwesomeElement {
<slot name="banner"></slot>
</div>
<div class="header" part="header">
<slot name="navigation-toggle">
<wa-button part="navigation-toggle" size="small" appearance="text" variant="neutral">
<slot name="navigation-toggle-icon">
<wa-icon name="bars" part="navigation-toggle-icon" label="Toggle navigation drawer"></wa-icon>
</slot>
</wa-button>
</slot>
<slot name="header"></slot>
</div>
<div class="subheader" part="subheader">