Skip to content

Commit

Permalink
feat: toggle sidebar in responsive mode | #15 #19
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzodianni committed Jan 7, 2023
1 parent 2e7d5ae commit c70ef99
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 81 deletions.
10 changes: 0 additions & 10 deletions demo/demo.css
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,3 @@ input[type="radio"]:checked + label:before {
h2 {
margin: 12px 0;
}

@media (min-width: 1025px) {
[sidebarjs-toggle="rightSidebarName"] {
margin-left: auto;
}

[sidebarjs-toggle="leftSidebarName"], [sidebarjs-toggle=""] {
display: none;
}
}
1 change: 0 additions & 1 deletion src/sidebar.core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ export const SIDEBARJS_FALLBACK_NAME = '';
export const SIDEBARJS_CONTENT = 'sidebarjs-content';
export const SIDEBARJS_TRANSITION_START = 'sidebarjs--transition-start';
export const SIDEBARJS_TRANSITION_END = 'sidebarjs--transition-end';
export const SIDEBARJS_RESPONSIVE = 'sidebarjs--responsive';
export const IS_VISIBLE = `${SIDEBARJS}--is-visible`;
export const IS_MOVING = `${SIDEBARJS}--is-moving`;
export const POSITIONS: SidebarPosition[] = [SidebarPosition.Left, SidebarPosition.Right];
Expand Down
41 changes: 24 additions & 17 deletions src/sidebar.element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
SidebarConfig,
SIDEBARJS,
SIDEBARJS_CONTENT,
SIDEBARJS_RESPONSIVE,
SIDEBARJS_TRANSITION_END,
SIDEBARJS_TRANSITION_START,
SidebarPosition,
Expand Down Expand Up @@ -131,15 +130,15 @@ export class SidebarElement implements SidebarBase {
}

public setPosition(position: SidebarPosition): void {
this.addComponentClass(IS_MOVING);
this.position = POSITIONS.indexOf(position) >= 0 ? position : SidebarPosition.Left;
const resetMainContent = (document.querySelectorAll(`[${SIDEBARJS}]`) || []).length === 1;
this.removeComponentClassPosition(resetMainContent);
this.addComponentClass(`${SIDEBARJS}--${this.position}`);
if (this.responsive && this.mainContent) {
this.mainContent.classList.add(`${SIDEBARJS_CONTENT}--${this.position}`);
}
setTimeout(() => this.component && this.removeComponentClass(IS_MOVING), 200);
this.invokeWithoutComponentTransition(() => {
this.position = POSITIONS.indexOf(position) >= 0 ? position : SidebarPosition.Left;
const resetMainContent = (document.querySelectorAll(`[${SIDEBARJS}]`) || []).length === 1;
this.removeComponentClassPosition(resetMainContent);
this.addComponentClass(`${SIDEBARJS}--${this.position}`);
if (this.responsive && this.mainContent) {
this.mainContent.classList.add(`${SIDEBARJS_CONTENT}--${this.position}`);
}
}, true);
}

public addAttrsEventsListeners(sidebarName: string): void {
Expand Down Expand Up @@ -354,12 +353,8 @@ export class SidebarElement implements SidebarBase {
if (this.responsive && !this.mainContent) {
throw new Error(`You have set {responsive: true} without provide a [${SIDEBARJS_CONTENT}] element`);
}
this.addComponentClass(SIDEBARJS_RESPONSIVE);
const destroyMediaQuery = this.setMediaQuery(breakpoint);
return () => {
destroyMediaQuery();
this.removeComponentClass(SIDEBARJS_RESPONSIVE);
};
return () => destroyMediaQuery();
}

private setMediaQuery(breakpoint?: SidebarConfig['responsive']) {
Expand All @@ -371,11 +366,23 @@ export class SidebarElement implements SidebarBase {
return () => {
mediaQuery.removeEventListener('change', toggleMediaQueryClass);
this.toggleDesktopBreakpointClass(false);
}
};
}

private removeIsMovingComponentClass = () => {
this.component && this.removeComponentClass(IS_MOVING);
};

private invokeWithoutComponentTransition(fn: () => void, isAsync?: boolean) {
this.addComponentClass(IS_MOVING);
fn();
isAsync ? setTimeout(this.removeIsMovingComponentClass, 200) : this.removeIsMovingComponentClass();
}

private toggleDesktopBreakpointClass(isDesktop: boolean) {
document.body.classList.toggle('sidebarjs--desktop-breakpoint', isDesktop);
this.invokeWithoutComponentTransition(() => {
document.body.classList.toggle('sidebarjs--desktop-breakpoint', isDesktop);
}, true);
}

private applyStyle(el: HTMLElement, prop: CSSStyleProperties, val: CSSStyleValues, vendorify?: boolean): void {
Expand Down
126 changes: 73 additions & 53 deletions src/sidebarjs.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
$timing: ease;
$duration: .3s;
$width: 300px;
:root {
--sidebarjs-width: 300px;
--sidebarjs-transition-duration: .3s;
--sidebarjs-transition-timing-function: ease;
}

@mixin shadow($position) {
$x: 0;
Expand All @@ -19,14 +21,6 @@ $width: 300px;
height: 100%;
}

@mixin component--is-visible($important: null) {
transform: translate(0, 0) $important;
transition: transform 0s $timing 0s;
[sidebarjs-container] {
transform: translate(0, 0) $important;
}
}

%component--left {
transform: translate(-100%, 0);
}
Expand All @@ -35,31 +29,12 @@ $width: 300px;
transform: translate(100%, 0);
}

[sidebarjs].sidebarjs--left {
@extend %component--left;

[sidebarjs-container] {
@extend %component--left;
@include shadow('left');
}
}

[sidebarjs].sidebarjs--right {
@extend %component--right;

[sidebarjs-container] {
@extend %component--right;
@include shadow('right');
margin-left: auto;
}
}

[sidebarjs-backdrop] {
@extend %component--full-screen;
position: absolute;
background: #000;
opacity: 0;
transition: opacity $duration $timing;
transition: opacity var(--sidebarjs-transition-duration) var(--sidebarjs-transition-timing-function);
will-change: opacity;
}

Expand All @@ -69,29 +44,54 @@ $width: 300px;
display: flex;
flex-direction: column;
width: 90%;
max-width: $width;
max-width: var(--sidebarjs-width);
height: 100%;
background: #fff;
transition: transform $timing $duration;
transition: transform var(--sidebarjs-transition-timing-function) var(--sidebarjs-transition-duration);
will-change: transform;
}

[sidebarjs] {
@extend %component--full-screen;
position: fixed;
z-index: 9999;
transition: transform 0s $timing $duration;
transition: transform 0s var(--sidebarjs-transition-timing-function) var(--sidebarjs-transition-duration);

&.sidebarjs--is-visible {
@include component--is-visible;
transform: translate(0, 0);
transition: transform 0s var(--sidebarjs-transition-timing-function) 0s;

[sidebarjs-container] {
transform: translate(0, 0);
}
}

&.sidebarjs--is-moving {
transition: none;
transform: translate(0, 0);

[sidebarjs-container], [sidebarjs-backdrop] {
transition: none;
&, [sidebarjs-container], [sidebarjs-backdrop] {
transition: none !important;
}
}

&.sidebarjs--left {
&, [sidebarjs-container] {
@extend %component--left;
}

[sidebarjs-container] {
@include shadow('left');
}
}

&.sidebarjs--right {
&, [sidebarjs-container] {
@extend %component--right;
}

[sidebarjs-container] {
@include shadow('right');
margin-left: auto;
}
}
}
Expand All @@ -100,7 +100,7 @@ $width: 300px;
position: relative;
width: 100%;
min-height: 100%;
transition: width $duration $timing;
transition: width var(--sidebarjs-transition-duration) var(--sidebarjs-transition-timing-function);

&.sidebarjs-content--left {
margin-left: auto;
Expand All @@ -114,41 +114,61 @@ $width: 300px;
}

.sidebarjs--desktop-breakpoint {
[sidebarjs].sidebarjs--responsive {
@include component--is-visible(!important);
width: $width;
display: flex;

[sidebarjs-backdrop] {
display: none;
}

[sidebarjs] {
position: relative;
flex-shrink: 0;
height: 100vh;
width: 0;
transition: width var(--sidebarjs-transition-duration) var(--sidebarjs-transition-timing-function);

&.sidebarjs--transition-start {
will-change: width;
}

&.sidebarjs--is-visible {
width: var(--sidebarjs-width);
}

&.sidebarjs--left {
left: 0;
right: auto;
order: 0;

[sidebarjs-container] {
box-shadow: 1px 0 0 rgba(black, .1);
}
}

&.sidebarjs--right {
right: 0;
left: auto;
order: 1000;

[sidebarjs-container] {
box-shadow: -1px 0 0 rgba(black, .1);
}
}

&, [sidebarjs-container] {
transform: none;
}

[sidebarjs-container] {
max-width: none;
width: 100%;
box-shadow: none;
}
}

[sidebarjs-content] {
width: calc(100% - #{$width});

&.sidebarjs-content--left.sidebarjs-content--right {
width: calc(100% - #{$width*2});
margin: 0 auto;
&:not(.sidebarjs--is-visible) {
[sidebarjs-container] {
overflow-x: hidden;
}
}
}

[sidebarjs-content].sidebarjs-content--left.sidebarjs-content--right {
margin: 0 auto;
}
}

0 comments on commit c70ef99

Please sign in to comment.