apply lindsay's tweaks

This commit is contained in:
konnorrogers
2023-09-28 16:53:29 -04:00
parent aaf845c72a
commit 52bda73657
7 changed files with 207 additions and 288 deletions

View File

@@ -6,11 +6,14 @@ layout: component
---
```html:preview
<nav style="
border: var(--wa-panel-border-width) var(--wa-border-style) var(--wa-color-surface-outline);
border-radius: var(--wa-panel-corners);
padding: var(--wa-space-square-m);
">
<wa-nav-group
style="
--gap: var(--wa-space-2xl);
border: var(--wa-panel-border-width) var(--wa-border-style) var(--wa-color-surface-outline);
border-radius: var(--wa-panel-corners);
padding: var(--wa-space-square-m);
"
>
<wa-nav-group>
<wa-nav-item href="#">
<wa-icon name="search" slot="prefix"></wa-icon>
@@ -21,9 +24,11 @@ layout: component
<wa-icon name="bell" slot="prefix"></wa-icon>
Notifications
</wa-nav-item>
</wa-nav-group>
<wa-nav-group heading="Workspace" expandable style="margin-top: 1rem;">
<div slot="summary" style="display: flex; align-items: center; gap: 8px;">
<wa-nav-group label="Workspace">
<wa-nav-item expandable>
<div slot="label" style="display: flex; align-items: center; gap: 8px;">
<wa-icon name="credit-card"></wa-icon>
Payments
</div>
@@ -39,15 +44,10 @@ layout: component
<wa-nav-item href="#">
Disputed Charges
</wa-nav-item>
</wa-nav-group>
<wa-nav-item href="#">
<wa-icon name="question-circle" slot="prefix"></wa-icon>
Help
</wa-nav-item>
</wa-nav-group>
<wa-nav-group heading="Reports" style="margin-top: 1rem;">
<wa-nav-group label="Reports">
<wa-nav-item href="#">
Sales
</wa-nav-item>
@@ -60,90 +60,20 @@ layout: component
Payroll
</wa-nav-item>
</wa-nav-group>
</nav>
<wa-nav-item href="#">
<wa-icon name="question-circle" slot="prefix"></wa-icon>
Help
</wa-nav-item>
</wa-nav-group>
```
{% raw %}
```jsx:react
import WaNavItem from '@shoelace-style/shoelace/dist/react/nav-item';
import WaNavGroup from '@shoelace-style/shoelace/dist/react/nav-group';
export default () => {
return (
<nav style={{
border: "var(--wa-panel-border-width) var(--wa-border-style) var(--wa-color-surface-outline)",
borderRadius: "var(--wa-panel-corners)",
padding: "var(--wa-space-square-m)"
}}>
<WaNavGroup>
<WaNavItem href="#">
<WaIcon name="search" slot="prefix" />
Search
</WaNavItem>
<WaNavItem href="#">
<WaIcon name="bell" slot="prefix" />
Notifications
</WaNavItem>
<WaNavGroup heading="Workspace" expandable style="margin-top: 1rem;">
<div
slot="summary"
style={{
display: "flex",
align-items: "center",
gap: "8px"
}}
>
<WaIcon name="credit-card" />
Payments
</div>
<WaNavItem href="#" active>
Transactions
</WaNavItem>
<WaNavItem href="#">
Invoices
</WaNavItem>
<WaNavItem href="#">
Disputed Charges
</WaNavItem>
</WaNavGroup>
<WaNavItem href="#">
<WaIcon name="question-circle" slot="prefix" />
Help
</WaNavItem>
</WaNavGroup>
<WaNavGroup heading="Reports" style={{marginTop: "1rem"}}>
<WaNavItem href="#">
Sales
</WaNavItem>
<WaNavItem href="#">
Expenses
</WaNavItem>
<WaNavItem href="#">
Payroll
</WaNavItem>
</WaNavGroup>
</nav>
)
```
{% endraw %}
## Examples
### Nav Group with heading
### Nav Group with label
```html:preview
<wa-nav-group heading="Workspace">
<wa-nav-group label="Workspace">
<wa-nav-item href="#" active>
Transactions
</wa-nav-item>
@@ -156,72 +86,4 @@ export default () => {
Disputed Charges
</wa-nav-item>
</wa-nav-group>
```
{% raw %}
```jsx:react
import WaNavItem from '@shoelace-style/shoelace/dist/react/nav-item';
import WaNavGroup from '@shoelace-style/shoelace/dist/react/nav-group';
<WaNavGroup heading="Workspace">
<WaNavItem href="#" active>
Transactions
</WaNavItem>
<WaNavItem href="#">
Invoices
</WaNavItem>
<WaNavItem href="#">
Disputed Charges
</WaNavItem>
</WaNavGroup>
```
{% endraw %}
### Nav group with nested nav items
Use the `expandable` attribute to mark a nav item as expandable. In addition,
you can add a `summary` slot or attribute to display in the `<wa-details>` element prior
to expanding the nav group.
```html:preview
<wa-nav-group expandable summary="Payments">
<wa-nav-item href="#" active>
Transactions
</wa-nav-item>
<wa-nav-item href="#">
Invoices
</wa-nav-item>
<wa-nav-item href="#">
Disputed Charges
</wa-nav-item>
</wa-nav-group>
```
{% raw %}
```jsx:react
import WaNavItem from '@shoelace-style/shoelace/dist/react/nav-item';
import WaNavGroup from '@shoelace-style/shoelace/dist/react/nav-group';
<WaNavGroup expandable summary="Payments">
<WaNavItem href="#" active>
Transactions
</WaNavItem>
<WaNavItem href="#">
Invoices
</WaNavItem>
<WaNavItem href="#">
Disputed Charges
</WaNavItem>
</WaNavGroup>
```
{% endraw %}
```

View File

@@ -182,3 +182,47 @@ export default () => {
```
{% endraw %}
### Nav group with nested nav items
Use the `expandable` attribute to mark a nav item as expandable. In addition,
you can add a `label` slot or attribute to display in the `<wa-details>` element prior
to expanding the nav group.
```html:preview
<wa-nav-item expandable label="Payments">
<wa-nav-item href="#" active>
Transactions
</wa-nav-item>
<wa-nav-item href="#">
Invoices
</wa-nav-item>
<wa-nav-item href="#">
Disputed Charges
</wa-nav-item>
</wa-nav-group>
```
{% raw %}
```jsx:react
import WaNavItem from '@shoelace-style/shoelace/dist/react/nav-item';
<WaNavItem expandable label="Payments">
<WaNavItem href="#" active>
Transactions
</WaNavItem>
<WaNavItem href="#">
Invoices
</WaNavItem>
<WaNavItem href="#">
Disputed Charges
</WaNavItem>
</WaNavGroup>
```
{% endraw %}

