mirror of
https://github.com/codex-team/codex.docs.git
synced 2025-08-07 14:35:26 +02:00
feat: add sidebar slider
This commit is contained in:
parent
69b61a2c87
commit
95969ce276
6 changed files with 115 additions and 5 deletions
|
@ -17,6 +17,7 @@
|
|||
"editor-upgrade": "yarn add -D @editorjs/{editorjs,header,code,delimiter,list,link,image,table,inline-code,marker,warning,checklist,raw}@latest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codexteam/shortcuts": "^1.1.1",
|
||||
"config": "^3.3.6",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"csurf": "^1.11.0",
|
||||
|
|
|
@ -52,4 +52,8 @@
|
|||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
<div class="docs-sidebar__slider">
|
||||
{{ svg('arrow-left') }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { Storage } from '../utils/storage';
|
||||
import Shortcut from '@codexteam/shortcuts';
|
||||
|
||||
/**
|
||||
* Local storage key
|
||||
*/
|
||||
const LOCAL_STORAGE_KEY = 'docs_sidebar_state';
|
||||
const SIDEBAR_VISIBILITY_KEY = 'docs_sidebar_visibility';
|
||||
|
||||
|
||||
/**
|
||||
|
@ -31,6 +33,9 @@ export default class Sidebar {
|
|||
sectionList: 'docs-sidebar__section-list',
|
||||
sectionListItemActive: 'docs-sidebar__section-list-item--active',
|
||||
sidebarToggler: 'docs-sidebar__toggler',
|
||||
sidebarSlider: 'docs-sidebar__slider',
|
||||
sidebarCollapsed: 'docs-sidebar--collapsed',
|
||||
sidebarAnimated: 'docs-sidebar--animated',
|
||||
sidebarContent: 'docs-sidebar__content',
|
||||
sidebarContentHidden: 'docs-sidebar__content--hidden',
|
||||
sidebarContentInvisible: 'docs-sidebar__content--invisible',
|
||||
|
@ -45,14 +50,21 @@ export default class Sidebar {
|
|||
* Stores refs to HTML elements needed for correct sidebar work
|
||||
*/
|
||||
this.nodes = {
|
||||
sidebar: null,
|
||||
sections: [],
|
||||
sidebarContent: null,
|
||||
toggler: null,
|
||||
slider: null,
|
||||
};
|
||||
this.sidebarStorage = new Storage(LOCAL_STORAGE_KEY);
|
||||
const storedState = this.sidebarStorage.get();
|
||||
|
||||
this.sectionsState = storedState ? JSON.parse(storedState) : {};
|
||||
|
||||
this.sidebarVisibilityStorage = new Storage(SIDEBAR_VISIBILITY_KEY);
|
||||
const storedVisibility = this.sidebarVisibilityStorage.get();
|
||||
|
||||
this.visibility = storedVisibility !== 'false';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,11 +74,14 @@ export default class Sidebar {
|
|||
* @param {HTMLElement} moduleEl - module element
|
||||
*/
|
||||
init(settings, moduleEl) {
|
||||
this.nodes.sidebar = moduleEl;
|
||||
this.nodes.sections = Array.from(moduleEl.querySelectorAll('.' + Sidebar.CSS.section));
|
||||
this.nodes.sections.forEach(section => this.initSection(section));
|
||||
this.nodes.sidebarContent = moduleEl.querySelector('.' + Sidebar.CSS.sidebarContent);
|
||||
this.nodes.toggler = moduleEl.querySelector('.' + Sidebar.CSS.sidebarToggler);
|
||||
this.nodes.toggler.addEventListener('click', () => this.toggleSidebar());
|
||||
this.nodes.slider = moduleEl.querySelector('.' + Sidebar.CSS.sidebarSlider);
|
||||
this.nodes.slider.addEventListener('click', () => this.handleSliderClick());
|
||||
this.ready();
|
||||
}
|
||||
|
||||
|
@ -168,12 +183,48 @@ export default class Sidebar {
|
|||
this.nodes.sidebarContent.classList.toggle(Sidebar.CSS.sidebarContentHidden);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes sidebar
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
initSidebar() {
|
||||
if (!this.visibility) {
|
||||
this.nodes.slider.classList.add(Sidebar.CSS.sidebarSliderHidden);
|
||||
this.nodes.sidebar.classList.add(Sidebar.CSS.sidebarCollapsed);
|
||||
}
|
||||
|
||||
// prevent sidebar animation on page load
|
||||
setTimeout(() => {
|
||||
this.nodes.sidebar.classList.add(Sidebar.CSS.sidebarAnimated);
|
||||
}, 200);
|
||||
|
||||
// add shortcut to slide sidebar
|
||||
const shortcutForSlider = new Shortcut({
|
||||
name: 'CMD+SHIFT+S',
|
||||
on: document.body,
|
||||
callback: () => this.handleSliderClick(),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Slides sidebar
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
handleSliderClick() {
|
||||
this.visibility = !this.visibility;
|
||||
this.sidebarVisibilityStorage.set(this.visibility);
|
||||
this.nodes.sidebar.classList.toggle(Sidebar.CSS.sidebarCollapsed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays sidebar when ready
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
ready() {
|
||||
this.initSidebar();
|
||||
this.nodes.sidebarContent.classList.remove(Sidebar.CSS.sidebarContentInvisible);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,34 @@
|
|||
.docs-sidebar {
|
||||
width: 100vw;
|
||||
|
||||
|
||||
&--animated {
|
||||
.docs-sidebar__content {
|
||||
transition: transform 200ms ease-in-out;
|
||||
}
|
||||
|
||||
.docs-sidebar__slider {
|
||||
transition: left 200ms ease-in-out;
|
||||
|
||||
svg {
|
||||
transition: transform 200ms ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--collapsed {
|
||||
.docs-sidebar__content {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.docs-sidebar__slider {
|
||||
left: 20px;
|
||||
|
||||
svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (--desktop) {
|
||||
width: var(--layout-sidebar-width);
|
||||
}
|
||||
|
@ -14,7 +42,7 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
|
||||
|
||||
@media (--desktop) {
|
||||
height: calc(100vh - var(--layout-height-header));
|
||||
border-right: 1px solid var(--color-line-gray);
|
||||
|
@ -157,7 +185,7 @@
|
|||
height: 24px;
|
||||
transition-property: background-color;
|
||||
transition-duration: 0.1s;
|
||||
|
||||
|
||||
@apply --squircle;
|
||||
|
||||
@media (--can-hover) {
|
||||
|
@ -178,7 +206,7 @@
|
|||
color: var(--color-text-second);
|
||||
padding: 20px 15px;
|
||||
border-bottom: 1px solid var(--color-line-gray);
|
||||
|
||||
|
||||
@media (--desktop) {
|
||||
display: none;
|
||||
}
|
||||
|
@ -188,6 +216,24 @@
|
|||
}
|
||||
}
|
||||
|
||||
&__slider {
|
||||
display: none;
|
||||
position: fixed;
|
||||
left: calc(var(--layout-sidebar-width) + 20px);
|
||||
bottom: 20px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
background-color: var(--color-link-hover);
|
||||
|
||||
@media (--desktop) {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
&__logo {
|
||||
display: none;
|
||||
margin-top: auto;
|
||||
|
@ -217,4 +263,4 @@
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
3
src/frontend/svg/arrow-left.svg
Normal file
3
src/frontend/svg/arrow-left.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="7" height="11" viewBox="0 0 7 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.95579 10.2458C6.14204 10.0584 6.24658 9.80498 6.24658 9.5408C6.24658 9.27661 6.14204 9.02316 5.95579 8.8358L2.41579 5.2458L5.95579 1.7058C6.14204 1.51844 6.24658 1.26498 6.24658 1.0008C6.24658 0.736612 6.14204 0.483161 5.95579 0.295798C5.86283 0.20207 5.75223 0.127675 5.63037 0.0769067C5.50851 0.026138 5.3778 0 5.24579 0C5.11378 0 4.98307 0.026138 4.86121 0.0769067C4.73935 0.127675 4.62875 0.20207 4.53579 0.295798L0.295789 4.5358C0.202061 4.62876 0.127667 4.73936 0.0768978 4.86122C0.0261292 4.98308 -9.32772e-06 5.11379 -9.32772e-06 5.2458C-9.32772e-06 5.37781 0.0261292 5.50852 0.0768978 5.63037C0.127667 5.75223 0.202061 5.86284 0.295789 5.9558L4.53579 10.2458C4.62875 10.3395 4.73935 10.4139 4.86121 10.4647C4.98307 10.5155 5.11378 10.5416 5.24579 10.5416C5.3778 10.5416 5.50851 10.5155 5.63037 10.4647C5.75223 10.4139 5.86283 10.3395 5.95579 10.2458Z" fill="#060C26"/>
|
||||
</svg>
|
After Width: | Height: | Size: 991 B |
|
@ -907,6 +907,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@codexteam/misprints/-/misprints-1.0.0.tgz#e5a7dec7389fe0f176cd51a040d6dc9bdc252086"
|
||||
integrity sha512-R2IO1JmcaWCuWNPFVEAyar2HqQFuJwkeQUyVF0ovY4ip7z+VnVTYWxeYhCx7eZYEQCyXmcJooICQDihtn16lOA==
|
||||
|
||||
"@codexteam/shortcuts@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@codexteam/shortcuts/-/shortcuts-1.1.1.tgz#6aa19ed0476da78045847ddc6d5b311f2f015094"
|
||||
integrity sha512-wtpYocFlFQSOiea3KAySn9ONno/yKL4JukokV0vJUq1BOUmVEx71sdTW7qgQhG1wcfIO2R/XJ/y4K9EZQyBzng==
|
||||
|
||||
"@cspotcode/source-map-consumer@0.8.0":
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue