Browse Source

get rid of light theme

Nostr-Signature: 16cc720587afa7994fdf4d1951934298d731f79d8fe4a3c5d4b9143e3b41abfd 573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc 125b3afa090a8a2679d6e2614163c8c95a42ba6d3323e9682ce94ecff387da8d1abbfffcc61d59646c6925d8e845527570387b012c194deed032fa7d43bceac0
main
Silberengel 3 weeks ago
parent
commit
91f50e0eb9
  1. 1
      nostr/commit-signatures.jsonl
  2. 4
      src/app.html
  3. 23
      src/lib/components/NavBar.svelte
  4. 23
      src/lib/components/SettingsButton.svelte
  5. 24
      src/lib/components/SettingsModal.svelte
  6. 82
      src/lib/components/ThemeToggle.svelte
  7. 2
      src/lib/services/settings-store.ts
  8. 138
      src/lib/styles/repo.css
  9. 26
      src/routes/+layout.svelte
  10. 59
      src/routes/repos/[npub]/[repo]/+page.svelte
  11. 11
      src/routes/repos/[npub]/[repo]/components/TagsTab.svelte
  12. 21
      src/routes/settings/[[tab]]/+page.svelte

1
nostr/commit-signatures.jsonl

@ -72,3 +72,4 @@
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1771952814,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","more work on branches"]],"content":"Signed commit: more work on branches","id":"adaaea7f2065a00cfd04c9de9bf82b1b976ac3d20c32389a8bd8aa7ad0a95677","sig":"71ce678d0a0732beab1f49f8318cbfe3d8b33d45eacf13392fdb9553e8b1f4732c28d8ffc33b50c9736a8324cf7604c223bb71ff4cfd32f41d7f3e81e1591fcc"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1771952814,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","more work on branches"]],"content":"Signed commit: more work on branches","id":"adaaea7f2065a00cfd04c9de9bf82b1b976ac3d20c32389a8bd8aa7ad0a95677","sig":"71ce678d0a0732beab1f49f8318cbfe3d8b33d45eacf13392fdb9553e8b1f4732c28d8ffc33b50c9736a8324cf7604c223bb71ff4cfd32f41d7f3e81e1591fcc"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1771956701,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","implemented releases and code serach\nadd contributors to private repos\napply/merge buttons for patches and PRs\nhighlgihts and comments on patches and prs\nadded tagged downloads"]],"content":"Signed commit: implemented releases and code serach\nadd contributors to private repos\napply/merge buttons for patches and PRs\nhighlgihts and comments on patches and prs\nadded tagged downloads","id":"e822be2b0fbf3285bbedf9d8f9d1692b5503080af17a4d28941a1dc81c96187c","sig":"70c8b6e499551ce43478116cf694992102a29572d5380cbe3b070a3026bc2c9e35177587712c7414f25d1ca50038c9614479f7758bbdc48f69cc44cd52bf4842"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1771956701,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","implemented releases and code serach\nadd contributors to private repos\napply/merge buttons for patches and PRs\nhighlgihts and comments on patches and prs\nadded tagged downloads"]],"content":"Signed commit: implemented releases and code serach\nadd contributors to private repos\napply/merge buttons for patches and PRs\nhighlgihts and comments on patches and prs\nadded tagged downloads","id":"e822be2b0fbf3285bbedf9d8f9d1692b5503080af17a4d28941a1dc81c96187c","sig":"70c8b6e499551ce43478116cf694992102a29572d5380cbe3b070a3026bc2c9e35177587712c7414f25d1ca50038c9614479f7758bbdc48f69cc44cd52bf4842"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1771958124,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fix crash on download"]],"content":"Signed commit: fix crash on download","id":"3fdcc681cdda4b523f9c3752309b8cf740b58178ca02dcff4ef97ec714bf394c","sig":"e405612a5aafeef66818f0a3c683e322f862d1fc3c662c32f618f516fd8c11ece5f4539b94893583301d31fd2ecd3de3b6d7a953505e2696915afe10710a16d7"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1771958124,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fix crash on download"]],"content":"Signed commit: fix crash on download","id":"3fdcc681cdda4b523f9c3752309b8cf740b58178ca02dcff4ef97ec714bf394c","sig":"e405612a5aafeef66818f0a3c683e322f862d1fc3c662c32f618f516fd8c11ece5f4539b94893583301d31fd2ecd3de3b6d7a953505e2696915afe10710a16d7"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1771964922,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fix page crash on download"]],"content":"Signed commit: fix page crash on download","id":"eafa232557affbacb430b467507febc201f0a8f54f4b9ecf57e315c32e51a589","sig":"53c58aabe0bfad6e432a8bb980c2046fc14bc8163825fde2ac766a449ce4418adb1049ac732c7fc7ecc7ad050539fb68c023d54f2b6c390e478616b5c0b91a31"}

4
src/app.html

