Greasy Fork is available in English.
Move Kick chat left without the visible slide, while avoiding blank chat
// ==UserScript==
// @name Kick Left Chat
// @namespace https://kick.com/
// @version 0.3.1
// @description Move Kick chat left without the visible slide, while avoiding blank chat
// @match https://kick.com/*
// @grant GM_addStyle
// @run-at document-start
// ==/UserScript==
(function () {
'use strict';
const CHAT_WIDTH = 350;
const READY_CLASS = 'kick-left-chat-ready';
GM_addStyle(`
/* Hide chat until it has been moved and is ready */
#channel-chatroom {
opacity: 0 !important;
pointer-events: none !important;
}
#channel-chatroom.${READY_CLASS} {
opacity: 1 !important;
pointer-events: auto !important;
}
`);
function chatLooksReady(chat) {
if (!chat) return false;
// Need more than just the empty shell existing
const hasChildren = chat.querySelector('*') !== null;
const hasText = (chat.textContent || '').trim().length > 20;
const rect = chat.getBoundingClientRect();
return hasChildren && (hasText || rect.height > 200);
}
function moveChatLeft() {
const chat = document.getElementById('channel-chatroom');
const main = document.querySelector('main');
if (!chat || !main) return false;
// Wait until chat is actually populated, not just present
if (!chatLooksReady(chat)) return false;
// If chat is nested inside main on some layouts, do nothing
if (main.contains(chat)) return false;
const parent = main.parentElement;
if (!parent) return false;
// This is the part from the version that actually worked for you
if (chat.parentElement !== parent || chat !== main.previousElementSibling) {
parent.insertBefore(chat, main);
}
chat.style.width = `${CHAT_WIDTH}px`;
chat.style.minWidth = `${CHAT_WIDTH}px`;
chat.style.flex = `0 0 ${CHAT_WIDTH}px`;
main.style.flex = '1 1 auto';
main.style.minWidth = '0';
chat.classList.add(READY_CLASS);
return true;
}
const observer = new MutationObserver(() => {
moveChatLeft();
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
// Try repeatedly during initial load/hydration
let tries = 0;
const timer = setInterval(() => {
tries += 1;
const done = moveChatLeft();
// Stop after success or after ~10 seconds
if (done || tries >= 40) {
clearInterval(timer);
// Failsafe: never leave chat hidden forever
const chat = document.getElementById('channel-chatroom');
if (chat && !chat.classList.contains(READY_CLASS)) {
chat.classList.add(READY_CLASS);
}
}
}, 250);
window.addEventListener('load', moveChatLeft);
})();