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:
parent
33e02db985
commit
42d0a36e46
3 changed files with 81 additions and 31 deletions
|
@ -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 }}">
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue