123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- class AccordionItem extends HTMLElement {
- static get observedAttributes() {
- return ['title'];
- }
-
- #title = '';
- #collapsed = true;
-
- constructor() {
- super();
- this.attachShadow({ mode: 'open' });
- }
-
- connectedCallback() {
- this.update();
- this.shadowRoot.addEventListener('click', this.toggle.bind(this));
- }
-
- attributeChangedCallback(name, oldValue, newValue) {
- if (name === 'title') {
- this.#title = newValue;
- }
- this.update();
- }
-
- toggle() {
- this.#collapsed = !this.#collapsed;
- this.update();
-
- // Dispatch a custom event to notify the parent AccordionElement
- const event = new CustomEvent('accordion-item-toggle', {
- bubbles: true,
- detail: {
- collapsed: this.#collapsed,
- item: this,
- },
- });
- this.dispatchEvent(event);
- }
-
- update() {
- this.shadowRoot.innerHTML = `
- <style>
- .accordion-item {
-
- }
- .accordion-title {
- display: flex;
- justify-content: space-between;
- align-items: center;
- cursor: pointer;
- padding: 0.5rem;
- background-color: white;
- }
- .accordion-title:hover {
- background-color: white;
- }
- .accordion-title::after {
- content: '${this.#collapsed ? '+' : '−'}';
- font-size: 1rem;
- font-weight: bold;
- color: #777;
- margin-left: 0.5rem;
- }
- .accordion-content {
- padding: 0.5rem;
- display: ${this.#collapsed ? 'none' : 'block'};
- }
- </style>
- <div class="accordion-item">
- <div class="accordion-title">${this.#title}</div>
- <div class="accordion-content">
- <slot></slot>
- </div>
- </div>
- `;
- }
- }
-
- class AccordionElement extends HTMLElement {
- #activeItem = null;
-
- constructor() {
- super();
- this.attachShadow({ mode: 'open' });
- this.shadowRoot.innerHTML = '<slot></slot>';
- this.addEventListener('accordion-item-toggle', this.handleItemToggle.bind(this));
- }
-
- handleItemToggle(event) {
- const { collapsed, item } = event.detail;
-
- // If the active item is different from the toggled item, collapse the active item
- if (this.#activeItem && this.#activeItem !== item && !collapsed) {
- this.#activeItem.toggle();
- }
-
- // Update the active item
- if (!collapsed) {
- this.#activeItem = item;
- } else if (this.#activeItem === item) {
- this.#activeItem = null;
- }
- }
- }
-
- customElements.define('accordion-item', AccordionItem);
- customElements.define('accordion-element', AccordionElement);
-
-
|