Skip to content
Merged
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
1 change: 1 addition & 0 deletions apps/web/src/appSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export const AppSettingsSchema = Schema.Struct({
sidebarAccentProjectNames: Schema.Boolean.pipe(withDefaults(() => true)),
sidebarAccentColorOverride: Schema.optional(Schema.String.check(Schema.isMaxLength(64))),
sidebarAccentBgColorOverride: Schema.optional(Schema.String.check(Schema.isMaxLength(64))),
showStitchBorder: Schema.Boolean.pipe(withDefaults(() => true)),
sidebarWideThreadNames: Schema.Boolean.pipe(withDefaults(() => true)),
customCodexModels: Schema.Array(Schema.String).pipe(withDefaults(() => [])),
customClaudeModels: Schema.Array(Schema.String).pipe(withDefaults(() => [])),
Expand Down
14 changes: 9 additions & 5 deletions apps/web/src/components/VoodooStitches.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { useEffect, useState, useMemo } from "react";
import { useAppSettings } from "../appSettings";

/**
* Purely decorative voodoo-doll stitch border around the entire viewport.
* Each X-shaped cross-stitch pulses in opacity with a sequential delay,
* creating a wave that flows around the perimeter like calm backlit water.
*/

const STITCH_SPACING = 30; // px between stitch centers
const STITCH_SIZE = 6; // half-size of each X arm
const EDGE_INSET = 6; // px inset from viewport edge
const ANIMATION_DURATION = 6; // seconds for one full pulse cycle
const STROKE_WIDTH = 1.5;
const STITCH_SPACING = 40; // px between stitch centers
const STITCH_SIZE = 4; // half-size of each X arm
const EDGE_INSET = 4; // px inset from viewport edge
const ANIMATION_DURATION = 8; // seconds for one full pulse cycle
const STROKE_WIDTH = 1;

interface Stitch {
cx: number;
Expand Down Expand Up @@ -68,6 +69,7 @@ function generateStitches(w: number, h: number): { stitches: Stitch[]; total: nu
}

export function VoodooStitches() {
const { settings } = useAppSettings();
const [dimensions, setDimensions] = useState({ w: window.innerWidth, h: window.innerHeight });

useEffect(() => {
Expand All @@ -94,6 +96,8 @@ export function VoodooStitches() {
// Wave spans the full perimeter — each stitch gets a delay proportional to its position
const delayPerStitch = total > 0 ? ANIMATION_DURATION / total : 0;

if (!settings.showStitchBorder) return null;

return (
<div
aria-hidden
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -667,10 +667,10 @@ label:has(> select#reasoning-effort) select {
@keyframes voodoo-stitch-pulse {
0%,
100% {
opacity: 0.15;
opacity: 0.08;
}
50% {
opacity: 0.55;
opacity: 0.3;
}
}

Expand Down
29 changes: 29 additions & 0 deletions apps/web/src/routes/_chat.settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ function SettingsRouteView() {
...(fontFamily !== "inter" ? ["Font"] : []),
...(settings.timestampFormat !== defaults.timestampFormat ? ["Time format"] : []),
...(settings.diffWordWrap !== defaults.diffWordWrap ? ["Diff line wrapping"] : []),
...(settings.showStitchBorder !== defaults.showStitchBorder ? ["Stitch border"] : []),
...(settings.enableAssistantStreaming !== defaults.enableAssistantStreaming
? ["Assistant output"]
: []),
Expand Down Expand Up @@ -1150,6 +1151,34 @@ function SettingsRouteView() {
}
/>

<SettingsRow
title="Stitch border"
description="Show the decorative stitch border around the viewport."
resetAction={
settings.showStitchBorder !== defaults.showStitchBorder ? (
<SettingResetButton
label="stitch border"
onClick={() =>
updateSettings({
showStitchBorder: defaults.showStitchBorder,
})
}
/>
) : null
}
control={
<Switch
checked={settings.showStitchBorder}
onCheckedChange={(checked) =>
updateSettings({
showStitchBorder: Boolean(checked),
})
}
aria-label="Show stitch border"
/>
}
/>

<SettingsRow
title="Assistant output"
description="Show token-by-token output while a response is in progress."
Expand Down
Loading