Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# GitHub Stories

View stories on your GitHub dashboard.
View stories on your GitHub dashboard and open a lightweight chat panel on any GitHub page.

No uploads required. Just [install](#how-to-install) and visit [github.com](https://github.com).

The chat button appears in the lower-right corner on `github.com/*` pages. Open it to write page-specific notes, then hide it again without leaving GitHub.

![GitHub Stories Demo](./github-stories.gif)

## How to Install
Expand Down
94 changes: 94 additions & 0 deletions content-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,100 @@ const UPDATE_PROGRESS_BAR_VALUE =
time / (AUTOMATIC_SCROLL_DELAY / PROGRESS_BAR_UPDATE_DELAY - 5);
let storyViewOpen = false;

initGithubChat();

function initGithubChat() {
if (window.top !== window || document.getElementById('github-chat-root')) {
return;
}

const chatRoot = document.createElement('div');
chatRoot.id = 'github-chat-root';
chatRoot.innerHTML = `
<button class="github-chat-toggle" type="button" aria-expanded="false" aria-controls="github-chat-panel">
Chat
</button>
<section id="github-chat-panel" class="github-chat-panel hidden" aria-label="GitHub chat">
<header class="github-chat-header">
<strong>GitHub Chat</strong>
<button class="github-chat-close" type="button" aria-label="Close GitHub chat">×</button>
</header>
<div class="github-chat-messages" role="log" aria-live="polite"></div>
<form class="github-chat-form">
<input class="github-chat-input" type="text" placeholder="Message about this GitHub page..." autocomplete="off" />
<button class="github-chat-send" type="submit">Send</button>
</form>
</section>
`;

document.documentElement.appendChild(chatRoot);

const toggle = chatRoot.querySelector('.github-chat-toggle');
const panel = chatRoot.querySelector('.github-chat-panel');
const close = chatRoot.querySelector('.github-chat-close');
const form = chatRoot.querySelector('.github-chat-form');
const input = chatRoot.querySelector('.github-chat-input');
const messages = chatRoot.querySelector('.github-chat-messages');

const pageKey = `github-chat:${location.pathname}`;
const savedMessages = loadChatMessages(pageKey);
renderChatMessages(messages, savedMessages);

toggle.addEventListener('click', () => {
const isHidden = panel.classList.toggle('hidden');
toggle.setAttribute('aria-expanded', String(!isHidden));
if (!isHidden) input.focus();
});

close.addEventListener('click', () => {
panel.classList.add('hidden');
toggle.setAttribute('aria-expanded', 'false');
toggle.focus();
});

form.addEventListener('submit', (event) => {
event.preventDefault();
const text = input.value.trim();
if (!text) return;

const nextMessages = [
...loadChatMessages(pageKey),
{ text, createdAt: new Date().toISOString() },
];
saveChatMessages(pageKey, nextMessages);
renderChatMessages(messages, nextMessages);
input.value = '';
});
}

function loadChatMessages(pageKey) {
try {
return JSON.parse(localStorage.getItem(pageKey) || '[]');
} catch (error) {
return [];
}
}

function saveChatMessages(pageKey, messages) {
localStorage.setItem(pageKey, JSON.stringify(messages.slice(-50)));
}

function renderChatMessages(container, messages) {
if (messages.length === 0) {
container.innerHTML = '<p class="github-chat-empty">No messages yet.</p>';
return;
}

container.innerHTML = '';
messages.forEach((message) => {
const item = document.createElement('div');
item.className = 'github-chat-message';
item.innerText = message.text;
container.appendChild(item);
});
container.scrollTop = container.scrollHeight;
}

function getActionFullText(element){
let fullText = '';

Expand Down
3 changes: 1 addition & 2 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
"content_scripts": [
{
"matches": [
"https://github.com/",
"https://github.com/orgs/*"
"https://github.com/*"
],
"js": [
"content-script.js"
Expand Down
98 changes: 98 additions & 0 deletions story-list.css
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,101 @@ img.user-story-img {
border-radius: 50%;
width: 56px;
}

#github-chat-root {
position: fixed;
right: 24px;
bottom: 24px;
z-index: 99999;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

.github-chat-toggle {
background: #2da44e;
border: 0;
border-radius: 999px;
box-shadow: 0 8px 24px rgba(27, 31, 36, 0.24);
color: #ffffff;
cursor: pointer;
font-weight: 600;
min-height: 44px;
padding: 0 18px;
}

.github-chat-panel {
background: #ffffff;
border: 1px solid #d0d7de;
border-radius: 8px;
bottom: 56px;
box-shadow: 0 16px 48px rgba(27, 31, 36, 0.2);
color: #24292f;
display: flex;
flex-direction: column;
height: min(440px, calc(100vh - 120px));
overflow: hidden;
position: absolute;
right: 0;
width: min(360px, calc(100vw - 32px));
}

.github-chat-header {
align-items: center;
border-bottom: 1px solid #d0d7de;
display: flex;
justify-content: space-between;
padding: 12px 14px;
}

.github-chat-close {
background: transparent;
border: 0;
color: #57606a;
cursor: pointer;
font-size: 22px;
line-height: 1;
}

.github-chat-messages {
flex: 1;
overflow-y: auto;
padding: 14px;
}

.github-chat-empty {
color: #57606a;
margin: 0;
}

.github-chat-message {
background: #f6f8fa;
border: 1px solid #d8dee4;
border-radius: 8px;
margin-bottom: 8px;
padding: 8px 10px;
white-space: pre-wrap;
}

.github-chat-form {
border-top: 1px solid #d0d7de;
display: flex;
gap: 8px;
padding: 10px;
}

.github-chat-input {
border: 1px solid #d0d7de;
border-radius: 6px;
flex: 1;
min-width: 0;
padding: 8px;
}

.github-chat-send {
background: #0969da;
border: 0;
border-radius: 6px;
color: #ffffff;
cursor: pointer;
font-weight: 600;
padding: 0 12px;
}