Skip to content

Instantly share code, notes, and snippets.

@klydeinside
Last active August 12, 2026 04:46
Show Gist options
  • Select an option

  • Save klydeinside/348c673b051fda32ad4cd63dde544626 to your computer and use it in GitHub Desktop.

Select an option

Save klydeinside/348c673b051fda32ad4cd63dde544626 to your computer and use it in GitHub Desktop.
Twitch userscripts - Liquid Glass Sidebar
// ==UserScript==
// @name Twitch – Liquid Glass Sidebar
// @namespace https://cody-tools.local
// @version 1.6
// @description Frosted, glossy "Liquid Glass" treatment for the Twitch left sidebar (original iOS 26 beta style — almost fully see-through with a crisp bright rim) plus a cursor-tracked shine on hover. Hides the sidebar scrollbar. Cycle intensity with the bottom-right pill.
// @match https://www.twitch.tv/*
// @grant GM_setValue
// @grant GM_getValue
// @updateURL https://gist.githubusercontent.com/klydeinside/348c673b051fda32ad4cd63dde544626/raw/twitch-liquid-glass-sidebar.user.js
// @downloadURL https://gist.githubusercontent.com/klydeinside/348c673b051fda32ad4cd63dde544626/raw/twitch-liquid-glass-sidebar.user.js
// ==/UserScript==
(function () {
'use strict';
const STYLE_ID = 'lgSidebarStyle';
const TOGGLE_ID = 'lgSidebarToggle';
const LEVEL_KEY = 'lgSidebarLevel';
const LEVELS = ['Off', 'Subtle', 'Full'];
const SIDE_NAV = '[data-a-target="side-nav-bar"]';
const SCROLL_AREA = '.side-nav__scrollable_content';
const HEADER = '.followed-side-nav-header, .side-nav-header';
const CARD = '.side-nav-card';
const AVATAR_IMG = '.side-nav-card__avatar img';
function getLevel() {
const v = GM_getValue(LEVEL_KEY, 2);
return (v === 0 || v === 1 || v === 2) ? v : 2;
}
function setLevel(n) {
GM_setValue(LEVEL_KEY, n);
applyStyle();
updateToggleLabel();
}
function applyStyle() {
let style = document.getElementById(STYLE_ID);
if (!style) {
style = document.createElement('style');
style.id = STYLE_ID;
document.head.appendChild(style);
}
const level = getLevel();
if (level === 0) {
style.textContent = '';
return;
}
const base = `
${SIDE_NAV} {
position: relative;
background:
linear-gradient(180deg, rgba(255,255,255,0.09), rgba(255,255,255,0.01) 35%, rgba(255,255,255,0.04)),
color-mix(in srgb, var(--color-background-body, #0e0e10) 20%, transparent) !important;
-webkit-backdrop-filter: blur(14px) saturate(140%);
backdrop-filter: blur(14px) saturate(140%);
border-right: 1px solid rgba(255,255,255,0.35);
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.5),
inset -1px 0 0 rgba(255,255,255,0.08),
1px 0 0 rgba(120,180,255,0.12),
14px 0 34px rgba(0,0,0,0.5);
}
${SCROLL_AREA} {
background: transparent !important;
scrollbar-width: none;
-ms-overflow-style: none;
}
${SCROLL_AREA}::-webkit-scrollbar {
display: none;
}
${HEADER} {
position: relative;
-webkit-backdrop-filter: blur(8px);
backdrop-filter: blur(8px);
background: rgba(255,255,255,0.03) !important;
border-bottom: 1px solid rgba(255,255,255,0.1);
}
${CARD} {
position: relative;
border-radius: 10px;
transition:
background 0.25s ease,
transform 0.2s cubic-bezier(0.16, 1, 0.3, 1),
box-shadow 0.25s ease;
}
${CARD}:hover {
background: color-mix(in srgb, white 7%, transparent);
box-shadow:
inset 0 0 0 1px rgba(255,255,255,0.4),
0 6px 16px rgba(0,0,0,0.35);
transform: translateX(3px) scale(1.015);
}
${AVATAR_IMG} {
box-shadow: 0 0 0 1px rgba(255,255,255,0.2);
}
`;
const full = `
${SIDE_NAV}::after {
content: "";
position: absolute;
inset: 0;
pointer-events: none;
background: linear-gradient(
115deg,
transparent 15%,
rgba(255,255,255,0.07) 38%,
rgba(255,255,255,0.18) 50%,
rgba(255,255,255,0.07) 62%,
transparent 85%
);
background-size: 250% 250%;
mix-blend-mode: overlay;
animation: lgSheen 7s ease-in-out infinite;
}
@keyframes lgSheen {
0% { background-position: 0% 0%; }
50% { background-position: 100% 100%; }
100% { background-position: 0% 0%; }
}
${CARD}::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s ease;
background: radial-gradient(
160px 160px at var(--lg-mx, 50%) var(--lg-my, 50%),
rgba(255,255,255,0.3),
transparent 65%
);
}
${CARD}:hover::before {
opacity: 1;
}
`;
style.textContent = level === 2 ? base + full : base;
}
let shineHandlerBound = false;
function bindShineHandler() {
if (shineHandlerBound) return;
shineHandlerBound = true;
document.addEventListener('mousemove', (e) => {
if (getLevel() !== 2) return;
const card = e.target.closest && e.target.closest(CARD);
if (!card) return;
const rect = card.getBoundingClientRect();
const x = ((e.clientX - rect.left) / rect.width) * 100;
const y = ((e.clientY - rect.top) / rect.height) * 100;
card.style.setProperty('--lg-mx', `${x}%`);
card.style.setProperty('--lg-my', `${y}%`);
}, { passive: true });
}
function updateToggleLabel() {
const btn = document.getElementById(TOGGLE_ID);
if (btn) btn.textContent = `Glass: ${LEVELS[getLevel()]}`;
}
function createToggle() {
if (document.getElementById(TOGGLE_ID)) return;
const btn = document.createElement('button');
btn.id = TOGGLE_ID;
btn.style.cssText = `
position: fixed;
bottom: 76px;
right: 20px;
z-index: 999999;
padding: 8px 14px;
background: #9147ff;
color: #fff;
border: none;
border-radius: 9999px;
font-size: 13px;
font-weight: 700;
font-family: Arial, sans-serif;
cursor: pointer;
box-shadow: 0 4px 12px rgba(0,0,0,0.35);
`;
btn.onclick = () => setLevel((getLevel() + 1) % LEVELS.length);
document.body.appendChild(btn);
updateToggleLabel();
}
function tick() {
if (document.querySelector(SIDE_NAV)) {
applyStyle();
createToggle();
bindShineHandler();
}
}
let tickScheduled = false;
function scheduleTick() {
if (tickScheduled) return;
tickScheduled = true;
requestAnimationFrame(() => {
tickScheduled = false;
tick();
});
}
const origPushState = history.pushState;
history.pushState = function (...args) {
origPushState.apply(this, args);
scheduleTick();
};
window.addEventListener('popstate', scheduleTick);
const observer = new MutationObserver(scheduleTick);
observer.observe(document.body, { childList: true, subtree: true });
tick();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment