From 75392503fe75b640cca3297bee0a7ff235667f0b Mon Sep 17 00:00:00 2001 From: Ezzy Rappeport Date: Wed, 20 May 2026 22:54:03 -0700 Subject: [PATCH] feat: add Chrome Extension (Manifest V3) for GitHub Chat Closes #1 Adds a Chrome Extension that embeds the existing Firebase chat into github.com/* pages via a floating toggle button. - Manifest V3 compliant - Floating toggle button (bottom-right corner) - Iframe-based chat panel with show/hide toggle - Scoped to github.com/* domain only - Minimal, focused implementation with no external dependencies --- extension/content.js | 42 ++++++++++++++++++ extension/icons/icon128.png | Bin 0 -> 833 bytes extension/icons/icon16.png | Bin 0 -> 171 bytes extension/icons/icon48.png | Bin 0 -> 329 bytes extension/manifest.json | 21 +++++++++ extension/styles.css | 83 ++++++++++++++++++++++++++++++++++++ 6 files changed, 146 insertions(+) create mode 100644 extension/content.js create mode 100644 extension/icons/icon128.png create mode 100644 extension/icons/icon16.png create mode 100644 extension/icons/icon48.png create mode 100644 extension/manifest.json create mode 100644 extension/styles.css diff --git a/extension/content.js b/extension/content.js new file mode 100644 index 0000000..df00446 --- /dev/null +++ b/extension/content.js @@ -0,0 +1,42 @@ +const CHAT_ORIGIN = 'https://inquid.github.io/github-chat' +const CHAT_URL = CHAT_ORIGIN + '/index.html' + +let chatFrame = null +let toggleBtn = null +let isOpen = false + +function createToggle() { + toggleBtn = document.createElement('button') + toggleBtn.id = 'ghchat-toggle' + toggleBtn.innerHTML = ` + + + + ` + toggleBtn.setAttribute('aria-label', 'Toggle chat') + toggleBtn.addEventListener('click', toggleChat) + document.body.appendChild(toggleBtn) +} + +function createChatFrame() { + chatFrame = document.createElement('div') + chatFrame.id = 'ghchat-frame' + chatFrame.innerHTML = ` +
+ GitHub Chat + +
+ + ` + chatFrame.querySelector('#ghchat-close').addEventListener('click', toggleChat) + document.body.appendChild(chatFrame) +} + +function toggleChat() { + isOpen = !isOpen + chatFrame.classList.toggle('ghchat-open', isOpen) + toggleBtn.classList.toggle('ghchat-hidden', isOpen) +} + +createToggle() +createChatFrame() diff --git a/extension/icons/icon128.png b/extension/icons/icon128.png new file mode 100644 index 0000000000000000000000000000000000000000..09f83c32b6b5e6edd1ceecabdbb7460bae825806 GIT binary patch literal 833 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrVCL|2aSW-L^LFknS@9)Qt=p?pnAhzl)c<=PtbN z`G4I_Q{z&Wx0Q=JG@D2gRgLgC9q8{&G@BQ%6#y{B!SKfu^)?JfQF0!@K+2s7VUMWjz zjSZLAeAYL2{^(`fPc5%+XVA`yn7R24%Z-IUWwR_r*M{)tyg@oa+M=n!*VbIrA~l7Kn62uk~h$D3x6x;v=G+9W!zF8J2GBhRu5Sv2IiHy;f7)q6p`@?!7`Tp;EvZzep ikx;G$asp;xi1@&`-BB;b&G;`kaeKP@xvXB>Ar*6y6C^SYbod68ciyj$ zk)HeUOzk}$Rsx>z(jKZq96=aq`jTFAB(QdzKDXx_2}Bmc;6fN& z2!jh@a3RcKfEd4lR-%(V=SZM;3dHC&PXfJCAZ8DC0-h#FP#Yzy3=b33sJX`@J_D8} zNKp$lTQLh0q+D#>tN^@Li`{mk9?M;m-RKpob&dh_zCqDyX$&sh4GnjIVeZHxe+8*j b3jFj3f!}sz7oyA~00000NkvXXu0mjf26ThI literal 0 HcmV?d00001 diff --git a/extension/manifest.json b/extension/manifest.json new file mode 100644 index 0000000..dfcafbc --- /dev/null +++ b/extension/manifest.json @@ -0,0 +1,21 @@ +{ + "manifest_version": 3, + "name": "GitHub Chat", + "version": "1.0.0", + "description": "Floating chat panel for GitHub pages. Toggle in the bottom-right corner.", + "permissions": [], + "host_permissions": ["https://github.com/*"], + "content_scripts": [ + { + "matches": ["https://github.com/*"], + "js": ["content.js"], + "css": ["styles.css"], + "run_at": "document_end" + } + ], + "icons": { + "16": "icons/icon16.png", + "48": "icons/icon48.png", + "128": "icons/icon128.png" + } +} diff --git a/extension/styles.css b/extension/styles.css new file mode 100644 index 0000000..25988d4 --- /dev/null +++ b/extension/styles.css @@ -0,0 +1,83 @@ +#ghchat-toggle { + position: fixed; + bottom: 20px; + right: 20px; + z-index: 999999; + width: 48px; + height: 48px; + border-radius: 50%; + background: #2da44e; + color: #fff; + border: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0,0,0,0.25); + transition: transform 0.2s, opacity 0.2s, visibility 0.2s; +} +#ghchat-toggle:hover { + transform: scale(1.1); + background: #2c974b; +} +#ghchat-toggle.ghchat-hidden { + opacity: 0; + visibility: hidden; + transform: scale(0.8); +} + +#ghchat-frame { + position: fixed; + bottom: 20px; + right: 20px; + z-index: 999999; + width: 360px; + height: 500px; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 8px 32px rgba(0,0,0,0.3); + display: flex; + flex-direction: column; + transform: translateY(20px); + opacity: 0; + visibility: hidden; + transition: transform 0.25s ease, opacity 0.25s ease, visibility 0.25s; +} +#ghchat-frame.ghchat-open { + transform: translateY(0); + opacity: 1; + visibility: visible; +} + +#ghchat-header { + background: #2da44e; + color: #fff; + padding: 10px 16px; + font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + font-weight: 600; + display: flex; + justify-content: space-between; + align-items: center; + flex-shrink: 0; +} +#ghchat-header button { + background: none; + border: none; + color: #fff; + font-size: 20px; + cursor: pointer; + padding: 0 4px; + line-height: 1; + opacity: 0.8; +} +#ghchat-header button:hover { + opacity: 1; +} + +#ghchat-iframe { + flex: 1; + width: 100%; + height: 100%; + background: #fff; + border: none; +}