Skip to content

Commit

Permalink
feat: rewrite the sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
EduardoJM authored Jul 21, 2024
1 parent 9232b7d commit 48e8d33
Show file tree
Hide file tree
Showing 12 changed files with 203 additions and 95 deletions.
10 changes: 10 additions & 0 deletions apps/docs/stories/components/Sidebar/Sidebar.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CollapseManager, SidebarManager, SidebarCollapseManager } from '@inventare/vanilla/src/components';
import { createSidebarButton } from '../SidebarButton/SidebarButton';
import { createSidebarLabel } from '../SidebarLabel/SidebarLabel';

Expand Down Expand Up @@ -135,5 +136,14 @@ export const createSidebar = () => {

baseContainer.appendChild(anotherDiv);

const collapseManager = new CollapseManager();
const sidebarManager = new SidebarManager();
const sidebarCollapseManager = new SidebarCollapseManager();
baseContainer.addEventListener('click', (ev) => {
sidebarCollapseManager.getInstance(ev.target as HTMLElement)?.executeByClick(ev);
collapseManager.getInstance(ev.target as HTMLElement)?.executeByClick(ev);
sidebarManager.getInstance(ev.target as HTMLElement)?.executeByClick(ev);
});

return baseContainer;
};
4 changes: 2 additions & 2 deletions packages/vanilla/src/base/ClickTriggerComponent.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ComponentManager } from './ComponentManager'

export interface ClickTriggerComponent {
executeByClick(): void;
executeByClick(ev: Event): void;
}

type TWithId = { id: string };
Expand All @@ -21,7 +21,7 @@ export class ClickTriggerComponentManager {
if (!instance) {
continue;
}
instance.executeByClick();
instance.executeByClick(ev);
}
}
}
39 changes: 38 additions & 1 deletion packages/vanilla/src/components/Collapse/Collapse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,43 @@ export class Collapse implements ClickTriggerComponent {
};
}

hide() {
const { toggle, content } = this.element;
if (content.classList.contains(CLASS_NAME_COLLAPSING)) {
return;
}

const isOpenAttr = toggle.getAttribute('aria-expanded');
let isOpen = true;
if (isOpenAttr) {
isOpen = Boolean(JSON.parse(isOpenAttr));
}

if (!isOpen) {
return;
}

const { value, property } = this.getContentSize(content, isOpen);

content.style[property] = value;
content.offsetHeight; // reset animation

content.classList.add(CLASS_NAME_COLLAPSING);
content.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW)
content.classList.toggle(CLASS_NAME_COLLAPSED, isOpen);
toggle.setAttribute('aria-expanded', JSON.stringify(!isOpen));

const complete = () => {
content.classList.remove(CLASS_NAME_COLLAPSING);
content.classList.add(CLASS_NAME_COLLAPSE);
};
executeAfterTransition(complete, content);

const { value: destValue } = this.getContentSize(content, !isOpen);

content.style[property] = destValue;
}

