Skip to content

Twitch.tv Compact Left Panel by pabli

Screenshot of Twitch.tv Compact Left Panel

Details

Authorpabli

LicenseMIT

Categorytwitch.tv

Created

Updated

Size9.7 kB

Statistics

Learn how we calculate statistics in the FAQ.

Failed to fetch stats.

Description

Customizable compact left panel (sidebar) for Twitch.tv

Notes

☕ Support me on ko-fi

Features:

  • Change width
  • Show left panel on hover over the edge (useful in Theatre Mode)
  • Hide offline channels
  • Hide channels without unfollowing them
  • Favorite channels
  • Square avatars
  • Hide headers, red dot
  • Display lines with alternating background colors
  • Change colors of background and text
  • Features for "Previews (For TTV & YT)" extension:
    • Put YT channels under the Followed channels
    • Set the text color for favorite/youtube channels (useful when headers are hidden)

You can change all of that stuff in ⚙️ Configure

Chrome/Edge 105+, Opera 91+, Firefox 121+ or your browser has to support :has() selector.

Source code

/* ==UserStyle==
@name         Twitch Compact Left Panel
@namespace    https://github.com/pabli24
@version      2.0.4
@description  Twitch.tv Smaller sidebar with many customization options
@author       Pabli (https://ko-fi.com/pabli)
@license      MIT
@preprocessor stylus

@var checkbox _compact             "Compact Left Panel" 1
@var number   _width               "Width (rem)" [16, -1, null, 0.1, "rem"]
@var number   _widthCollapse       "Width when collapsed (rem)" [4, -1, null, 0.1, "rem"]
@var select   _showOnHover         "Show left panel on hover" ["Disabled", "Enabled", "thm:In Theatre Mode*"]
@var number   _showOnHoverOpacity  "➥ Opacity on hover" [0.9, 0, 1, 0.1]

@var checkbox _hideChannels        "❌ Hide channels" 1
@var text     _hiddenChannels      "" "'ChannelName1, ChannelName2'"

@var checkbox _favorite            "⭐ Favorite channels" 1
@var text     _favChannels         "" "'ChannelName1, ChannelName2'"
@var checkbox _favTop              "Favorite channels at the top of the following list (Extension that can 'Auto Expand Followed Channels List (show more)' is recommended)" 1
@var color    _favColor            "Favorite channels name text color" #ffd700
@var text     _favIcon             "Favorite channels icon (e.g. ★ ♥ 🖈 📌 ❤️)" "'⭐'"

@var number   _squareAvatars       "Square avatars □" [0, -1, 50, 1, "%"]
@var checkbox _hideCollapse        "Hide Collapse button ⟻" 0
@var checkbox _hideHeaders         "Hide Headers" 1
@var checkbox _hideLiveDot         "Hide Red dot 🔴" 1
@var checkbox _hideOfflineChannels "Hide Offline channels" 0
@var checkbox _hideStories         "Hide Stories" 0
@var checkbox _bgOdd               "Alternating Background (can impact performance)" 0
@var color    _bgOddColor          "" rgba(128, 128, 128, .06)
@var checkbox _bg                  "Background color" 0
@var color    _bgColor             "" #000
@var checkbox _bgOnHover           "Background color on hover" 0
@var color    _bgColorOnHover      "" #222
@var checkbox _isNameColor         "Channel name text color" 0
@var color    _nameColor           "" #fff
@var checkbox _isViewsColor        "Viewer count text color" 1
@var color    _viewsColor          "" #ff8282
@var checkbox _isGameColor         "Game name text color" 0
@var color    _gameColor           "" #aaa

@var number   _h0                  "▼ --- Previews (For TTV & YT) EXTENSION --- ▼" [0,0,0]
@var checkbox _isPreviewsFavColor  "Channel name text color in 'Favorite Channels'" 1
@var color    _previewsFavColor    "" #ffd700
@var checkbox _isPreviewsYTColor   "Channel name text color in 'YouTube Channels'" 1
@var color    _previewsYTTColor    "" #ff4e45
@var checkbox _previewsYTUnder     "Put YouTube channels under the Followed channels" 0

@var number   _p0                  "☕ ko-fi.com/pabli - If you like this style and would like to support me, you can buy me a coffee. Thank You!" [0,0,0,1]
==/UserStyle== */

