Created
August 20, 2026 08:00
-
-
Save pfelipm/8a5b6c11d47aefc8ce0e6d91d3ecfe7d to your computer and use it in GitHub Desktop.
NotebookLM / Gemini Notebook - Restaurar paneles
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name NotebookLM / Gemini Notebook - Restaurar paneles | |
| // @namespace https://github.com/ | |
| // @version 1.1.0 | |
| // @description Restaura los paneles laterales en vistas restringidas. | |
| // @author Pablo Felip | |
| // @match *://notebooklm.google.com/* | |
| // @match *://notebook.google.com/* | |
| // @match *://notebooklm.google/* | |
| // @match *://*.google.com/notebook/* | |
| // @match *://notebooklm.cloud.google.com/* | |
| // @run-at document-start | |
| // @grant GM_addStyle | |
| // ==/UserScript== | |
| (function () { | |
| 'use strict'; | |
| // 1. Inyección de reglas CSS con prioridad máxima para evitar el colapso visual | |
| const customStyles = ` | |
| /* Forzar visibilidad y dimensiones mínimas de los contenedores laterales */ | |
| mat-drawer, | |
| .mat-drawer, | |
| aside, | |
| [role="complementary"], | |
| [class*="source-panel"], | |
| [class*="studio-panel"], | |
| [class*="sidebar-container"], | |
| [class*="drawer-content"] { | |
| display: flex !important; | |
| visibility: visible !important; | |
| opacity: 1 !important; | |
| transform: none !important; | |
| } | |
| /* Evitar que el contenedor principal fuerce ancho cero a las columnas */ | |
| mat-drawer-container, | |
| .mat-drawer-container { | |
| overflow: visible !important; | |
| } | |
| /* Sobrescribir estados cerrados de Angular Material */ | |
| mat-drawer.mat-drawer-closed, | |
| .mat-drawer-closed { | |
| visibility: visible !important; | |
| min-width: 280px !important; | |
| width: auto !important; | |
| } | |
| /* Asegurar que el layout de tres columnas mantenga el reparto de espacio */ | |
| main, [role="main"] { | |
| max-width: 100% !important; | |
| } | |
| `; | |
| if (typeof GM_addStyle !== 'undefined') { | |
| GM_addStyle(customStyles); | |
| } else { | |
| const styleEl = document.createElement('style'); | |
| styleEl.id = 'nlm-restore-panels-style'; | |
| styleEl.textContent = customStyles; | |
| document.head ? document.head.appendChild(styleEl) : document.documentElement.appendChild(styleEl); | |
| } | |
| // 2. Función para limpiar clases y atributos de colapso en elementos existentes | |
| const restoreElements = () => { | |
| const selectors = [ | |
| 'mat-drawer', | |
| '.mat-drawer', | |
| 'aside', | |
| '[role="complementary"]', | |
| '[class*="panel"]', | |
| '[class*="drawer"]' | |
| ]; | |
| document.querySelectorAll(selectors.join(',')).forEach((el) => { | |
| // Elimina clases habituales de cierre/ocultación | |
| el.classList.remove( | |
| 'mat-drawer-closed', | |
| 'drawer-closed', | |
| 'hidden', | |
| 'collapsed', | |
| 'is-hidden', | |
| 'ng-hide' | |
| ); | |
| // Elimina inline styles que fuercen ancho o display nulo | |
| if (el.style.display === 'none') { | |
| el.style.removeProperty('display'); | |
| } | |
| if (el.style.visibility === 'hidden') { | |
| el.style.removeProperty('visibility'); | |
| } | |
| if (el.style.width === '0px' || el.style.width === '0') { | |
| el.style.removeProperty('width'); | |
| } | |
| }); | |
| }; | |
| // 3. Observador de mutaciones para interceptar el ciclo de renderizado dinámico (SPA) | |
| const observer = new MutationObserver((mutations) => { | |
| for (const mutation of mutations) { | |
| if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { | |
| restoreElements(); | |
| } else if (mutation.type === 'attributes' && (mutation.attributeName === 'class' || mutation.attributeName === 'style')) { | |
| const target = mutation.target; | |
| if ( | |
| target.classList.contains('mat-drawer-closed') || | |
| target.classList.contains('hidden') || | |
| target.style.display === 'none' | |
| ) { | |
| restoreElements(); | |
| } | |
| } | |
| } | |
| }); | |
| // 4. Iniciar la observación tan pronto como el DOM esté disponible | |
| const startObserver = () => { | |
| if (document.body) { | |
| observer.observe(document.body, { | |
| childList: true, | |
| subtree: true, | |
| attributes: true, | |
| attributeFilter: ['class', 'style'] | |
| }); | |
| restoreElements(); | |
| } else { | |
| document.addEventListener('DOMContentLoaded', () => { | |
| observer.observe(document.body, { | |
| childList: true, | |
| subtree: true, | |
| attributes: true, | |
| attributeFilter: ['class', 'style'] | |
| }); | |
| restoreElements(); | |
| }); | |
| } | |
| }; | |
| startObserver(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment