1
0
Fork 0
mirror of https://github.com/codex-team/codex.docs.git synced 2025-07-19 05:09:41 +02:00

Added sidebar toggler (#214)

* feat: add sidebar slider

* fix: fix visibility on mobile layout

* fix visibility on mobile layout
* change keyboard shortcut
* change css property

* fix: fix shortcuts to support Mac

* fix shortcuts to support Mac
* add comment to explain properties

* fix: fix shortcuts

* resolve merge conflict

* fix: remove redundant property

Co-authored-by: Peter Savchenko <specc.dev@gmail.com>
This commit is contained in:
YeoKyung Yoon 2022-08-27 15:21:50 +09:00 committed by GitHub
parent 136702aeb7
commit 09835e3007
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 117 additions and 12 deletions

View file

@ -18,6 +18,7 @@
"editor-upgrade": "yarn add -D @editorjs/{editorjs,header,code,delimiter,list,link,image,table,inline-code,marker,warning,checklist,raw}@latest" "editor-upgrade": "yarn add -D @editorjs/{editorjs,header,code,delimiter,list,link,image,table,inline-code,marker,warning,checklist,raw}@latest"
}, },
"dependencies": { "dependencies": {
"@codexteam/shortcuts": "^1.2.0",
"@hawk.so/javascript": "^3.0.1", "@hawk.so/javascript": "^3.0.1",
"@hawk.so/nodejs": "^3.1.2", "@hawk.so/nodejs": "^3.1.2",
"config": "^3.3.6", "config": "^3.3.6",

View file

@ -52,4 +52,8 @@
</div> </div>
</aside> </aside>
<div class="docs-sidebar__slider">
{{ svg('arrow-left') }}
</div>
</div> </div>

View file

@ -1,10 +1,11 @@
import { Storage } from '../utils/storage'; import { Storage } from '../utils/storage';
import Shortcut from '@codexteam/shortcuts';
/** /**
* Local storage key * Local storage key
*/ */
const LOCAL_STORAGE_KEY = 'docs_sidebar_state'; const LOCAL_STORAGE_KEY = 'docs_sidebar_state';
const SIDEBAR_VISIBILITY_KEY = 'docs_sidebar_visibility';
/** /**
* Section list item height in px * Section list item height in px
@ -31,6 +32,9 @@ export default class Sidebar {
sectionList: 'docs-sidebar__section-list', sectionList: 'docs-sidebar__section-list',
sectionListItemActive: 'docs-sidebar__section-list-item--active', sectionListItemActive: 'docs-sidebar__section-list-item--active',
sidebarToggler: 'docs-sidebar__toggler', sidebarToggler: 'docs-sidebar__toggler',
sidebarSlider: 'docs-sidebar__slider',
sidebarCollapsed: 'docs-sidebar--collapsed',
sidebarAnimated: 'docs-sidebar--animated',
sidebarContent: 'docs-sidebar__content', sidebarContent: 'docs-sidebar__content',
sidebarContentHidden: 'docs-sidebar__content--hidden', sidebarContentHidden: 'docs-sidebar__content--hidden',
sidebarContentInvisible: 'docs-sidebar__content--invisible', sidebarContentInvisible: 'docs-sidebar__content--invisible',
@ -45,14 +49,24 @@ export default class Sidebar {
* Stores refs to HTML elements needed for correct sidebar work * Stores refs to HTML elements needed for correct sidebar work
*/ */
this.nodes = { this.nodes = {
sidebar: null,
sections: [], sections: [],
sidebarContent: null, sidebarContent: null,
toggler: null, toggler: null,
slider: null,
}; };
this.sidebarStorage = new Storage(LOCAL_STORAGE_KEY); this.sidebarStorage = new Storage(LOCAL_STORAGE_KEY);
const storedState = this.sidebarStorage.get(); const storedState = this.sidebarStorage.get();
this.sectionsState = storedState ? JSON.parse(storedState) : {}; this.sectionsState = storedState ? JSON.parse(storedState) : {};
// Initialize localStorage that contains sidebar visibility
this.sidebarVisibilityStorage = new Storage(SIDEBAR_VISIBILITY_KEY);
// Get current sidebar visibility from storage
const storedVisibility = this.sidebarVisibilityStorage.get();
// Sidebar visibility
this.isVisible = storedVisibility !== 'false';
} }
/** /**
@ -62,11 +76,14 @@ export default class Sidebar {
* @param {HTMLElement} moduleEl - module element * @param {HTMLElement} moduleEl - module element
*/ */
init(settings, moduleEl) { init(settings, moduleEl) {
this.nodes.sidebar = moduleEl;
this.nodes.sections = Array.from(moduleEl.querySelectorAll('.' + Sidebar.CSS.section)); this.nodes.sections = Array.from(moduleEl.querySelectorAll('.' + Sidebar.CSS.section));
this.nodes.sections.forEach(section => this.initSection(section)); this.nodes.sections.forEach(section => this.initSection(section));
this.nodes.sidebarContent = moduleEl.querySelector('.' + Sidebar.CSS.sidebarContent); this.nodes.sidebarContent = moduleEl.querySelector('.' + Sidebar.CSS.sidebarContent);
this.nodes.toggler = moduleEl.querySelector('.' + Sidebar.CSS.sidebarToggler); this.nodes.toggler = moduleEl.querySelector('.' + Sidebar.CSS.sidebarToggler);
this.nodes.toggler.addEventListener('click', () => this.toggleSidebar()); this.nodes.toggler.addEventListener('click', () => this.toggleSidebar());
this.nodes.slider = moduleEl.querySelector('.' + Sidebar.CSS.sidebarSlider);
this.nodes.slider.addEventListener('click', () => this.handleSliderClick());
this.ready(); this.ready();
} }
@ -104,7 +121,7 @@ export default class Sidebar {
const itemsCount = sectionList.children.length; const itemsCount = sectionList.children.length;
sectionList.style.maxHeight = `${ itemsCount * ITEM_HEIGHT }px`; sectionList.style.maxHeight = `${itemsCount * ITEM_HEIGHT}px`;
} }
/** /**
@ -168,12 +185,52 @@ export default class Sidebar {
this.nodes.sidebarContent.classList.toggle(Sidebar.CSS.sidebarContentHidden); this.nodes.sidebarContent.classList.toggle(Sidebar.CSS.sidebarContentHidden);
} }
/**
* Initializes sidebar
*
* @returns {void}
*/
initSidebar() {
if (!this.isVisible) {
this.nodes.sidebar.classList.add(Sidebar.CSS.sidebarCollapsed);
}
/**
* prevent sidebar animation on page load
* Since animated class contains transition, hiding will be animated with it
* To prevent awkward animation when visibility is set to false, we need to remove animated class
*/
setTimeout(() => {
this.nodes.sidebar.classList.add(Sidebar.CSS.sidebarAnimated);
}, 200);
// add event listener to execute keyboard shortcut
// eslint-disable-next-line no-new
new Shortcut({
name: 'CMD+.',
on: document.body,
callback: () => this.handleSliderClick(),
});
}
/**
* Slides sidebar
*
* @returns {void}
*/
handleSliderClick() {
this.isVisible = !this.isVisible;
this.sidebarVisibilityStorage.set(this.isVisible);
this.nodes.sidebar.classList.toggle(Sidebar.CSS.sidebarCollapsed);
}
/** /**
* Displays sidebar when ready * Displays sidebar when ready
* *
* @returns {void} * @returns {void}
*/ */
ready() { ready() {
this.initSidebar();
this.nodes.sidebarContent.classList.remove(Sidebar.CSS.sidebarContentInvisible); this.nodes.sidebarContent.classList.remove(Sidebar.CSS.sidebarContentInvisible);
} }
} }