@-moz-document domain("twitch.tv") {

i = !important

if _width != -1 {
	.side-nav {
		width: _width
	}
}

if _widthCollapse != -1 {
	.side-nav--collapsed:not(.side-nav--hover-exp) {
		width: _widthCollapse
	}
}

if _hideHeaders {
	#tp_favorites_section, #tp_YTsidebar_section {
		> div > [style*="color: grey"] {
			display: none i
		}
	}
	.followed-side-nav-header, .side-nav__title, .side-nav-header {
		display: none i
	}
}

if _hideCollapse {
	.collapse-toggle {
		display: none i
	}
}

if _isViewsColor {
	.side-nav-card__live-status > div > div > span {
		color: _viewsColor i
	}
}

if _hideLiveDot {
	.tw-channel-status-indicator {
		display: none i
	}
}

if _compact {
	.collapse-toggle {
		unless _hideHeaders {
			top: 2rem i
		}
		right: -1.3rem i
	}
	// dots ...
	[data-a-target="side-nav-card-metadata"] > div > p {
		text-overflow: clip i
		overflow: unset i
	}
	
	.side-nav-header {
		margin: 0 0.2rem i
		padding-top: 0 i
	}
	.followed-side-nav-header, .followed-side-nav-header--expanded, [data-a-target="side-nav-header-expanded"] {
		margin: 0 i
	}
	// For you
	#side-nav > div > div > div.side-nav__title {
		display: none 
	}
	
	#side-nav > div > div > div[class*="storiesLeftNavSection"] {
		margin-top: 0 i
		height: 3.4rem i
		button > div {
			margin: 0 i
		}
	}
	
	[data-a-target="side-nav-card-metadata"] {
		margin-left: 0.2rem i
	}
	.side-nav-card__link {
		height: 3.4rem
		padding: 0 0.2rem i
	}
	.side-nav-card__live-status {
		min-width: 0 i
		margin-left: 0 i
	}
	.kaXoQh {
		margin-left: 0.2rem i
	}
	
	.side-nav-card__link > * {
		height: 100%
		margin: 0 i
	}
	[data-a-target="side-nav-game-title"] > p {
		position: absolute
	}
	
	// show less show more
	.side-nav-show-more-toggle__button {
		padding: 0 i
	}
	
	#side-nav\.find-friends {
		height: 2.2rem i
	}
	
	// sponsored stream
	.side-nav-card__link--promoted-followed {
		.tw-image:not(.tw-image-avatar),
		[style*="background-color:"]
		.side-nav-promoted-followed-card__sponsorship {
			display: none i
		}
		> div > div {
			padding-top: 0 i
		}
		.side-nav-promoted-followed-card__title {
			position: absolute
			top: -6px
			left: 34px
		}
		.side-nav-promoted-followed-card__content {
			position: absolute
			top: 13px
			left: 34px
		}
	}
	// hype train
	.side-nav-card-hype-train-bottom {
		margin: 0 i
		padding: 0 i
		> :not(div:has(>[class*="hype-train-icon__"])) {
			display: none i
		}
		[class*="hype-train-icon__"] {
			position: absolute
			right: 0
			top: 15px
		}
	}
}

if _showOnHover != Disabled {
	thmode = _showOnHover == thm ? ":has(.channel-root__scroll-area--theatre-mode)" : ""
	body{thmode} {
		> .previews_app_previewDiv {
			z-index: 9999 i
		}
		div:has(>.side-nav), div[style="z-index: 10;"] {
			z-index: 99999 i
		}
		.side-nav, .side-nav--collapsed:not(.side-nav--hover-exp) {
			position: fixed i
			top: 0 i
			width: 1rem
			opacity: 0
			transition: width 0.3s, opacity 0.5s
			&:hover {
				width: _width
				opacity: _showOnHoverOpacity
			}
		}
		.side-nav--collapsed:not(.side-nav--hover-exp):hover {
			width: _widthCollapse
		}
	}
}

if _hideOfflineChannels {
	#side-nav > div > div > div > div > div:has(.side-nav-card__avatar--offline) {
		display none i
	}
}

if _hideStories {
	#side-nav > div > div > div[class*="storiesLeftNavSection"] {
		display none i
	}
}

