Twitch Dashboard Side Nav Revision

In this example below you will see how to do a Twitch Dashboard Side Nav Revision with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by Alca, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright Alca ©
  • HTML
  • CSS
  • JavaScript
    #revised-side-nav
	.section
		.title Dashboard
		.options
			.opt Live
			.opt Extensions
			.opt Achievements
			.opt Events
			.opt Activity
			.opt Streaming Tools
	.section
		.title Analytics
		.options
			.opt Channel
			.opt Stream Summary
	.section
		.title Videos
		.options
			.opt Video Producer
			.opt Video Moderation
			.opt Collections
			.opt Clips
	.section
		.title Settings
		.options
			.opt Channel
			.opt Permissions
			.opt Moderation
			.opt Affiliate / Partner
#dashboard
	.column
		.section#chat
			.title Chat
		.section
			.title Stats
		.section.closed
			.title Video Broadcast
		.section.closed
			.title Host
	.column
		.section
			.title Stream Information
		.section.closed
			.title Stream Health
		.section.closed
			.title Video Preview
		.section.closed
			.title Extensions
	.column
	.column

/*Downloaded from https://www.codeseek.co/Alca/twitch-dashboard-side-nav-revision-wXMmGo */
    body {
	background: hsl(0, 0%, 8.3%);
	color: hsl(0, 0%, 85%);
	font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
	margin: 40px 0 0;
	user-select: none;
}

#revised-side-nav {
	background: hsl(0, 0%, 5.5%);
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	font-size: 0;
	z-index: 100;
	
	.section {
		font-size: 14px;
		display: inline-block;
		position: relative;
		
		.title {
			padding: 12px 16px;
			cursor: pointer;
			
			&:hover {
				text-decoration: underline;
				background: hsl(0, 0%, 9.6%);
			}
			&:active {
				background: hsl(0, 0%, 8.4%);
			}
		}
		.options {
			--bg-color: hsl(0, 0%, 4.2%);
			display: none;
			background: var(--bg-color);
			font-size: 12px;
			width: 180px;
			padding: 8px;
			position: absolute;
			top: 105%;
			z-index: 200;
			
			.opt {
				padding: 6px 10px;
				width: 100%;
				box-sizing: border-box;
				cursor: pointer;
				
				&:hover {
					background: hsl(0, 0%, 6.8%);
				}
			}
			&:before {
				display: block;
				content: '';
				border-style: solid;
				border-width: 0 5px 6px 5px;
				border-color: transparent transparent var(--bg-color) transparent;
				position: absolute;
				top: -6px;
				left: 24px;
			}
		}
		&.showing .options {
			display: block;
		}
	}
}

#dashboard {
	--padding: 20px;
	white-space: nowrap;
	padding: var(--padding);
	font-size: 0;
	overflow-x: hidden;
	
	.column {
		display: inline-block;
		vertical-align: top;
		
		&:not(:last-child) {
			margin-right: var(--padding);
		}
	}
	
	.section {
		--border-color: hsl(0, 0%, 16%);
		width: 415px;
		border: 1px solid var(--border-color);
		font-size: 14px;
		height: 240px;
		background: hsl(0, 0%, 11.3%);
		transition: 100ms height;
		
		&:not(:last-child) {
			margin-bottom: var(--padding);
		}
		.title {
			border-bottom: 1px solid var(--border-color);
			height: 44px;
			line-height: 44px;
			padding-left: 44px;
			position: relative;
			cursor: move;
			
			&:before {
				display: inline;
				content: '';
				width: 0;
				height: 0;
				cursor: pointer;
				border-style: solid;
				border-width: 6px 5px 0 5px;
				border-color: hsl(0, 0%, 85%) transparent transparent transparent;
				position: absolute;
				top: 19px;
				left: 17px;
				transition: 50ms transform ease-in-out;
			}
		}
		&#chat {
			background: hsl(0, 0%, 5.5%);
			
			.title {
				background: hsl(0, 0%, 11.3%);
			}
		}
		&.closed {
			height: 45px;
			
			.title:before {
				transform: rotate(-90deg);
			}
		}
	}
}


/*Downloaded from https://www.codeseek.co/Alca/twitch-dashboard-side-nav-revision-wXMmGo */
    class NavSection {
	constructor(section) {
		let [ title, options ] = section.children;
		this.section = section;
		this.title = title;
		this.options = options;
		this.showing = false;
		
		this._listeners = [];

		title.addEventListener('click', () => {
			let showed = this.toggle();
			this.emit('clicked', showed);
		});
	}
	toggle(show = !this.showing) {
		if(show === this.showing) {
			return;
		}
		this.showing = show;
		this.section.classList[show ? 'add' : 'remove']('showing');
		return show;
	}
	show() {
		return this.toggle(true);
	}
	hide() {
		return this.toggle(false);
	}
	on(eventName, cb) {
		this._listeners.push({ eventName, cb });
	}
	emit(eventName, ...data) {
		let listeners = this._listeners.filter(n => n.eventName === eventName);
		listeners.forEach(l => l.cb.apply(this, data));
	}
}

let sectionElements = Array.from(document.querySelectorAll('#revised-side-nav .section'));
let sections = sectionElements.map(section => {
	let ns = new NavSection(section);
	ns.on('clicked', () => sections.forEach(n => n !== ns && n.hide()));
	return ns;
});

window.addEventListener('click', e => {
	let { target, path } = e;
	if(!path.some(n => n.id === 'revised-side-nav')) {
		sections.forEach(n => n.hide());
		
		if(
			path.some(n => n.id === 'dashboard') &&
			target.classList.contains('title')
		) {
			target.parentNode.classList.toggle('closed');
		}
	}
});

Comments