style: fix lint warnings and a11y issues
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 52s
CI / Lint & Test (pull_request) Successful in 14m40s
CI / Build Linux (pull_request) Successful in 19m17s
CI / Build Windows (cross-compile) (pull_request) Successful in 28m51s

- Add proper for/id associations for color picker labels (ConfigSidebar)
- Add tabindex and svelte-ignore for dialog overlays (GitPanel)
- Add standard mask/line-clamp CSS properties for compatibility
- Remove unused .stat-highlight CSS selector (StatsDisplay)
- Fix SvelteSet reactivity by using .clear() instead of reassignment
- Make updateNotification properly reactive with $state
This commit is contained in:
2026-01-25 21:34:28 -08:00
committed by Naomi Carrigan
parent c45414b0aa
commit edcca9179a
12 changed files with 292 additions and 75 deletions
+3
View File
@@ -249,6 +249,9 @@
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
opacity: 0;
+48 -18
View File
@@ -458,11 +458,12 @@
<!-- Theme Selection -->
<div class="mb-4">
<label class="block text-sm text-[var(--text-secondary)] mb-2">Theme</label>
<div class="flex flex-wrap gap-2">
<span class="block text-sm text-[var(--text-secondary)] mb-2">Theme</span>
<div class="flex flex-wrap gap-2" role="group" aria-label="Theme selection">
<button
onclick={() => handleThemeChange("dark")}
class="flex-1 min-w-[70px] px-3 py-2 rounded-lg border transition-colors {config.theme === 'dark'
class="flex-1 min-w-[70px] px-3 py-2 rounded-lg border transition-colors {config.theme ===
'dark'
? 'bg-[var(--accent-primary)] border-[var(--accent-primary)] text-white'
: 'bg-[var(--bg-primary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--accent-primary)]'}"
>
@@ -470,7 +471,8 @@
</button>
<button
onclick={() => handleThemeChange("light")}
class="flex-1 min-w-[70px] px-3 py-2 rounded-lg border transition-colors {config.theme === 'light'
class="flex-1 min-w-[70px] px-3 py-2 rounded-lg border transition-colors {config.theme ===
'light'
? 'bg-[var(--accent-primary)] border-[var(--accent-primary)] text-white'
: 'bg-[var(--bg-primary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--accent-primary)]'}"
>
@@ -488,7 +490,8 @@
</button>
<button
onclick={() => handleThemeChange("custom")}
class="flex-1 min-w-[70px] px-3 py-2 rounded-lg border transition-colors {config.theme === 'custom'
class="flex-1 min-w-[70px] px-3 py-2 rounded-lg border transition-colors {config.theme ===
'custom'
? 'bg-[var(--accent-primary)] border-[var(--accent-primary)] text-white'
: 'bg-[var(--bg-primary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--accent-primary)]'}"
title="Create your own custom theme"
@@ -504,9 +507,12 @@
<h4 class="text-sm font-medium text-[var(--text-primary)] mb-3">Custom Theme Colors</h4>
<div class="grid grid-cols-2 gap-3">
<div class="color-input-group">
<label class="text-xs text-[var(--text-secondary)]">Background</label>
<label class="text-xs text-[var(--text-secondary)]" for="color-bg-primary"
>Background</label
>
<div class="flex gap-2 items-center">
<input
id="color-bg-primary"
type="color"
value={config.custom_theme_colors.bg_primary || defaultDarkColors.bg_primary}
oninput={(e) => handleCustomColorChange("bg_primary", e.currentTarget.value)}
@@ -518,9 +524,12 @@
</div>
</div>
<div class="color-input-group">
<label class="text-xs text-[var(--text-secondary)]">Secondary BG</label>
<label class="text-xs text-[var(--text-secondary)]" for="color-bg-secondary"
>Secondary BG</label
>
<div class="flex gap-2 items-center">
<input
id="color-bg-secondary"
type="color"
value={config.custom_theme_colors.bg_secondary || defaultDarkColors.bg_secondary}
oninput={(e) => handleCustomColorChange("bg_secondary", e.currentTarget.value)}
@@ -532,9 +541,12 @@
</div>
</div>
<div class="color-input-group">
<label class="text-xs text-[var(--text-secondary)]">Terminal BG</label>
<label class="text-xs text-[var(--text-secondary)]" for="color-bg-terminal"
>Terminal BG</label
>
<div class="flex gap-2 items-center">
<input
id="color-bg-terminal"
type="color"
value={config.custom_theme_colors.bg_terminal || defaultDarkColors.bg_terminal}
oninput={(e) => handleCustomColorChange("bg_terminal", e.currentTarget.value)}
@@ -546,9 +558,10 @@
</div>
</div>
<div class="color-input-group">
<label class="text-xs text-[var(--text-secondary)]">Border</label>
<label class="text-xs text-[var(--text-secondary)]" for="color-border">Border</label>
<div class="flex gap-2 items-center">
<input
id="color-border"
type="color"
value={config.custom_theme_colors.border_color || defaultDarkColors.border_color}
oninput={(e) => handleCustomColorChange("border_color", e.currentTarget.value)}
@@ -560,11 +573,15 @@
</div>
</div>
<div class="color-input-group">
<label class="text-xs text-[var(--text-secondary)]">Accent Primary</label>
<label class="text-xs text-[var(--text-secondary)]" for="color-accent-primary"
>Accent Primary</label
>
<div class="flex gap-2 items-center">
<input
id="color-accent-primary"
type="color"
value={config.custom_theme_colors.accent_primary || defaultDarkColors.accent_primary}
value={config.custom_theme_colors.accent_primary ||
defaultDarkColors.accent_primary}
oninput={(e) => handleCustomColorChange("accent_primary", e.currentTarget.value)}
class="color-picker"
/>
@@ -574,23 +591,32 @@
</div>
</div>
<div class="color-input-group">
<label class="text-xs text-[var(--text-secondary)]">Accent Secondary</label>
<label class="text-xs text-[var(--text-secondary)]" for="color-accent-secondary"
>Accent Secondary</label
>
<div class="flex gap-2 items-center">
<input
id="color-accent-secondary"
type="color"
value={config.custom_theme_colors.accent_secondary || defaultDarkColors.accent_secondary}
oninput={(e) => handleCustomColorChange("accent_secondary", e.currentTarget.value)}
value={config.custom_theme_colors.accent_secondary ||
defaultDarkColors.accent_secondary}
oninput={(e) =>
handleCustomColorChange("accent_secondary", e.currentTarget.value)}
class="color-picker"
/>
<span class="text-xs text-[var(--text-tertiary)] font-mono">
{config.custom_theme_colors.accent_secondary || defaultDarkColors.accent_secondary}
{config.custom_theme_colors.accent_secondary ||
defaultDarkColors.accent_secondary}
</span>
</div>
</div>
<div class="color-input-group">
<label class="text-xs text-[var(--text-secondary)]">Text Primary</label>
<label class="text-xs text-[var(--text-secondary)]" for="color-text-primary"
>Text Primary</label
>
<div class="flex gap-2 items-center">
<input
id="color-text-primary"
type="color"
value={config.custom_theme_colors.text_primary || defaultDarkColors.text_primary}
oninput={(e) => handleCustomColorChange("text_primary", e.currentTarget.value)}
@@ -602,11 +628,15 @@
</div>
</div>
<div class="color-input-group">
<label class="text-xs text-[var(--text-secondary)]">Text Secondary</label>
<label class="text-xs text-[var(--text-secondary)]" for="color-text-secondary"
>Text Secondary</label
>
<div class="flex gap-2 items-center">
<input
id="color-text-secondary"
type="color"
value={config.custom_theme_colors.text_secondary || defaultDarkColors.text_secondary}
value={config.custom_theme_colors.text_secondary ||
defaultDarkColors.text_secondary}
oninput={(e) => handleCustomColorChange("text_secondary", e.currentTarget.value)}
class="color-picker"
/>
+16 -6
View File
@@ -279,8 +279,15 @@
<svelte:window on:keydown={handleKeydown} />
{#if isOpen}
<!-- svelte-ignore a11y_click_events_have_key_events -->
<div class="git-panel-overlay" on:click={onClose} role="presentation">
<div class="git-panel" on:click|stopPropagation role="dialog" aria-label="Git Panel">
<div
class="git-panel"
on:click|stopPropagation
role="dialog"
aria-label="Git Panel"
tabindex="-1"
>
<div class="git-panel-header">
<h2>🔀 Git</h2>
<button class="close-btn" on:click={onClose} title="Close (Esc)"></button>
@@ -580,8 +587,15 @@
</div>
{#if showDiff}
<!-- svelte-ignore a11y_click_events_have_key_events -->
<div class="diff-overlay" on:click={() => (showDiff = false)} role="presentation">
<div class="diff-modal" on:click|stopPropagation role="dialog" aria-label="Diff View">
<div
class="diff-modal"
on:click|stopPropagation
role="dialog"
aria-label="Diff View"
tabindex="-1"
>
<div class="diff-header">
<h3>📄 {diffFile}</h3>
<button on:click={() => (showDiff = false)} title="Close"></button>
@@ -938,10 +952,6 @@
cursor: pointer;
}
.new-branch-input button:first-of-type {
/* Styling handled by btn-trans-gradient class */
}
.new-branch-input button:last-of-type {
background: var(--bg-tertiary);
color: var(--text-primary);
+125 -29
View File
@@ -39,11 +39,12 @@
let isGeneratingImage = false;
$: unlockedCount = Object.values($achievementsStore.achievements).filter((a) => a.unlocked).length;
$: unlockedCount = Object.values($achievementsStore.achievements).filter(
(a) => a.unlocked
).length;
$: totalAchievements = Object.values($achievementsStore.achievements).length;
$: achievementPercentage = totalAchievements > 0
? Math.round((unlockedCount / totalAchievements) * 100)
: 0;
$: achievementPercentage =
totalAchievements > 0 ? Math.round((unlockedCount / totalAchievements) * 100) : 0;
async function selectAvatar() {
try {
@@ -82,11 +83,15 @@
async function loadAvatarAsDataUrl(path: string): Promise<string | null> {
try {
const data = await readFile(path);
const extension = path.split('.').pop()?.toLowerCase() || 'png';
const mimeType = extension === 'jpg' || extension === 'jpeg' ? 'image/jpeg'
: extension === 'gif' ? 'image/gif'
: extension === 'webp' ? 'image/webp'
: 'image/png';
const extension = path.split(".").pop()?.toLowerCase() || "png";
const mimeType =
extension === "jpg" || extension === "jpeg"
? "image/jpeg"
: extension === "gif"
? "image/gif"
: extension === "webp"
? "image/webp"
: "image/png";
// Convert Uint8Array to base64 in chunks to avoid stack overflow
const blob = new Blob([data], { type: mimeType });
return new Promise((resolve) => {
@@ -123,7 +128,7 @@
const stripeColors = ["#5bcefa", "#f5a9b8", "#ffffff", "#f5a9b8", "#5bcefa"];
stripeColors.forEach((color, i) => {
ctx.fillStyle = color;
ctx.fillRect(0, i * (stripeHeight / 5) * 2, width, stripeHeight / 5 * 2);
ctx.fillRect(0, i * (stripeHeight / 5) * 2, width, (stripeHeight / 5) * 2);
});
// Border
@@ -154,7 +159,13 @@
img.onerror = () => reject();
img.src = dataUrl;
});
ctx.drawImage(img, avatarX - avatarRadius, avatarY - avatarRadius, avatarRadius * 2, avatarRadius * 2);
ctx.drawImage(
img,
avatarX - avatarRadius,
avatarY - avatarRadius,
avatarRadius * 2,
avatarRadius * 2
);
avatarLoaded = true;
}
} catch {
@@ -163,12 +174,22 @@
}
if (!avatarLoaded) {
const avatarGradient = ctx.createLinearGradient(avatarX - avatarRadius, avatarY - avatarRadius, avatarX + avatarRadius, avatarY + avatarRadius);
const avatarGradient = ctx.createLinearGradient(
avatarX - avatarRadius,
avatarY - avatarRadius,
avatarX + avatarRadius,
avatarY + avatarRadius
);
avatarGradient.addColorStop(0, "#5bcefa");
avatarGradient.addColorStop(0.5, "#f5a9b8");
avatarGradient.addColorStop(1, "#5bcefa");
ctx.fillStyle = avatarGradient;
ctx.fillRect(avatarX - avatarRadius, avatarY - avatarRadius, avatarRadius * 2, avatarRadius * 2);
ctx.fillRect(
avatarX - avatarRadius,
avatarY - avatarRadius,
avatarRadius * 2,
avatarRadius * 2
);
}
ctx.restore();
@@ -260,13 +281,23 @@
progressGradient.addColorStop(1, "#5bcefa");
ctx.fillStyle = progressGradient;
ctx.beginPath();
ctx.roundRect(progressX, progressY, progressWidth * (achievementPercentage / 100), progressHeight, 22);
ctx.roundRect(
progressX,
progressY,
progressWidth * (achievementPercentage / 100),
progressHeight,
22
);
ctx.fill();
// Progress text
ctx.fillStyle = "#ffffff";
ctx.font = "bold 36px system-ui, -apple-system, sans-serif";
ctx.fillText(`${unlockedCount} / ${totalAchievements} (${achievementPercentage}%)`, progressX + progressWidth + 40, progressY + 34);
ctx.fillText(
`${unlockedCount} / ${totalAchievements} (${achievementPercentage}%)`,
progressX + progressWidth + 40,
progressY + 34
);
// Hikari branding
ctx.fillStyle = "#f5a9b8";
@@ -312,7 +343,14 @@
<div class="profile-header">
<h2>Profile</h2>
<button class="close-btn" on:click={onClose} aria-label="Close profile">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<path d="M18 6L6 18M6 6l12 12" />
</svg>
</button>
@@ -321,7 +359,13 @@
<div class="profile-content">
<!-- Avatar Section -->
<div class="avatar-section">
<div class="avatar-container" on:click={selectAvatar} role="button" tabindex="0" on:keydown={(e) => e.key === 'Enter' && selectAvatar()}>
<div
class="avatar-container"
on:click={selectAvatar}
role="button"
tabindex="0"
on:keydown={(e) => e.key === "Enter" && selectAvatar()}
>
{#if avatarDataUrl}
<img src={avatarDataUrl} alt="Profile avatar" class="avatar-image" />
<div class="avatar-overlay">
@@ -329,7 +373,14 @@
</div>
{:else}
<div class="avatar-placeholder">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<svg
width="48"
height="48"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
>
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
<circle cx="12" cy="7" r="4" />
</svg>
@@ -350,13 +401,26 @@
bind:value={nameInput}
placeholder="Enter your name"
class="name-input"
on:keydown={(e) => e.key === 'Enter' && saveName()}
on:keydown={(e) => e.key === "Enter" && saveName()}
on:blur={saveName}
/>
{:else}
<button class="name-display" on:click={() => { editingName = true; nameInput = config.profile_name || ""; }}>
<button
class="name-display"
on:click={() => {
editingName = true;
nameInput = config.profile_name || "";
}}
>
<span class="name-text">{config.profile_name || "Click to add name"}</span>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
</svg>
@@ -377,7 +441,13 @@
></textarea>
<button class="save-bio-btn btn-trans-gradient" on:click={saveBio}>Save</button>
{:else}
<button class="bio-display" on:click={() => { editingBio = true; bioInput = config.profile_bio || ""; }}>
<button
class="bio-display"
on:click={() => {
editingBio = true;
bioInput = config.profile_bio || "";
}}
>
<span class="bio-text">{config.profile_bio || "Click to add a bio..."}</span>
</button>
{/if}
@@ -421,18 +491,31 @@
<div class="progress-bar">
<div class="progress-fill" style="width: {achievementPercentage}%"></div>
</div>
<span class="progress-text">{unlockedCount} / {totalAchievements} ({achievementPercentage}%)</span>
<span class="progress-text"
>{unlockedCount} / {totalAchievements} ({achievementPercentage}%)</span
>
</div>
</div>
<!-- Share Section -->
<div class="share-section">
<button class="share-btn btn-trans-gradient" on:click={shareProfile} disabled={isGeneratingImage}>
<button
class="share-btn btn-trans-gradient"
on:click={shareProfile}
disabled={isGeneratingImage}
>
{#if isGeneratingImage}
<span class="spinner"></span>
Generating...
{:else}
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" />
<polyline points="16 6 12 2 8 6" />
<line x1="12" y1="2" x2="12" y2="15" />
@@ -761,7 +844,14 @@
.progress-fill {
height: 100%;
background: linear-gradient(90deg, var(--trans-blue), var(--trans-pink), var(--trans-white), var(--trans-pink), var(--trans-blue));
background: linear-gradient(
90deg,
var(--trans-blue),
var(--trans-pink),
var(--trans-white),
var(--trans-pink),
var(--trans-blue)
);
background-size: 200% 100%;
animation: shimmer 3s linear infinite;
border-radius: 6px;
@@ -769,8 +859,12 @@
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
.progress-text {
@@ -828,6 +922,8 @@
}
@keyframes spin {
to { transform: rotate(360deg); }
to {
transform: rotate(360deg);
}
}
</style>
@@ -449,6 +449,7 @@
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
@@ -469,6 +469,7 @@
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
@@ -460,6 +460,7 @@
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
-8
View File
@@ -119,14 +119,6 @@
opacity: 0.8;
}
.stat-highlight {
font-weight: 600;
color: var(--accent-primary);
margin-top: 0.25rem;
padding-top: 0.25rem;
border-top: 1px solid var(--border-color);
}
.stat-label {
color: var(--text-secondary, #9ca3af);
}
+1 -1
View File
@@ -17,7 +17,7 @@
hasQuestionPending.subscribe((pending) => {
isVisible = pending;
if (!pending) {
selectedOptions = new SvelteSet();
selectedOptions.clear();
customAnswer = "";
showCustomInput = false;
}
+90 -11
View File
@@ -1502,12 +1502,25 @@ export const achievementCategories = [
{
name: "Token Milestones",
description: "Track your token generation progress",
ids: ["FirstSteps", "GrowingStrong", "BlossomingCoder", "TokenMaster", "TokenBillionaire", "TokenTreasure"] as AchievementId[],
ids: [
"FirstSteps",
"GrowingStrong",
"BlossomingCoder",
"TokenMaster",
"TokenBillionaire",
"TokenTreasure",
] as AchievementId[],
},
{
name: "Code Generation",
description: "Achievements for generating code",
ids: ["HelloWorld", "CodeWizard", "ThousandBlocks", "CodeFactory", "CodeEmpire"] as AchievementId[],
ids: [
"HelloWorld",
"CodeWizard",
"ThousandBlocks",
"CodeFactory",
"CodeEmpire",
] as AchievementId[],
},
{
name: "File Operations",
@@ -1517,7 +1530,13 @@ export const achievementCategories = [
{
name: "Conversations",
description: "Building our relationship through chat",
ids: ["ConversationStarter", "ChattyKathy", "Conversationalist", "ChatMarathon", "ChatLegend"] as AchievementId[],
ids: [
"ConversationStarter",
"ChattyKathy",
"Conversationalist",
"ChatMarathon",
"ChatLegend",
] as AchievementId[],
},
{
name: "Tools & Skills",
@@ -1556,7 +1575,16 @@ export const achievementCategories = [
{
name: "Relationship & Greetings",
description: "Our special moments together",
ids: ["GoodMorning", "GoodNight", "ThankYou", "LoveYou", "HelloHikari", "HowAreYou", "MissedYou", "BackAgain"] as AchievementId[],
ids: [
"GoodMorning",
"GoodNight",
"ThankYou",
"LoveYou",
"HelloHikari",
"HowAreYou",
"MissedYou",
"BackAgain",
] as AchievementId[],
},
{
name: "Personality & Fun",
@@ -1571,7 +1599,16 @@ export const achievementCategories = [
{
name: "Git & Development",
description: "Version control mastery",
ids: ["GitGuru", "TestWriter", "Debugger", "CommitKing", "CommitLegend", "BranchMaster", "MergeExpert", "ConflictResolver"] as AchievementId[],
ids: [
"GitGuru",
"TestWriter",
"Debugger",
"CommitKing",
"CommitLegend",
"BranchMaster",
"MergeExpert",
"ConflictResolver",
] as AchievementId[],
},
{
name: "Tool Mastery",
@@ -1606,17 +1643,41 @@ export const achievementCategories = [
{
name: "Seasonal",
description: "Holiday coding!",
ids: ["NewYearCoder", "ValentinesDev", "SpookyCode", "HolidayCoder", "LeapDayCoder"] as AchievementId[],
ids: [
"NewYearCoder",
"ValentinesDev",
"SpookyCode",
"HolidayCoder",
"LeapDayCoder",
] as AchievementId[],
},
{
name: "Message Content",
description: "How you communicate",
ids: ["LongMessage", "NovelWriter", "ShortAndSweet", "CodeInMessage", "MarkdownMaster"] as AchievementId[],
ids: [
"LongMessage",
"NovelWriter",
"ShortAndSweet",
"CodeInMessage",
"MarkdownMaster",
] as AchievementId[],
},
{
name: "Programming Languages",
description: "Languages you've used",
ids: ["RustDeveloper", "PythonDeveloper", "JavaScriptDev", "TypeScriptDev", "GoDeveloper", "CppDeveloper", "JavaDeveloper", "HtmlCssDev", "SqlDeveloper", "ShellScripter", "FullStackDev"] as AchievementId[],
ids: [
"RustDeveloper",
"PythonDeveloper",
"JavaScriptDev",
"TypeScriptDev",
"GoDeveloper",
"CppDeveloper",
"JavaDeveloper",
"HtmlCssDev",
"SqlDeveloper",
"ShellScripter",
"FullStackDev",
] as AchievementId[],
},
{
name: "Project Types",
@@ -1661,12 +1722,23 @@ export const achievementCategories = [
{
name: "UI Exploration",
description: "Explore Hikari's features",
ids: ["MultiTasker", "Minimalist", "PrivacyFirst", "ThemeChanger", "SettingsTweaker"] as AchievementId[],
ids: [
"MultiTasker",
"Minimalist",
"PrivacyFirst",
"ThemeChanger",
"SettingsTweaker",
] as AchievementId[],
},
{
name: "Achievement Meta",
description: "Achievements about achievements",
ids: ["AchievementHunter", "Completionist", "MasterUnlocker", "PlatinumStatus"] as AchievementId[],
ids: [
"AchievementHunter",
"Completionist",
"MasterUnlocker",
"PlatinumStatus",
] as AchievementId[],
},
{
name: "Clipboard & Snippets",
@@ -1676,7 +1748,14 @@ export const achievementCategories = [
{
name: "Other Features",
description: "Miscellaneous features",
ids: ["QuickActionUser", "HistoryBuff", "Archivist", "SessionExporter", "GitPanelUser", "FeatureExplorer"] as AchievementId[],
ids: [
"QuickActionUser",
"HistoryBuff",
"Archivist",
"SessionExporter",
"GitPanelUser",
"FeatureExplorer",
] as AchievementId[],
},
{
name: "Special",
+2 -1
View File
@@ -236,7 +236,8 @@ export function applyCustomThemeColors(colors: CustomThemeColors) {
if (colors.bg_secondary) root.style.setProperty("--bg-secondary", colors.bg_secondary);
if (colors.bg_terminal) root.style.setProperty("--bg-terminal", colors.bg_terminal);
if (colors.accent_primary) root.style.setProperty("--accent-primary", colors.accent_primary);
if (colors.accent_secondary) root.style.setProperty("--accent-secondary", colors.accent_secondary);
if (colors.accent_secondary)
root.style.setProperty("--accent-secondary", colors.accent_secondary);
if (colors.text_primary) root.style.setProperty("--text-primary", colors.text_primary);
if (colors.text_secondary) root.style.setProperty("--text-secondary", colors.text_secondary);
if (colors.border_color) root.style.setProperty("--border-color", colors.border_color);
+4 -1
View File
@@ -24,7 +24,7 @@
import UpdateNotification from "$lib/components/UpdateNotification.svelte";
let initialized = false;
let updateNotification: UpdateNotification;
let updateNotification: UpdateNotification | undefined = $state(undefined);
let achievementPanelOpen = $state(false);
let currentCharacterState: CharacterState = $state("idle");
let compactModeActive = $state(false);
@@ -375,6 +375,9 @@
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
opacity: 0;