View file

@ -1,6 +1,34 @@
.docs-sidebar { .docs-sidebar {
width: 100vw; width: 100vw;
&--animated {
.docs-sidebar__content {
transition: transform 200ms ease-in-out;
will-change: transform;
}
.docs-sidebar__slider {
transition: transform 200ms ease-in-out;
will-change: transform;
}
}
&--collapsed {
@media (--desktop) {
.docs-sidebar__content {
transform: translateX(-100%);
}
}
.docs-sidebar__slider {
transform: translateX(20px);
svg {
transform: rotate(180deg);
}
}
}
@media (--desktop) { @media (--desktop) {
width: var(--layout-sidebar-width); width: var(--layout-sidebar-width);
} }
@ -188,6 +216,24 @@
} }
} }
&__slider {
display: none;
position: fixed;
transform: translateX(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 { &__logo {
display: none; display: none;
margin-top: auto; margin-top: auto;

View 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

View file

@ -922,6 +922,10 @@
resolved "https://registry.yarnpkg.com/@codexteam/misprints/-/misprints-1.0.0.tgz#e5a7dec7389fe0f176cd51a040d6dc9bdc252086" resolved "https://registry.yarnpkg.com/@codexteam/misprints/-/misprints-1.0.0.tgz#e5a7dec7389fe0f176cd51a040d6dc9bdc252086"
integrity sha512-R2IO1JmcaWCuWNPFVEAyar2HqQFuJwkeQUyVF0ovY4ip7z+VnVTYWxeYhCx7eZYEQCyXmcJooICQDihtn16lOA== integrity sha512-R2IO1JmcaWCuWNPFVEAyar2HqQFuJwkeQUyVF0ovY4ip7z+VnVTYWxeYhCx7eZYEQCyXmcJooICQDihtn16lOA==
"@codexteam/shortcuts@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@codexteam/shortcuts/-/shortcuts-1.2.0.tgz#b8dd7396962b0bd845a5c8f8f19bc6119b520e19"
"@cspotcode/source-map-support@^0.8.0": "@cspotcode/source-map-support@^0.8.0":
version "0.8.1" version "0.8.1"
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
@ -937,7 +941,6 @@
"@csstools/selector-specificity@^2.0.0": "@csstools/selector-specificity@^2.0.0":
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz#1bfafe4b7ed0f3e4105837e056e0a89b108ebe36" resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz#1bfafe4b7ed0f3e4105837e056e0a89b108ebe36"
integrity sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==
"@discoveryjs/json-ext@^0.5.0": "@discoveryjs/json-ext@^0.5.0":
version "0.5.7" version "0.5.7"
@ -3073,7 +3076,6 @@ entities@^2.0.0:
entities@^4.2.0, entities@^4.3.0: entities@^4.2.0, entities@^4.3.0:
version "4.3.1" version "4.3.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.3.1.tgz#c34062a94c865c322f9d67b4384e4169bcede6a4" resolved "https://registry.yarnpkg.com/entities/-/entities-4.3.1.tgz#c34062a94c865c322f9d67b4384e4169bcede6a4"
integrity sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==
envinfo@^7.7.3: envinfo@^7.7.3:
version "7.8.1" version "7.8.1"
@ -3718,7 +3720,6 @@ function-bind@^1.1.1:
function.prototype.name@^1.1.5: function.prototype.name@^1.1.5:
version "1.1.5" version "1.1.5"
resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==
dependencies: dependencies:
call-bind "^1.0.2" call-bind "^1.0.2"
define-properties "^1.1.3" define-properties "^1.1.3"
@ -3733,7 +3734,6 @@ functional-red-black-tree@^1.0.1:
functions-have-names@^1.2.2: functions-have-names@^1.2.2:
version "1.2.3" version "1.2.3"
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
gensync@^1.0.0-beta.2: gensync@^1.0.0-beta.2:
version "1.0.0-beta.2" version "1.0.0-beta.2"
@ -3878,7 +3878,6 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.2.4
has-bigints@^1.0.1, has-bigints@^1.0.2: has-bigints@^1.0.1, has-bigints@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
has-flag@^3.0.0: has-flag@^3.0.0:
version "3.0.0" version "3.0.0"
@ -5919,7 +5918,6 @@ qs@6.10.3:
qs@^6.5.1: qs@^6.5.1:
version "6.11.0" version "6.11.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
dependencies: dependencies:
side-channel "^1.0.4" side-channel "^1.0.4"
@ -6389,7 +6387,6 @@ shebang-regex@^3.0.0:
shell-quote@^1.7.3: shell-quote@^1.7.3:
version "1.7.3" version "1.7.3"
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123"
integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==
side-channel@^1.0.4: side-channel@^1.0.4:
version "1.0.4" version "1.0.4"
@ -7004,7 +7001,6 @@ untildify@^4.0.0:
update-browserslist-db@^1.0.5: update-browserslist-db@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38"
integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==
dependencies: dependencies:
escalade "^3.1.1" escalade "^3.1.1"
picocolors "^1.0.0" picocolors "^1.0.0"
@ -7244,7 +7240,6 @@ yallist@^2.1.2:
yallist@^4.0.0: yallist@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yaml@^1.10.0, yaml@^1.10.2: yaml@^1.10.0, yaml@^1.10.2:
version "1.10.2" version "1.10.2"
@ -7272,7 +7267,6 @@ yargs-parser@^20.2.2:
yargs-parser@^21.0.0: yargs-parser@^21.0.0:
version "21.1.1" version "21.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
yargs-unparser@2.0.0: yargs-unparser@2.0.0:
version "2.0.0" version "2.0.0"