if _squareAvatars != -1 {
	.tw-image-avatar, .tw-avatar, .tw-halo, .tw-halo::before {
		border-radius: _squareAvatars i
	}
	if _squareAvatars != 50 {
		#side-nav > div > div > div[class*="storiesLeftNavSection"] > button > div > div > div > div {
			border-radius: _squareAvatars i
		}
	}
}

if _isNameColor {
	#side-nav .side-nav-card__title > p, 
	#side-nav [data-a-target="side-nav-card-metadata"] p {
		--color-text-alt: _nameColor
		color: _nameColor i
	}
}

if _isGameColor {
	#side-nav .side-nav-card__metadata > p {
		--color-text-alt-2: _gameColor
		color: _gameColor i
	}
}

if _bg {
	.tw-root--theme-dark .side-nav__overlay-wrapper, .side-nav__overlay-wrapper, .side-bar-contents {
		background: _bgColor i
	}
}

if _bgOdd {
	//.side-nav-card[style="display: none;"] --> Previews (For TTV & YT) Sidebar Favorite Channels - Hide favorite channels from followed list
	#side-nav .tw-transition-group > div:nth-child(odd of :not(:has(:is({t} .side-nav-card[style="display: none;"])))) {
		background: _bgOddColor i
	}
}

if _bgOnHover {
	.tw-root--theme-dark .side-nav-card__link:hover, .side-nav-card__link:hover {
		background: _bgColorOnHover i
	}
}

// --- Previews (For TTV & YT) extension ---
body > .previews_app_previewDiv:not([style*="margin-left: 6rem"]) {
	margin-left: _width + 1 i
}
.tp-tooltip-sidebar {
	height: auto
}

if _isPreviewsFavColor {
	#tp_favorites_section [data-a-target="side-nav-title"] {
		color: _previewsFavColor i
	}
}

if _isPreviewsYTColor {
	#tp_YTsidebar_section [data-a-target="side-nav-title"] {
		color: _previewsYTColor i
	}
}

if _previewsYTUnder {
	#side-nav > div > div {
		display: flex
		flex-direction: column
	}
	#tp_favorites_section {
		order: -5 i
	}
	#side-nav > div > div > div:not([aria-label]) + div[aria-label]:not([id]) {
		order: -4 i
	}
	#side-nav > div > div > div:has(.followed-side-nav-header):not([id]) {
		order: -4 i
	}
	#tp_YTsidebar_section {
		order: -3 i
	}
}

filter(a) {
	a = split(',', replace('^\s+|\s+(?=,)|(?<=,)\s+|\s+$', '', a))
	b = ()
	for n in a {
		if n != '' {
			push(b, n)
		}
	}
	return b
}

if _hideChannels {
	t = ()
	if _hiddenChannels != 'ChannelName1, ChannelName2' {
		_hiddenChannels = filter(_hiddenChannels)
		for n in _hiddenChannels {
			push(t,'[href="/'+ n +'" i]')
		}
		t = join("\,", t)
		#side-nav .side-nav-section > div > .tw-transition:has(:is({t})) {
			display none i
		}
	}
}

if _favorite {
	t = ()
	if _favChannels != 'ChannelName1, ChannelName2' {
		_favChannels = filter(_favChannels)
		for n in _favChannels {
			push(t,'[href="/'+ n +'" i]')
		}
		t = join("\,", t)
		if _favTop {
			#side-nav .side-nav-section:has(> .followed-side-nav-header) > div.tw-transition-group {
				display: flex
				flex-direction: column
			}
			#side-nav .side-nav-section:has(> .followed-side-nav-header) > div.tw-transition-group .tw-transition:has(:is({t})) {
				order: -1 i
			}
		}
		
		#side-nav .side-nav-section:has(> .followed-side-nav-header) > div.tw-transition-group .tw-transition:has(:is({t})) :is(.side-nav-card__title, [data-a-target="side-nav-card-metadata"] > div:first-child) > p {
			--color-text-alt: _favColor
			color: _favColor i
		}
		if _favIcon != "" {
			#side-nav .side-nav-section:has(> .followed-side-nav-header) > div.tw-transition-group .tw-transition:has(:is({t})) :is(.side-nav-card__title, [data-a-target="side-nav-card-metadata"] > div:first-child) > p:first-child::before {
				content: _favIcon
			}
		}
	}
}

}

Reviews

No reviews yet.