feat(12-02): make config sections collapsible with chevron dropdown
Sections start collapsed showing only heading, description, and a chevron icon. Click to expand and reveal the fields. The open property allows sections to start expanded if needed.
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
import { LitElement, html, css, nothing } from 'lit';
|
import { LitElement, html, css, nothing } from 'lit';
|
||||||
import { customElement, property } from 'lit/decorators.js';
|
import { customElement, property, state } from 'lit/decorators.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A visual grouping wrapper for config fields.
|
* A visual grouping wrapper for config fields.
|
||||||
* Renders a heading, optional description, and a slot for fields.
|
* Renders a collapsible heading with optional description,
|
||||||
|
* and a slot for fields. Starts collapsed by default.
|
||||||
*/
|
*/
|
||||||
@customElement('config-section')
|
@customElement('config-section')
|
||||||
export class ConfigSection extends LitElement {
|
export class ConfigSection extends LitElement {
|
||||||
@@ -17,11 +18,42 @@ export class ConfigSection extends LitElement {
|
|||||||
background: var(--yj-bg-surface, #212529);
|
background: var(--yj-bg-surface, #212529);
|
||||||
border: 1px solid var(--yj-border-subtle, #333);
|
border: 1px solid var(--yj-border-subtle, #333);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.5em;
|
||||||
padding: 1.25em;
|
padding: 1.25em;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header:hover {
|
||||||
|
background: var(--yj-bg-elevated, #343a40);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chevron {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin-top: 0.15em;
|
||||||
|
transition: transform 150ms ease;
|
||||||
|
color: var(--yj-text-tertiary, #888);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chevron.open {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-text {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
margin: 0 0 0.25em;
|
margin: 0;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--yj-text-primary, #fff);
|
color: var(--yj-text-primary, #fff);
|
||||||
@@ -30,7 +62,11 @@ export class ConfigSection extends LitElement {
|
|||||||
.description {
|
.description {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
color: var(--yj-text-tertiary, #888);
|
color: var(--yj-text-tertiary, #888);
|
||||||
margin: 0 0 1em;
|
margin: 0.25em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
padding: 0 1.25em 1.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fields {
|
.fields {
|
||||||
@@ -45,18 +81,55 @@ export class ConfigSection extends LitElement {
|
|||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
description = '';
|
description = '';
|
||||||
|
|
||||||
|
@property({ type: Boolean })
|
||||||
|
open = false;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private expanded = false;
|
||||||
|
|
||||||
|
override connectedCallback(): void {
|
||||||
|
super.connectedCallback();
|
||||||
|
this.expanded = this.open;
|
||||||
|
}
|
||||||
|
|
||||||
|
private toggle = (): void => {
|
||||||
|
this.expanded = !this.expanded;
|
||||||
|
};
|
||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
return html`
|
return html`
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h3>${this.heading}</h3>
|
<div
|
||||||
${this.description
|
class="header"
|
||||||
? html`<p class="description">
|
@click=${this.toggle}
|
||||||
${this.description}
|
>
|
||||||
</p>`
|
<svg
|
||||||
: nothing}
|
class="chevron ${this.expanded ? 'open' : ''}"
|
||||||
<div class="fields">
|
viewBox="0 0 16 16"
|
||||||
<slot></slot>
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M6 3l5 5-5 5z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<div class="header-text">
|
||||||
|
<h3>${this.heading}</h3>
|
||||||
|
${this.description
|
||||||
|
? html`<p class="description">
|
||||||
|
${this.description}
|
||||||
|
</p>`
|
||||||
|
: nothing}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
${this.expanded
|
||||||
|
? html`
|
||||||
|
<div class="body">
|
||||||
|
<div class="fields">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user