toggle() {
const { toggle, content } = this.element;

Expand Down Expand Up @@ -83,7 +120,7 @@ export class Collapse implements ClickTriggerComponent {
content.style[property] = destValue;
}

executeByClick() {
executeByClick(ev: Event) {
this.toggle();
}
}
4 changes: 2 additions & 2 deletions packages/vanilla/src/components/Collapse/CollapseManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { ComponentManager, ClickTriggerComponentManager } from '../../base';
import { CollapseElement } from './CollapseElement';
import { Collapse } from './Collapse';

const TRIGGER_SELECTOR = '[data-toggle="collapse"]';
export const COLLAPSE_TRIGGER_SELECTOR = '[data-toggle="collapse"]';

export class CollapseManager extends ComponentManager<CollapseElement, Collapse> {
protected getElement(target?: HTMLElement | null): CollapseElement | null {
if (!target) {
return null;
}
const toggleClosest = target.closest<HTMLElement>(TRIGGER_SELECTOR);
const toggleClosest = target.closest<HTMLElement>(COLLAPSE_TRIGGER_SELECTOR);
if (!toggleClosest) {
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/vanilla/src/components/Modal/Modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export class Modal implements ClickTriggerComponent {
return this.show();
}

executeByClick() {
executeByClick(ev: Event) {
this.toggle();
}
}
Expand Down
72 changes: 72 additions & 0 deletions packages/vanilla/src/components/Sidebar/Sidebar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { ClickTriggerComponent } from '../../base';
import { executeAfterTransition } from '../../utils/transitions';
import { COLLAPSE_TRIGGER_SELECTOR, CollapseManager } from '../Collapse';
import { SidebarElement } from './SidebarElement';

export const SIDEBAR_TRIGGER_SELECTOR = '[data-toggle="sidebar"]';

export class Sidebar implements ClickTriggerComponent {
element: SidebarElement;
manager: CollapseManager;

get isExpanded() {
return !this.element.content.classList.contains('collapsed');
}

constructor(element: SidebarElement) {
this.element = element;
this.manager = new CollapseManager();
}

collapse() {
const collapseTriggers = [
...this.element.content.querySelectorAll<HTMLElement>(COLLAPSE_TRIGGER_SELECTOR)
];
collapseTriggers.forEach((item) => {
this.manager.getInstance(item)?.hide()
});

const complete = () => {
this.element.content.classList.add('collapsed-complete');
};

this.element.content.classList.remove('collapsed-complete');
this.element.content.classList.add('collapsed');
executeAfterTransition(complete, this.element.content);
}

expand() {
this.element.content.classList.remove('collapsed', 'collapsed-complete');
}

toggle() {
if (this.isExpanded) {
return this.collapse();
}
this.expand();
}

executeByClick(ev: Event) {
console.log(ev);
this.toggle();
}
}

export class SidebarCollapse implements ClickTriggerComponent {
sidebar: Sidebar;

constructor(sidebarElement: HTMLElement) {
this.sidebar = new Sidebar({
id: sidebarElement.id,
toggle: sidebarElement,
content: sidebarElement,
})
}

executeByClick(ev: Event): void {
if (this.sidebar.isExpanded) {
return;
}
this.sidebar.expand();
}
}
5 changes: 5 additions & 0 deletions packages/vanilla/src/components/Sidebar/SidebarElement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface SidebarElement {
id: string;
toggle: HTMLElement;
content: HTMLElement;
}
69 changes: 69 additions & 0 deletions packages/vanilla/src/components/Sidebar/SidebarManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { ComponentManager, ClickTriggerComponentManager } from '../../base';
import { Sidebar, SidebarCollapse, SIDEBAR_TRIGGER_SELECTOR } from './Sidebar';
import { SidebarElement } from './SidebarElement';
import { COLLAPSE_TRIGGER_SELECTOR, CollapseElement } from '../Collapse';

export class SidebarManager extends ComponentManager<SidebarElement, Sidebar> {
protected getElement(target?: HTMLElement | null): SidebarElement | null {
if (!target) {
return null;
}
const toggleClosest = target.closest<HTMLElement>(SIDEBAR_TRIGGER_SELECTOR);
if (!toggleClosest) {
return null;
}
const contentQuery = toggleClosest.getAttribute('data-target');
if (!contentQuery) {
return null;
}
const contentEl = document.querySelector<HTMLElement>(contentQuery);
if (!contentEl) {
return null;
}
return {
id: contentEl.id,
toggle: toggleClosest,
content: contentEl,
};
}

protected createInstance(element: SidebarElement): Sidebar {
return new Sidebar(element);
}
}

export class SidebarCollapseManager extends ComponentManager<CollapseElement, SidebarCollapse> {
protected getElement(target?: HTMLElement | null): CollapseElement | null {
if (!target) {
return null;
}
const toggleClosest = target.closest<HTMLElement>(COLLAPSE_TRIGGER_SELECTOR);
if (!toggleClosest) {
return null;
}
const contentQuery = toggleClosest.getAttribute('data-target');
if (!contentQuery) {
return null;
}
const contentEl = document.querySelector<HTMLElement>(contentQuery);
if (!contentEl) {
return null;
}
if (!contentEl.closest('.sidebar')) {
return null;
}
return {
id: contentEl.id,
toggle: toggleClosest,
content: contentEl,
};
}

protected createInstance(element: CollapseElement): SidebarCollapse {
const sidebar = element.content.closest('.sidebar') as HTMLElement;
return new SidebarCollapse(sidebar);
}
}

ClickTriggerComponentManager.register(new SidebarManager());
ClickTriggerComponentManager.register(new SidebarCollapseManager());
3 changes: 3 additions & 0 deletions packages/vanilla/src/components/Sidebar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './SidebarManager';
export * from './SidebarElement';
export * from './Sidebar';
1 change: 1 addition & 0 deletions packages/vanilla/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './Backdrop';
export * from './Modal';
export * from './Collapse';
export * from './Sidebar';
1 change: 0 additions & 1 deletion packages/vanilla/src/components/sidebar/index.ts

This file was deleted.

88 changes: 0 additions & 88 deletions packages/vanilla/src/components/sidebar/sidebar.browser.ts

This file was deleted.

0 comments on commit 48e8d33

Please sign in to comment.