View File

@@ -75,7 +75,7 @@ export default css`
display: none;
}
.details__body {
:not(.details--open) .details__body {
overflow: hidden;
}

View File

@@ -1,9 +1,6 @@
import { html } from 'lit';
import { LocalizeController } from '../../utilities/localize.js';
import { property } from 'lit/decorators.js';
import { when } from 'lit/directives/when.js';
import styles from './nav-group.styles.js';
import WaDetails from '../details/details.component.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import type { CSSResultGroup } from 'lit';
@@ -32,71 +29,22 @@ import type { CSSResultGroup } from 'lit';
export default class WaNavGroup extends WebAwesomeElement {
static styles: CSSResultGroup = styles;
static dependencies = {
'wa-details': WaDetails
};
private readonly localize = new LocalizeController(this);
/**
* The text to display in the summary of the `<wa-details>` element when the nav group is expandable.
*/
@property({ reflect: true }) summary = '';
/**
* The label to display above the nav items slotted in.
*/
@property({ reflect: true }) heading = '';
/**
* If true, will add a `<wa-details>` element into the shadowRoot that you can slot `<wa-nav-items>` into.
*/
@property({ reflect: true, type: Boolean }) expandable: boolean = false;
@property({ reflect: true }) label = '';
render() {
const isRtl = this.localize.dir() === 'rtl';
return html`
<div part="base" class="base">
<p id="label" part="label" class="label">
<slot name="label">${this.label}</slot>
</p>
return html` <div part="base" class="base">
<p id="heading" part="heading" class="heading">
<slot name="heading">${this.heading}</slot>
</p>
${when(
this.expandable,
() => html`
<wa-details
class="details"
part="details"
exportparts="
base:details__base,
header:details__header,
summary:details__summary,
summary-icon:details__summary-icon,
content:details__content
"
>
<div slot="summary">
<slot name="summary"> ${this.summary} </slot>
</div>
<slot slot="expand-icon" name="expand-icon">
<wa-icon library="system" name=${isRtl ? 'chevron-left' : 'chevron-right'}></wa-icon>
</slot>
<slot slot="collapse-icon" name="collapse-icon">
<wa-icon library="system" name=${isRtl ? 'chevron-left' : 'chevron-right'}></wa-icon>
</slot>
<div class="nav-items" part="nav-items" aria-labelledby="heading" role="list">
<slot></slot>
</div>
</wa-details>
`,
() => html`
<div class="nav-items" part="nav-items" aria-labelledby="heading" role="list">
<slot></slot>
</div>
`
)}
</div>`;
<div class="nav-items" part="nav-items" aria-labelledby="label" role="list">
<slot></slot>
</div>
</div>
`;
}
}

View File

@@ -6,45 +6,29 @@ export default css`
:host {
display: block;
--gap: 6px;
}
p {
margin: 0;
margin-bottom: 0.25rem;
margin-bottom: var(--wa-space-xs);
}
.base {
color: var(--wa-color-text-normal);
height: 100%;
}
.heading {
.label {
font-weight: var(--wa-font-weight-heading);
color: var(--wa-color-neutral-text-on-surface);
padding-inline-start: var(--wa-space-xs);
}
.nav-items {
display: flex;
flex-direction: column;
gap: 6px;
gap: var(--gap);
height: 100%;
}
.details::part(base) {
border-color: transparent;
}
.details::part(content) {
padding-top: 6px;
padding-inline-start: 2em;
}
.details::part(header) {
padding: var(--wa-space-square-s);
border-radius: var(--wa-corners-1x);
}
.details::part(header):hover {
background-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-hover));
border-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-hover));
color: var(--wa-color-neutral-text-on-vivid);
}
`;

View File

@@ -5,6 +5,9 @@ import { property, state } from 'lit/decorators.js';
import styles from './nav-item.styles.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import type { CSSResultGroup } from 'lit';
import { when } from 'lit/directives/when.js';
import { LocalizeController } from '@shoelace-style/localize';
import WaDetails from '../details/details.component.js';
/**
* @summary A nav item is intended to be used in a navigation area such as within a nav element in a sidebar or inside of a drawer. A nav item is meant to drive page navigations.
@@ -22,11 +25,17 @@ import type { CSSResultGroup } from 'lit';
export default class WaNavItem extends WebAwesomeElement {
static styles: CSSResultGroup = styles;
static dependencies = {
'wa-details': WaDetails
};
private readonly localize = new LocalizeController(this);
/** maps to the underlying `<a>`'s href */
@property() href = '';
/** maps to aria-current="page" */
@property({ type: Boolean }) active: boolean = false;
@property({ type: Boolean, reflect: true }) active: boolean = false;
/** Tells the browser where to open the link. Only used when `href` is present. */
@property() target: '_blank' | '_parent' | '_self' | '_top';
@@ -42,6 +51,17 @@ export default class WaNavItem extends WebAwesomeElement {
/** Tells the browser to download the linked file as this filename. Only used when `href` is present. */
@property() download?: string;
/**
* The text to display in the summary of the `<wa-details>` element when the nav item is expandable.
*/
@property({ reflect: true }) label = '';
/**
* If true, will add a `<wa-details>` element into the shadowRoot that you can slot `<wa-nav-items>` into.
*/
@property({ reflect: true, type: Boolean }) expandable: boolean = false;
@state() hasFocus: boolean = false;
private handleBlur() {
@@ -55,25 +75,63 @@ export default class WaNavItem extends WebAwesomeElement {
}
render() {
const isRtl = this.localize.dir() === 'rtl';
return html`
<div class="base" role="listitem" aria-current=${this.active ? 'page' : 'false'}>
<a
class=${classMap({
control: true,
'control--active': this.active
})}
part="control"
href=${ifDefined(this.href)}
target=${ifDefined(this.target)}
download=${ifDefined(this.download)}
rel=${ifDefined(this.rel)}
@blur=${this.handleBlur}
@focus=${this.handleFocus}
>
<slot name="prefix"></slot>
<slot></slot>
<slot name="suffix"></slot>
</a>
<div
class=${classMap({
base: true,
"base--active": this.active,
})}
role="listitem"
aria-current=${this.active && !this.expandable ? 'page' : 'false'}
>
${when(
this.expandable,
() => html`
<wa-details
class="details"
part="details"
exportparts="
base:details__base,
header:details__header,
summary:details__summary,
summary-icon:details__summary-icon,
content:details__content
"
>
<div slot="summary" part="label">
<slot name="label">${this.label}</slot>
</div>
<slot slot="expand-icon" name="expand-icon">
<wa-icon library="system" name=${isRtl ? 'chevron-left' : 'chevron-right'}></wa-icon>
</slot>
<slot slot="collapse-icon" name="collapse-icon">
<wa-icon library="system" name=${isRtl ? 'chevron-left' : 'chevron-right'}></wa-icon>
</slot>
<div class="nav-items" part="nav-items" aria-labelledby="heading" role="list">
<slot></slot>
</div>
</wa-details>
`,
() => html`
<a
class="control"
part="control"
href=${ifDefined(this.href)}
target=${ifDefined(this.target)}
download=${ifDefined(this.download)}
rel=${ifDefined(this.rel)}
@blur=${this.handleBlur}
@focus=${this.handleFocus}
>
<slot name="prefix"></slot>
<slot></slot>
<slot name="suffix"></slot>
</a>
`
)}
</div>
`;
}

View File

@@ -17,14 +17,10 @@ export default css`
height: 100%;
}
.control {
display: grid;
grid-auto-flow: column;
align-items: center;
justify-content: start;
gap: 8px;
width: 100%;
border: none;
.control,
.details::part(header) {
padding: var(--wa-space-square-xs);
border-radius: var(--wa-corners-1x);
font: inherit;
font-weight: var(--wa-font-weight-action);
text-decoration: none;
@@ -35,8 +31,16 @@ export default css`
cursor: inherit;
color: var(--wa-color-text-normal);
line-height: var(--wa-font-height-compact);
padding: var(--wa-space-square-s);
border-radius: var(--wa-corners-1x);
}
.control {
display: grid;
grid-auto-flow: column;
align-items: center;
justify-content: start;
gap: 8px;
width: 100%;
border: none;
}
.control::-moz-focus-inner {
@@ -47,40 +51,59 @@ export default css`
outline: transparent;
}
.control:hover {
background-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-hover));
.details::part(header):is(:active, :hover),
.control:is(:active, :hover) {
background-color: var(--wa-color-neutral-fill-muted-alt);
color: var(--wa-color-text-normal);
border-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-hover));
color: var(--wa-color-neutral-text-on-vivid);
}
.control:active {
background-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-active));
border-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-active));
}
.details::part(header):focus-visible,
.control:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
outline-color: var(--wa-color-neutral-fill-vivid);
}
.control.control--active {
.base--active .details::part(header),
.base--active .control {
background-color: var(--wa-color-brand-fill-vivid);
color: var(--wa-color-brand-text-on-vivid);
}
.control--active:focus-visible {
.base--active .details::part(header):focus-visible,
.base--active .control:focus-visible {
outline-color: var(--wa-color-brand-fill-vivid);
}
.control--active:active {
.base--active .details::part(header):active,
.base--active .control:active {
background-color: color-mix(in oklab, var(--wa-color-brand-fill-vivid), var(--wa-color-tint-active));
border-color: color-mix(in oklab, var(--wa-color-brand-fill-vivid), var(--wa-color-tint-active));
}
.control--active:hover {
.base--active .details::part(header):hover,
.base--active .control:hover {
background-color: color-mix(in oklab, var(--wa-color-brand-fill-vivid), var(--wa-color-tint-hover));
border-color: color-mix(in oklab, var(--wa-color-brand-fill-vivid), var(--wa-color-tint-hover));
color: var(--wa-color-brand-text-on-vivid);
}
.details::part(base) {
border-color: transparent;
}
.details::part(content) {
padding-top: 6px;
padding-inline-end: 0px;
padding-inline-start: 2em;
}
.nav-items {
display: flex;
flex-direction: column;
gap: 6px;
height: 100%;
}
`;