1
0
Fork 0
mirror of https://github.com/codex-team/codex.docs.git synced 2025-08-08 23:15:28 +02:00

Save state to local storage

This commit is contained in:
Tanya Fomina 2022-06-07 15:07:06 +08:00
parent 33e02db985
commit 42d0a36e46
3 changed files with 81 additions and 31 deletions

View file

@ -24,7 +24,7 @@
{% if firstLevelPage.children is not empty %}
<ul class="docs-sidebar__section-list">
{% for child in firstLevelPage.children %}
<li>
<li class="docs-sidebar__section-list-item-wrapper">
<a
class="docs-sidebar__section-list-item {{page is defined and page._id == child._id ? 'docs-sidebar__section-list-item--active' : ''}}"
href="{{ child.uri ? '/' ~ child.uri : '/page/' ~ child._id }}">

View file

@ -1,15 +1,23 @@
/**
*
* Local storage key
*/
const LOCAL_STORAGE_KEY = 'docs_siedabar_state';
/**
* Sidebar module
*/
export default class Sidebar {
/**
* CSS classes
*
* @returns {Record<string, string>}
*/
static get CSS() {
return {
toggler: 'docs-sidebar__section-toggler',
togglerCollapsed: 'docs-sidebar__section-toggler--collapsed',
section: 'docs-sidebar__section',
sectionAnimated: 'docs-sidebar__section--animated',
sectionTitle: 'docs-sidebar__section-title',
sectionTitleActive: 'docs-sidebar__section-title--active',
sectionList: 'docs-sidebar__section-list',
@ -17,49 +25,75 @@ export default class Sidebar {
sectionListItemActive: 'docs-sidebar__section-list-item--active',
};
}
/**
*
* Creates base properties
*/
constructor() {
this.nodes = {
section: null,
};
this.collapsed = {};
const storedState = window.localStorage.getItem(LOCAL_STORAGE_KEY);
this.collapsed = storedState ? JSON.parse(storedState) : {};
}
/**
* @param settings
* @param moduleEl
* Called by ModuleDispatcher to initialize module from DOM
*
* @param {writingSettings} settings - module settings
* @param {HTMLElement} moduleEl - module element
*/
init(settings = {}, moduleEl) {
init(settings, moduleEl) {
this.nodes.sections = Array.from(moduleEl.querySelectorAll('.' + Sidebar.CSS.section));
this.nodes.sections.forEach(section => {
const id = section.getAttribute('data-id');
this.collapsed[id] = false;
const togglerEl = section.querySelector('.' + Sidebar.CSS.toggler);
togglerEl.addEventListener('click', e => this.toggleSection(id, section, togglerEl, e));
togglerEl.addEventListener('click', e => this.handleTogglerClick(id, section, togglerEl, e));
if (typeof this.collapsed[id] === 'undefined') {
this.collapsed[id] = false;
}
if (this.collapsed[id]) {
this.setSectionCollapsed(section, togglerEl, true, false);
}
});
}
/**
* @param sectionId
* @param sectionEl
* @param togglerEl
* @param event
* Toggles section expansion
*
* @param {number} sectionId - id of the section to toggle
* @param {HTMLElement} sectionEl - section html element
* @param {HTMLElement} togglerEl - toggler button html element
* @param {MouseEvent} event - click event
* @returns {void}
*/
toggleSection(sectionId, sectionEl, togglerEl, event) {
handleTogglerClick(sectionId, sectionEl, togglerEl, event) {
event.preventDefault();
this.collapsed[sectionId] = !this.collapsed[sectionId];
togglerEl.classList.toggle(Sidebar.CSS.togglerCollapsed, this.collapsed[sectionId]);
const sectionList = sectionEl.querySelector('.' + Sidebar.CSS.sectionList);
window.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(this.collapsed));
this.setSectionCollapsed(sectionEl, togglerEl, this.collapsed[sectionId]);
}
/**
* Updates section's collapsed state
*
* @param {HTMLElement} sectionEl - element of the section to toggle
* @param {HTMLElement} togglerEl - section's toggler button element
* @param {boolean} collapsed - new collapsed state
* @param {boolean} animated - true if state should change with animation
*/
setSectionCollapsed(sectionEl, togglerEl, collapsed, animated = true) {
togglerEl.classList.toggle(Sidebar.CSS.togglerCollapsed, collapsed);
const sectionList = sectionEl.querySelector('.' + Sidebar.CSS.sectionList);
if (!sectionList) {
return;
}
sectionList.classList.toggle(Sidebar.CSS.sectionListCollapsed, this.collapsed[sectionId]);
sectionEl.classList.toggle(Sidebar.CSS.sectionAnimated, animated);
sectionList.classList.toggle(Sidebar.CSS.sectionListCollapsed, collapsed);
/**
* Highlight section item as active if active child item is collapsed.
@ -67,14 +101,15 @@ export default class Sidebar {
const activeSectionListItem = sectionList.querySelector('.' + Sidebar.CSS.sectionListItemActive);
const sectionTitle = sectionEl.querySelector('.' + Sidebar.CSS.sectionTitle);
if (activeSectionListItem) {
if (this.collapsed[sectionId]) {
setTimeout(() => {
sectionTitle.classList.toggle(Sidebar.CSS.sectionTitleActive, true);
}, 200);
} else {
sectionTitle.classList.toggle(Sidebar.CSS.sectionTitleActive, false);
}
if (!activeSectionListItem) {
return;
}
if (collapsed && animated) {
setTimeout(() => {
sectionTitle.classList.toggle(Sidebar.CSS.sectionTitleActive, collapsed);
}, 200);
} else {
sectionTitle.classList.toggle(Sidebar.CSS.sectionTitleActive, collapsed);
}
}
}

View file

@ -6,6 +6,16 @@
&__section {
overflow: hidden;
&--animated {
.docs-sidebar__section-list {
transition: max-height 200ms ease-in-out;
}
.docs-sidebar__section-toggler {
transition: transform 200ms ease-in;
}
}
}
&__section:not(:last-child) {
@ -18,11 +28,13 @@
font-weight: 700;
z-index: 2;
position: relative;
height: 34px;
}
&__section-list-item {
font-size: 14px;
line-height: 21px;
height: 29px;
}
&__section-title,
@ -30,11 +42,17 @@
display: flex;
align-items: center;
justify-content: space-between;
height: 34px;
padding: 0 8px;
@apply --squircle;
}
&__section-list-item-wrapper,
&__section-title {
&:not(:last-child) {
margin-bottom: 2px;
}
}
&__section-title:not(&__section-title--active),
&__section-list-item:not(&__section-list-item--active) {
&:hover {
@ -54,9 +72,7 @@
margin: 0;
z-index: 1;
position: relative;
max-height: 1000px;
transition: max-height 200ms ease-in-out;
&--collapsed {
max-height: 0;
@ -69,7 +85,6 @@
padding: 0;
border: 0;
cursor: pointer;
transition: transform 200ms ease-in;
svg {
display: block;