[Details] Revamp CSS, simplify part names

First component to use the `display: contents` trick discussed in #207
This commit is contained in:
Lea Verou
2024-12-16 10:48:56 -05:00
parent f86c07bdab
commit c066c5f30b
3 changed files with 61 additions and 79 deletions

View File

@@ -28,7 +28,7 @@ Use the `disabled` attribute to prevent the details from expanding.
### Customizing the Summary Icon
Use the `expand-icon` and `collapse-icon` slots to change the expand and collapse icons, respectively. To disable the animation, override the `rotate` property on the `summary-icon` part as shown below.
Use the `expand-icon` and `collapse-icon` slots to change the expand and collapse icons, respectively. To disable the animation, override the `rotate` property on the `icon` part as shown below.
```html {.example}
<wa-details summary="Toggle Me" class="custom-icons">
@@ -40,8 +40,8 @@ Use the `expand-icon` and `collapse-icon` slots to change the expand and collaps
</wa-details>
<style>
wa-details.custom-icons::part(summary-icon) {
/* Disable the expand/collapse animation */
/* Disable the expand/collapse animation */
wa-details.custom-icons::part(icon) {
rotate: none;
}
</style>

View File

@@ -1,68 +1,65 @@
:host {
--background-color: var(--wa-color-surface-default);
--border-color: var(--wa-color-surface-border);
--border-radius: var(--wa-panel-border-radius);
--border-style: var(--wa-panel-border-style);
--border-width: var(--wa-panel-border-width);
background-color: var(--wa-color-surface-default);
border: var(--wa-panel-border-width) var(--wa-color-surface-border) var(--wa-panel-border-style);
border-radius: var(--wa-panel-border-radius);
--icon-color: var(--wa-color-text-quiet);
--spacing: var(--wa-space-m);
--show-duration: 200ms;
--hide-duration: 200ms;
display: block;
display: contents !important;
}
.details {
background-color: var(--background-color);
border-color: var(--border-color);
border-radius: var(--border-radius);
border-style: var(--border-style);
border-width: var(--border-width);
details {
all: inherit;
display: block;
overflow-anchor: none;
}
.details--disabled {
:host([disabled]) details {
opacity: 0.5;
summary {
cursor: not-allowed;
}
summary:focus-visible {
outline: none;
box-shadow: none;
}
}
.details__header {
summary {
display: flex;
align-items: center;
padding: var(--spacing);
user-select: none;
-webkit-user-select: none;
cursor: pointer;
&::marker,
&::-webkit-details-marker {
display: none;
}
&:focus {
outline: none;
}
&:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: calc(1px + var(--wa-focus-ring-offset));
}
[part~='summary'] {
flex: 1 1 auto;
display: flex;
align-items: center;
}
}
.details__header::-webkit-details-marker {
display: none;
}
.details__header:focus {
outline: none;
}
.details__header:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: calc(1px + var(--wa-focus-ring-offset));
}
.details--disabled .details__header {
cursor: not-allowed;
}
.details--disabled .details__header:focus-visible {
outline: none;
box-shadow: none;
}
.details__summary {
flex: 1 1 auto;
display: flex;
align-items: center;
}
.details__summary-icon {
[part~='icon'] {
flex: 0 0 auto;
display: flex;
align-items: center;
@@ -70,25 +67,25 @@
transition: rotate var(--wa-transition-normal) var(--wa-transition-easing);
}
.details--open .details__summary-icon {
:host([open]) [part~='icon'] {
rotate: 90deg;
}
.details--open.details--rtl .details__summary-icon {
:host([open]:dir(rtl)) [part~='icon'] {
rotate: -90deg;
}
.details--open slot[name='expand-icon'],
.details:not(.details--open) slot[name='collapse-icon'] {
:host([open]) slot[name='expand-icon'],
:host(:not([open])) slot[name='collapse-icon'] {
display: none;
}
/* Overflows get clipped during the closing animation if we don't wait until the close is gone. */
:not(.details--open) .details__body {
:host(:not([open])) .body {
overflow: hidden;
}
.details__content {
.content {
display: block;
padding: var(--spacing);
}

View File

@@ -1,6 +1,5 @@
import { html } from 'lit';
import { customElement, property, query } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { WaAfterHideEvent } from '../../events/after-hide.js';
import { WaAfterShowEvent } from '../../events/after-show.js';
import { WaHideEvent } from '../../events/hide.js';
@@ -31,17 +30,13 @@ import styles from './details.css';
* @event wa-hide - Emitted when the details closes.
* @event wa-after-hide - Emitted after the details closes and all animations are complete.
*
* @csspart base - The component's base wrapper.
* @csspart base - The inner `<details>` element used to render the component.
* Styles you apply to the component are automatically applied to this part, so you usually don't need to deal with it unless you need to set the `display` property.
* @csspart header - The header that wraps both the summary and the expand/collapse icon.
* @csspart summary - The container that wraps the summary.
* @csspart summary-icon - The container that wraps the expand/collapse icons.
* @csspart icon - The container that wraps the expand/collapse icons.
* @csspart content - The details content.
*
* @cssproperty --background-color - The details' background color.
* @cssproperty --border-color - The details' border color.
* @cssproperty --border-radius - The radius for the details' corners. Expects a single value.
* @cssproperty --border-style - The style of the details' borders.
* @cssproperty --border-width - The width of the details' borders. Expects a single value.
* @cssproperty --icon-color - The color of the details' icon.
* @cssproperty --spacing - The amount of space around and between the details' content. Expects a single value.
* @cssproperty [--show-duration=200ms] - The show duration to use when applying built-in animation classes.
@@ -54,10 +49,10 @@ export default class WaDetails extends WebAwesomeElement {
private detailsObserver: MutationObserver;
private readonly localize = new LocalizeController(this);
@query('.details') details: HTMLDetailsElement;
@query('.details__header') header: HTMLElement;
@query('.details__body') body: HTMLElement;
@query('.details__expand-icon-slot') expandIconSlot: HTMLSlotElement;
@query('details') details: HTMLDetailsElement;
@query('summary') header: HTMLElement;
@query('.body') body: HTMLElement;
@query('.expand-icon-slot') expandIconSlot: HTMLSlotElement;
/**
* Indicates whether or not the details is open. You can toggle this attribute to show and hide the details, or you
@@ -211,19 +206,9 @@ export default class WaDetails extends WebAwesomeElement {
const isRtl = !this.hasUpdated ? this.dir === 'rtl' : this.localize.dir() === 'rtl';
return html`
<details
part="base"
class=${classMap({
details: true,
'details--open': this.open,
'details--disabled': this.disabled,
'details--rtl': isRtl,
})}
>
<details part="base">
<summary
part="header"
id="header"
class="details__header"
role="button"
aria-expanded=${this.open ? 'true' : 'false'}
aria-controls="content"
@@ -232,9 +217,9 @@ export default class WaDetails extends WebAwesomeElement {
@click=${this.handleSummaryClick}
@keydown=${this.handleSummaryKeyDown}
>
<slot name="summary" part="summary" class="details__summary">${this.summary}</slot>
<slot name="summary" part="summary">${this.summary}</slot>
<span part="summary-icon" class="details__summary-icon">
<span part="icon">
<slot name="expand-icon">
<wa-icon
library="system"
@@ -254,8 +239,8 @@ export default class WaDetails extends WebAwesomeElement {
</span>
</summary>
<div class="details__body" role="region" aria-labelledby="header">
<slot part="content" id="content" class="details__content"></slot>
<div class="body" role="region" aria-labelledby="header">
<slot part="content" id="content" class="content"></slot>
</div>
</details>
`;