@ -10,9 +10,7 @@
// Use localStorage as quick fallback, layout will load proper theme from IndexedDB // Use localStorage as quick fallback, layout will load proper theme from IndexedDB
(function() { (function() {
const savedTheme = localStorage.getItem('theme'); const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'gitrepublic-light') { if (savedTheme === 'gitrepublic-black') {
document.documentElement.setAttribute('data-theme', 'light');
} else if (savedTheme === 'gitrepublic-black') {
document.documentElement.setAttribute('data-theme', 'black'); document.documentElement.setAttribute('data-theme', 'black');
} else { } else {
// Default to gitrepublic-dark (purple) // Default to gitrepublic-dark (purple)

23
src/lib/components/NavBar.svelte

@ -491,35 +491,16 @@
width: 20px; width: 20px;
height: 20px; height: 20px;
display: block; display: block;
filter: brightness(0) saturate(100%) invert(1) !important; /* Default white for dark themes */ /* White icon for both dark themes */
opacity: 1 !important; filter: brightness(0) saturate(100%) invert(1) !important;
}
/* Light theme: black icon */
:global([data-theme="light"]) .hamburger-icon {
filter: brightness(0) saturate(100%) !important; /* Black in light theme */
opacity: 1 !important;
}
/* Dark themes: white icon */
:global([data-theme="dark"]) .hamburger-icon,
:global([data-theme="black"]) .hamburger-icon {
filter: brightness(0) saturate(100%) invert(1) !important; /* White in dark themes */
opacity: 1 !important; opacity: 1 !important;
} }
/* Hover: white for visibility */
.mobile-menu-toggle:hover .hamburger-icon { .mobile-menu-toggle:hover .hamburger-icon {
filter: brightness(0) saturate(100%) invert(1) !important; filter: brightness(0) saturate(100%) invert(1) !important;
opacity: 1 !important; opacity: 1 !important;
} }
/* Light theme hover: keep black */
:global([data-theme="light"]) .mobile-menu-toggle:hover .hamburger-icon {
filter: brightness(0) saturate(100%) !important;
opacity: 1 !important;
}
/* Mobile responsive styles */ /* Mobile responsive styles */
@media (max-width: 768px) { @media (max-width: 768px) {
.header-container { .header-container {

23
src/lib/components/SettingsButton.svelte

@ -52,32 +52,13 @@
width: 16px; width: 16px;
height: 16px; height: 16px;
display: block; display: block;
filter: brightness(0) saturate(100%) invert(1) !important; /* Default white for dark themes */ /* White icon for both dark themes */
opacity: 1 !important; filter: brightness(0) saturate(100%) invert(1) !important;
}
/* Light theme: black icon */
:global([data-theme="light"]) .settings-icon {
filter: brightness(0) saturate(100%) !important; /* Black in light theme */
opacity: 1 !important;
}
/* Dark themes: white icon */
:global([data-theme="dark"]) .settings-icon,
:global([data-theme="black"]) .settings-icon {
filter: brightness(0) saturate(100%) invert(1) !important; /* White in dark themes */
opacity: 1 !important; opacity: 1 !important;
} }
/* Hover: white for visibility */
.settings-button:hover .settings-icon { .settings-button:hover .settings-icon {
filter: brightness(0) saturate(100%) invert(1) !important; filter: brightness(0) saturate(100%) invert(1) !important;
opacity: 1 !important; opacity: 1 !important;
} }
/* Light theme hover: keep black */
:global([data-theme="light"]) .settings-button:hover .settings-icon {
filter: brightness(0) saturate(100%) !important;
opacity: 1 !important;
}
</style> </style>

24
src/lib/components/SettingsModal.svelte

@ -18,7 +18,7 @@
let autoSave = $state(false); let autoSave = $state(false);
let userName = $state(''); let userName = $state('');
let userEmail = $state(''); let userEmail = $state('');
let theme = $state<'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black'>('gitrepublic-dark'); let theme = $state<'gitrepublic-dark' | 'gitrepublic-black'>('gitrepublic-dark');
let defaultBranch = $state('master'); let defaultBranch = $state('master');
let loading = $state(false); let loading = $state(false);
let saving = $state(false); let saving = $state(false);
@ -121,23 +121,21 @@
} }
} }
function applyTheme(newTheme: 'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black') { function applyTheme(newTheme: 'gitrepublic-dark' | 'gitrepublic-black') {
// Remove all theme attributes first // Remove all theme attributes first
document.documentElement.removeAttribute('data-theme'); document.documentElement.removeAttribute('data-theme');
document.documentElement.removeAttribute('data-theme-light'); document.documentElement.removeAttribute('data-theme-light');
document.documentElement.removeAttribute('data-theme-black'); document.documentElement.removeAttribute('data-theme-black');
// Apply the selected theme // Apply the selected theme
if (newTheme === 'gitrepublic-light') { if (newTheme === 'gitrepublic-dark') {
document.documentElement.setAttribute('data-theme', 'light');
} else if (newTheme === 'gitrepublic-dark') {
document.documentElement.setAttribute('data-theme', 'dark'); document.documentElement.setAttribute('data-theme', 'dark');
} else if (newTheme === 'gitrepublic-black') { } else if (newTheme === 'gitrepublic-black') {
document.documentElement.setAttribute('data-theme', 'black'); document.documentElement.setAttribute('data-theme', 'black');
} }
} }
function handleThemeChange(newTheme: 'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black') { function handleThemeChange(newTheme: 'gitrepublic-dark' | 'gitrepublic-black') {
theme = newTheme; theme = newTheme;
// Preview theme change immediately (don't save yet) // Preview theme change immediately (don't save yet)
applyTheme(newTheme); applyTheme(newTheme);
@ -232,14 +230,6 @@
<span class="label-text">Theme</span> <span class="label-text">Theme</span>
</div> </div>
<div class="theme-options"> <div class="theme-options">
<button
class="theme-option"
class:active={theme === 'gitrepublic-light'}
onclick={() => handleThemeChange('gitrepublic-light')}
>
<img src="/icons/sun.svg" alt="Light theme" class="theme-icon" />
<span>Light</span>
</button>
<button <button
class="theme-option" class="theme-option"
class:active={theme === 'gitrepublic-dark'} class:active={theme === 'gitrepublic-dark'}
@ -438,9 +428,6 @@
filter: brightness(0) saturate(100%) invert(1); filter: brightness(0) saturate(100%) invert(1);
} }
:global([data-theme="light"]) .close-icon {
filter: brightness(0) saturate(100%);
}
.tabs { .tabs {
display: flex; display: flex;
@ -603,9 +590,6 @@
filter: brightness(0) saturate(100%) invert(1); filter: brightness(0) saturate(100%) invert(1);
} }
:global([data-theme="light"]) .theme-icon {
filter: brightness(0) saturate(100%);
}
.loading { .loading {
padding: 2rem; padding: 2rem;

82
src/lib/components/ThemeToggle.svelte

@ -4,19 +4,17 @@
// Get theme and toggle function from layout context // Get theme and toggle function from layout context
const themeContext = getContext<{ const themeContext = getContext<{
theme: { value: 'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black' }; theme: { value: 'gitrepublic-dark' | 'gitrepublic-black' };
toggleTheme: () => void; toggleTheme: () => void;
}>('theme'); }>('theme');
let currentTheme = $state<'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black'>('gitrepublic-dark'); let currentTheme = $state<'gitrepublic-dark' | 'gitrepublic-black'>('gitrepublic-dark');
let dropdownOpen = $state(false); let dropdownOpen = $state(false);
let buttonElement: HTMLButtonElement | null = $state(null); let buttonElement: HTMLButtonElement | null = $state(null);
function updateTheme() { function updateTheme() {
const themeAttr = document.documentElement.getAttribute('data-theme'); const themeAttr = document.documentElement.getAttribute('data-theme');
if (themeAttr === 'light') { if (themeAttr === 'black') {
currentTheme = 'gitrepublic-light';
} else if (themeAttr === 'black') {
currentTheme = 'gitrepublic-black'; currentTheme = 'gitrepublic-black';
} else { } else {
currentTheme = 'gitrepublic-dark'; // default to dark/purple currentTheme = 'gitrepublic-dark'; // default to dark/purple
@ -57,12 +55,9 @@
dropdownOpen = !dropdownOpen; dropdownOpen = !dropdownOpen;
} }
function selectTheme(theme: 'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black') { function selectTheme(theme: 'gitrepublic-dark' | 'gitrepublic-black') {
// Set theme directly // Set theme directly
if (theme === 'gitrepublic-light') { if (theme === 'gitrepublic-black') {
document.documentElement.setAttribute('data-theme', 'light');
localStorage.setItem('theme', 'gitrepublic-light');
} else if (theme === 'gitrepublic-black') {
document.documentElement.setAttribute('data-theme', 'black'); document.documentElement.setAttribute('data-theme', 'black');
localStorage.setItem('theme', 'gitrepublic-black'); localStorage.setItem('theme', 'gitrepublic-black');
} else { } else {
@ -73,8 +68,7 @@
dropdownOpen = false; dropdownOpen = false;
} }
function getThemeName(theme: 'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black'): string { function getThemeName(theme: 'gitrepublic-dark' | 'gitrepublic-black'): string {
if (theme === 'gitrepublic-light') return 'Light';
if (theme === 'gitrepublic-black') return 'Black'; if (theme === 'gitrepublic-black') return 'Black';
return 'Purple'; return 'Purple';
} }
@ -92,14 +86,6 @@
{#if dropdownOpen} {#if dropdownOpen}
<div class="theme-dropdown"> <div class="theme-dropdown">
<button
class="theme-option"
class:active={currentTheme === 'gitrepublic-light'}
onclick={() => selectTheme('gitrepublic-light')}
>
<img src="/icons/sun.svg" alt="Light theme" class="theme-icon-option" />
<span class="theme-name">Light</span>
</button>
<button <button
class="theme-option" class="theme-option"
class:active={currentTheme === 'gitrepublic-dark'} class:active={currentTheme === 'gitrepublic-dark'}
@ -157,35 +143,11 @@
width: 16px; width: 16px;
height: 16px; height: 16px;
display: block; display: block;
filter: brightness(0) saturate(100%) invert(1) !important; /* Default white for dark themes */ /* White icon for both dark themes */
opacity: 1 !important;
}
/* Light theme: black icon */
:global([data-theme="light"]) .theme-toggle .theme-icon {
filter: brightness(0) saturate(100%) !important; /* Black in light theme */
opacity: 1 !important;
}
/* Dark themes: white icon */
:global([data-theme="dark"]) .theme-toggle .theme-icon,
:global([data-theme="black"]) .theme-toggle .theme-icon {
filter: brightness(0) saturate(100%) invert(1) !important; /* White in dark themes */
opacity: 1 !important;
}
/* Hover: white for visibility */
.theme-toggle:hover .theme-icon {
filter: brightness(0) saturate(100%) invert(1) !important; filter: brightness(0) saturate(100%) invert(1) !important;
opacity: 1 !important; opacity: 1 !important;
} }
/* Light theme hover: keep black */
:global([data-theme="light"]) .theme-toggle:hover .theme-icon {
filter: brightness(0) saturate(100%) !important;
opacity: 1 !important;
}
.theme-dropdown { .theme-dropdown {
position: absolute; position: absolute;
top: calc(100% + 0.5rem); top: calc(100% + 0.5rem);
@ -241,20 +203,8 @@
height: 18px; height: 18px;
display: inline-block; display: inline-block;
flex-shrink: 0; flex-shrink: 0;
filter: brightness(0) saturate(100%) invert(1) !important; /* Default white for dark themes */ /* White icons for both dark themes */
opacity: 1 !important; filter: brightness(0) saturate(100%) invert(1) !important;
}
/* Light theme: black icons */
:global([data-theme="light"]) .theme-option .theme-icon-option {
filter: brightness(0) saturate(100%) !important; /* Black in light theme */
opacity: 1 !important;
}
/* Dark themes: white icons */
:global([data-theme="dark"]) .theme-option .theme-icon-option,
:global([data-theme="black"]) .theme-option .theme-icon-option {
filter: brightness(0) saturate(100%) invert(1) !important; /* White in dark themes */
opacity: 1 !important; opacity: 1 !important;
} }
@ -262,20 +212,6 @@
transform: scale(1.1); transform: scale(1.1);
} }
/* Hover and active states */
.theme-option:hover .theme-icon-option,
.theme-option.active .theme-icon-option {
filter: brightness(0) saturate(100%) invert(1) !important; /* White for visibility */
opacity: 1 !important;
}
/* Light theme hover/active: keep black */
:global([data-theme="light"]) .theme-option:hover .theme-icon-option,
:global([data-theme="light"]) .theme-option.active .theme-icon-option {
filter: brightness(0) saturate(100%) !important; /* Black in light theme */
opacity: 1 !important;
}
.theme-name { .theme-name {
flex: 1; flex: 1;
} }

2
src/lib/services/settings-store.ts

@ -25,7 +25,7 @@ interface Settings {
autoSave: boolean; autoSave: boolean;
userName: string; userName: string;
userEmail: string; userEmail: string;
theme: 'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black'; theme: 'gitrepublic-dark' | 'gitrepublic-black';
defaultBranch: string; defaultBranch: string;
messagingPreferences?: MessagingPreferences; messagingPreferences?: MessagingPreferences;
} }

138
src/lib/styles/repo.css

@ -82,6 +82,10 @@
height: 20px; height: 20px;
flex-shrink: 0; flex-shrink: 0;
color: var(--text-secondary); color: var(--text-secondary);
/* White icon for both dark themes */
filter: brightness(0) saturate(100%) invert(1);
opacity: 0.8;
transition: opacity 0.2s ease, filter 0.2s ease;
} }
.read-only-banner .banner-content span { .read-only-banner .banner-content span {
@ -247,6 +251,15 @@
.file-item .file-icon { .file-item .file-icon {
opacity: 0.8; opacity: 0.8;
flex-shrink: 0; flex-shrink: 0;
/* Theme-aware file icon */
filter: brightness(0) saturate(100%);
transition: opacity 0.2s ease, filter 0.2s ease;
}
/* File icons - white for both dark themes */
.file-item .file-icon {
filter: brightness(0) saturate(100%) invert(1);
opacity: 0.8;
} }
.file-button { .file-button {
@ -680,39 +693,20 @@
cursor: not-allowed; cursor: not-allowed;
} }
/* File action button icons - white for both dark themes */
.file-action-button .icon-inline { .file-action-button .icon-inline {
width: 1rem; width: 1rem;
height: 1rem; height: 1rem;
filter: brightness(0) saturate(100%) invert(1) !important; /* Default white for dark themes */ filter: brightness(0) saturate(100%) invert(1) !important;
opacity: 1 !important; opacity: 1 !important;
transition: filter 0.3s ease, opacity 0.3s ease; transition: filter 0.3s ease, opacity 0.3s ease;
} }
/* Light theme: black icon */
:global([data-theme="light"]) .file-action-button .icon-inline {
filter: brightness(0) saturate(100%) !important; /* Black in light theme */
opacity: 1 !important;
}
/* Dark themes: white icon */
:global([data-theme="dark"]) .file-action-button .icon-inline,
:global([data-theme="black"]) .file-action-button .icon-inline {
filter: brightness(0) saturate(100%) invert(1) !important; /* White in dark themes */
opacity: 1 !important;
}
/* Hover: white for visibility */
.file-action-button:hover:not(:disabled) .icon-inline { .file-action-button:hover:not(:disabled) .icon-inline {
filter: brightness(0) saturate(100%) invert(1) !important; filter: brightness(0) saturate(100%) invert(1) !important;
opacity: 1 !important; opacity: 1 !important;
} }
/* Light theme hover: keep black */
:global([data-theme="light"]) .file-action-button:hover:not(:disabled) .icon-inline {
filter: brightness(0) saturate(100%) !important;
opacity: 1 !important;
}
/* File preview styling (same as readme-content.markdown) */ /* File preview styling (same as readme-content.markdown) */
.file-preview.markdown { .file-preview.markdown {
line-height: 1.6; line-height: 1.6;
@ -1026,6 +1020,16 @@
.mobile-toggle-button .icon-inline { .mobile-toggle-button .icon-inline {
width: 18px; width: 18px;
height: 18px; height: 18px;
/* Icons should be black in light mode (on light background) */
filter: brightness(0) saturate(100%) !important;
opacity: 1 !important;
}
/* White icons for both dark themes */
html[data-theme="dark"] .mobile-toggle-button .icon-inline,
html[data-theme="black"] .mobile-toggle-button .icon-inline {
filter: brightness(0) saturate(100%) invert(1) !important; /* White in dark themes */
opacity: 1 !important;
} }
.mobile-toggle-left { .mobile-toggle-left {
@ -1153,8 +1157,17 @@
.clone-toggle-icon { .clone-toggle-icon {
width: 16px; width: 16px;
height: 16px; height: 16px;
transition: transform 0.2s; transition: transform 0.2s, opacity 0.2s ease, filter 0.2s ease;
flex-shrink: 0; flex-shrink: 0;
/* Theme-aware icon styling */
filter: brightness(0) saturate(100%);
opacity: 0.8;
}
/* Clone toggle icon - white for both dark themes */
.clone-toggle-icon {
filter: brightness(0) saturate(100%) invert(1);
opacity: 0.8;
} }
.clone-toggle-icon.expanded { .clone-toggle-icon.expanded {
@ -1205,8 +1218,13 @@
.copy-clone-url-button .icon-inline { .copy-clone-url-button .icon-inline {
width: 16px; width: 16px;
height: 16px; height: 16px;
/* Icon filter pattern like settings button - white for dark button background */
filter: brightness(0) saturate(100%) invert(1) !important;
opacity: 1 !important;
} }
/* Copy clone URL button icon - white for both dark themes */
.clone-url-list.collapsed { .clone-url-list.collapsed {
max-height: 0; max-height: 0;
opacity: 0; opacity: 0;
@ -1260,8 +1278,12 @@
transition: all 0.2s ease; transition: all 0.2s ease;
display: inline-block; display: inline-block;
font-weight: 500; font-weight: 500;
/* Ensure text is legible in all themes */
min-height: 2rem;
line-height: 1.5;
} }
/* Clone more button - same styling for both dark themes */
.clone-more:hover { .clone-more:hover {
background: var(--button-secondary-hover, var(--bg-tertiary)); background: var(--button-secondary-hover, var(--bg-tertiary));
border-color: var(--accent, #007bff); border-color: var(--accent, #007bff);
@ -1285,17 +1307,38 @@ span.clone-more {
margin-top: 0.25rem; margin-top: 0.25rem;
} }
/* Icon inline - white for both dark themes */
.icon-inline { .icon-inline {
width: 1em; width: 1em;
height: 1em; height: 1em;
vertical-align: middle; vertical-align: middle;
display: inline-block; display: inline-block;
filter: brightness(0) saturate(100%) invert(1) !important;
opacity: 0.8 !important;
transition: opacity 0.2s ease, filter 0.2s ease;
}
/* Success/error icon colors using CSS filters for theme compatibility */
.icon-inline.icon-success {
/* Green filter that works in all themes */
filter: brightness(0) saturate(100%) invert(64%) sepia(61%) saturate(1824%) hue-rotate(91deg) brightness(95%) contrast(87%);
opacity: 1;
} }
.icon-inline.icon-error {
/* Red filter that works in all themes */
filter: brightness(0) saturate(100%) invert(27%) sepia(95%) saturate(7471%) hue-rotate(348deg) brightness(99%) contrast(92%);
opacity: 1;
}
/* Icon small - white for both dark themes */
.icon-small { .icon-small {
width: 16px; width: 16px;
height: 16px; height: 16px;
vertical-align: middle; vertical-align: middle;
filter: brightness(0) saturate(100%) invert(1);
opacity: 0.8;
transition: opacity 0.2s ease, filter 0.2s ease;
} }
.back-button { .back-button {
@ -1339,6 +1382,17 @@ span.clone-more {
.create-tag-button .icon { .create-tag-button .icon {
width: 18px; width: 18px;
height: 18px; height: 18px;
/* Theme-aware icon styling */
filter: brightness(0) saturate(100%);
opacity: 0.9;
transition: opacity 0.2s ease, filter 0.2s ease;
}
/* Create button icons - white for both dark themes */
.create-file-button .icon,
.create-tag-button .icon {
filter: brightness(0) saturate(100%) invert(1);
opacity: 0.9;
} }
.delete-file-button { .delete-file-button {
@ -1755,6 +1809,20 @@ span.clone-more {
.create-reply-button .icon { .create-reply-button .icon {
width: 18px; width: 18px;
height: 18px; height: 18px;
/* Theme-aware icon styling */
filter: brightness(0) saturate(100%);
opacity: 0.9;
transition: opacity 0.2s ease, filter 0.2s ease;
}
/* Create button icons - white for both dark themes */
.create-issue-button .icon,
.create-pr-button .icon,
.create-patch-button .icon,
.create-discussion-button .icon,
.create-reply-button .icon {
filter: brightness(0) saturate(100%) invert(1);
opacity: 0.9;
} }
.refresh-button { .refresh-button {
@ -1799,11 +1867,11 @@ span.clone-more {
} }
.reachability-badge.reachable { .reachability-badge.reachable {
color: #22c55e; /* green-500 */ color: var(--success-text, #22c55e);
} }
.reachability-badge.unreachable { .reachability-badge.unreachable {
color: #ef4444; /* red-500 */ color: var(--error-text, #ef4444);
} }
.reachability-badge.loading { .reachability-badge.loading {
@ -1840,6 +1908,20 @@ span.clone-more {
height: 16px; height: 16px;
flex-shrink: 0; flex-shrink: 0;
color: var(--text-primary); color: var(--text-primary);
/* Theme-aware icon styling */
filter: brightness(0) saturate(100%);
opacity: 0.8;
transition: opacity 0.2s ease, filter 0.2s ease;
}
/* Reachability refresh icon - white for both dark themes */
.reachability-refresh-button .refresh-icon {
filter: brightness(0) saturate(100%) invert(1);
opacity: 0.8;
}
.reachability-refresh-button:hover:not(:disabled) .refresh-icon {
opacity: 1;
} }
.server-type-badge { .server-type-badge {
@ -1855,13 +1937,13 @@ span.clone-more {
} }
.server-type-badge.grasp-badge { .server-type-badge.grasp-badge {
background: #8b5cf6; /* purple-500 */ background: var(--accent, #8b5cf6);
color: white; color: var(--accent-text, #ffffff);
} }
.server-type-badge.git-badge { .server-type-badge.git-badge {
background: #6b7280; /* gray-500 */ background: var(--bg-tertiary, #6b7280);
color: white; color: var(--text-on-accent, #ffffff);
} }
.empty { .empty {

26
src/routes/+layout.svelte

@ -24,7 +24,7 @@
let handleThemeChanged: ((event: Event) => void) | null = null; let handleThemeChanged: ((event: Event) => void) | null = null;
// Theme management - default to gitrepublic-dark (purple) // Theme management - default to gitrepublic-dark (purple)
let theme = $state<'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black'>('gitrepublic-dark'); let theme = $state<'gitrepublic-dark' | 'gitrepublic-black'>('gitrepublic-dark');
// User level checking state // User level checking state
let checkingUserLevel = $state(false); let checkingUserLevel = $state(false);
@ -66,8 +66,8 @@
console.warn('Failed to load theme from settings, using default:', err); console.warn('Failed to load theme from settings, using default:', err);
// Fallback to localStorage for migration // Fallback to localStorage for migration
try { try {
const savedTheme = localStorage.getItem('theme') as 'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black' | null; const savedTheme = localStorage.getItem('theme') as 'gitrepublic-dark' | 'gitrepublic-black' | null;
if (savedTheme === 'gitrepublic-light' || savedTheme === 'gitrepublic-dark' || savedTheme === 'gitrepublic-black') { if (savedTheme === 'gitrepublic-dark' || savedTheme === 'gitrepublic-black') {
if (isMounted) { if (isMounted) {
theme = savedTheme; theme = savedTheme;
themeLoaded = true; themeLoaded = true;
@ -76,10 +76,16 @@
settingsStore.setSetting('theme', theme).catch(console.error); settingsStore.setSetting('theme', theme).catch(console.error);
} }
} else if (isMounted) { } else if (isMounted) {
theme = 'gitrepublic-dark'; // Migrate old light theme to dark
if (savedTheme === 'gitrepublic-light') {
theme = 'gitrepublic-dark';
} else {
theme = 'gitrepublic-dark';
}
themeLoaded = true; themeLoaded = true;
applyTheme(theme); applyTheme(theme);
localStorage.setItem('theme', theme); localStorage.setItem('theme', theme);
settingsStore.setSetting('theme', theme).catch(console.error);
} }
} catch { } catch {
// Ignore localStorage errors // Ignore localStorage errors
@ -148,7 +154,7 @@
handleThemeChanged = (event: Event) => { handleThemeChanged = (event: Event) => {
if (!isMounted) return; if (!isMounted) return;
try { try {
const customEvent = event as CustomEvent<{ theme: 'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black' }>; const customEvent = event as CustomEvent<{ theme: 'gitrepublic-dark' | 'gitrepublic-black' }>;
if (customEvent.detail?.theme && isMounted) { if (customEvent.detail?.theme && isMounted) {
theme = customEvent.detail.theme; theme = customEvent.detail.theme;
// Sync to localStorage for app.html flash prevention // Sync to localStorage for app.html flash prevention
@ -323,7 +329,7 @@
pendingTransfers = pendingTransfers.filter(t => t.eventId !== eventId); pendingTransfers = pendingTransfers.filter(t => t.eventId !== eventId);
} }
function applyTheme(newTheme?: 'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black') { function applyTheme(newTheme?: 'gitrepublic-dark' | 'gitrepublic-black') {
const themeToApply = newTheme || theme; const themeToApply = newTheme || theme;
// Only run client-side // Only run client-side
if (typeof window === 'undefined') return; if (typeof window === 'undefined') return;
@ -334,9 +340,7 @@
document.documentElement.removeAttribute('data-theme-black'); document.documentElement.removeAttribute('data-theme-black');
// Apply the selected theme // Apply the selected theme
if (themeToApply === 'gitrepublic-light') { if (themeToApply === 'gitrepublic-dark') {
document.documentElement.setAttribute('data-theme', 'light');
} else if (themeToApply === 'gitrepublic-dark') {
document.documentElement.setAttribute('data-theme', 'dark'); document.documentElement.setAttribute('data-theme', 'dark');
} else if (themeToApply === 'gitrepublic-black') { } else if (themeToApply === 'gitrepublic-black') {
document.documentElement.setAttribute('data-theme', 'black'); document.documentElement.setAttribute('data-theme', 'black');
@ -357,10 +361,8 @@
}); });
function toggleTheme() { function toggleTheme() {
// Cycle through themes: gitrepublic-dark -> gitrepublic-light -> gitrepublic-black -> gitrepublic-dark // Cycle between dark and black themes
if (theme === 'gitrepublic-dark') { if (theme === 'gitrepublic-dark') {
theme = 'gitrepublic-light';
} else if (theme === 'gitrepublic-light') {
theme = 'gitrepublic-black'; theme = 'gitrepublic-black';
} else { } else {
theme = 'gitrepublic-dark'; theme = 'gitrepublic-dark';

59
src/routes/repos/[npub]/[repo]/+page.svelte

@ -5290,9 +5290,9 @@
: (reachability.error || 'Unreachable')} : (reachability.error || 'Unreachable')}
> >
{#if reachability.reachable} {#if reachability.reachable}
<img src="/icons/check-circle.svg" alt="Reachable" class="icon-inline" style="color: green;" /> <img src="/icons/check-circle.svg" alt="Reachable" class="icon-inline icon-success" />
{:else} {:else}
<img src="/icons/x-circle.svg" alt="Unreachable" class="icon-inline" style="color: red;" /> <img src="/icons/x-circle.svg" alt="Unreachable" class="icon-inline icon-error" />
{/if} {/if}
</span> </span>
{#if reachability.serverType === 'grasp'} {#if reachability.serverType === 'grasp'}
@ -7202,58 +7202,5 @@
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
} }
/* Tag date styling */ /* Tag-related styles have been moved to TagsTab.svelte component */
.tag-date {
font-size: 0.85rem;
color: var(--text-muted);
margin-top: 0.25rem;
}
/* Tag detail meta styling */
.tag-detail-meta {
display: flex;
flex-wrap: wrap;
gap: 1rem;
align-items: center;
margin-top: 0.5rem;
}
.tag-detail-meta .tag-date {
font-size: 0.9rem;
color: var(--text-muted);
}
/* Download tag button styling */
.download-tag-button {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
background: var(--button-primary);
color: var(--accent-text, #ffffff);
border: none;
border-radius: 4px;
text-decoration: none;
font-size: 0.9rem;
font-family: 'IBM Plex Serif', serif;
transition: background 0.2s ease;
cursor: pointer;
}
.download-tag-button:hover {
background: var(--button-primary-hover);
}
.download-tag-button .icon-inline {
width: 16px;
height: 16px;
}
/* Tag has release icon styling */
.tag-has-release-icon {
width: 16px;
height: 16px;
vertical-align: middle;
opacity: 0.8;
}
</style> </style>

11
src/routes/repos/[npub]/[repo]/components/TagsTab.svelte

@ -268,6 +268,7 @@
flex: 1; flex: 1;
margin: 0; margin: 0;
font-size: 1.2rem; font-size: 1.2rem;
color: var(--text-primary); /* Ensure proper contrast in dark themes */
} }
.create-tag-button { .create-tag-button {
@ -298,6 +299,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.25rem; gap: 0.25rem;
color: var(--text-primary); /* Ensure proper contrast in dark themes */
} }
.tag-item-button:hover { .tag-item-button:hover {
@ -311,6 +313,7 @@
.tag-name { .tag-name {
font-weight: 500; font-weight: 500;
color: var(--text-primary); /* Ensure proper contrast in dark themes */
} }
.tag-hash { .tag-hash {
@ -336,6 +339,7 @@
.tag-detail-header h3 { .tag-detail-header h3 {
margin: 0 0 0.5rem 0; margin: 0 0 0.5rem 0;
color: var(--text-primary); /* Ensure proper contrast in dark themes */
} }
.tag-detail-meta { .tag-detail-meta {
@ -344,6 +348,11 @@
gap: 1rem; gap: 1rem;
align-items: center; align-items: center;
margin-top: 0.5rem; margin-top: 0.5rem;
color: var(--text-primary); /* Ensure proper contrast in dark themes */
}
.tag-detail-meta span {
color: var(--text-secondary); /* Secondary text for meta info */
} }
.tag-message { .tag-message {
@ -408,6 +417,8 @@
height: 16px; height: 16px;
vertical-align: middle; vertical-align: middle;
opacity: 0.8; opacity: 0.8;
/* White icon for both dark themes */
filter: brightness(0) saturate(100%) invert(1);
} }
.error-message { .error-message {

21
src/routes/settings/[[tab]]/+page.svelte

@ -26,7 +26,7 @@
let autoSave = $state(false); let autoSave = $state(false);
let userName = $state(''); let userName = $state('');
let userEmail = $state(''); let userEmail = $state('');
let theme = $state<'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black'>('gitrepublic-dark'); let theme = $state<'gitrepublic-dark' | 'gitrepublic-black'>('gitrepublic-dark');
let defaultBranch = $state('master'); let defaultBranch = $state('master');
let loading = $state(false); let loading = $state(false);
let saving = $state(false); let saving = $state(false);
@ -139,23 +139,21 @@
} }
} }
function applyTheme(newTheme: 'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black') { function applyTheme(newTheme: 'gitrepublic-dark' | 'gitrepublic-black') {
// Remove all theme attributes first // Remove all theme attributes first
document.documentElement.removeAttribute('data-theme'); document.documentElement.removeAttribute('data-theme');
document.documentElement.removeAttribute('data-theme-light'); document.documentElement.removeAttribute('data-theme-light');
document.documentElement.removeAttribute('data-theme-black'); document.documentElement.removeAttribute('data-theme-black');
// Apply the selected theme // Apply the selected theme
if (newTheme === 'gitrepublic-light') { if (newTheme === 'gitrepublic-dark') {
document.documentElement.setAttribute('data-theme', 'light');
} else if (newTheme === 'gitrepublic-dark') {
document.documentElement.setAttribute('data-theme', 'dark'); document.documentElement.setAttribute('data-theme', 'dark');
} else if (newTheme === 'gitrepublic-black') { } else if (newTheme === 'gitrepublic-black') {
document.documentElement.setAttribute('data-theme', 'black'); document.documentElement.setAttribute('data-theme', 'black');
} }
} }
function handleThemeChange(newTheme: 'gitrepublic-light' | 'gitrepublic-dark' | 'gitrepublic-black') { function handleThemeChange(newTheme: 'gitrepublic-dark' | 'gitrepublic-black') {
theme = newTheme; theme = newTheme;
// Preview theme change immediately (don't save yet) // Preview theme change immediately (don't save yet)
applyTheme(newTheme); applyTheme(newTheme);
@ -250,14 +248,6 @@
<span class="label-text">Theme</span> <span class="label-text">Theme</span>
</div> </div>
<div class="theme-options"> <div class="theme-options">
<button
class="theme-option"
class:active={theme === 'gitrepublic-light'}
onclick={() => handleThemeChange('gitrepublic-light')}
>
<img src="/icons/sun.svg" alt="Light theme" class="theme-icon" />
<span>Light</span>
</button>
<button <button
class="theme-option" class="theme-option"
class:active={theme === 'gitrepublic-dark'} class:active={theme === 'gitrepublic-dark'}
@ -950,9 +940,6 @@
filter: brightness(0) saturate(100%) invert(1); filter: brightness(0) saturate(100%) invert(1);
} }
:global([data-theme="light"]) .theme-icon {
filter: brightness(0) saturate(100%);
}
.loading { .loading {
padding: 2rem; padding: 2rem;

Loading…
Cancel
Save