Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic palette selector (updated) #81

Merged
merged 3 commits into from
Apr 6, 2024
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
3 changes: 3 additions & 0 deletions src/lib/settings.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { persisted } from "svelte-persisted-store";
import { type ThemeName, defaultTheme } from "./ui/themes";

export type SettingsStore = {
name: string;
theme: ThemeName;
};

/** A persisted store for settings of the current user. */
export const settings = persisted<SettingsStore>("sshx-settings-store", {
name: "",
theme: defaultTheme,
});
5 changes: 4 additions & 1 deletion src/lib/ui/ChooseName.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
let value = "";

function handleSubmit() {
settings.set({ ...settings, name: value });
settings.update((curSettings) => ({
...curSettings,
name: value,
}));
}
</script>

Expand Down
60 changes: 48 additions & 12 deletions src/lib/ui/Settings.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<script lang="ts">
import { settings } from "$lib/settings";
import { ChevronDownIcon } from "svelte-feather-icons";
import OverlayMenu from "./OverlayMenu.svelte";
import themes, { defaultTheme, type ThemeName } from "./themes";

export let open: boolean;

Expand All @@ -12,6 +14,20 @@
initialized = true;
nameValue = $settings.name;
}

let selectedTheme: ThemeName; // Bound to the settings input.
if (Object.hasOwn(themes, $settings.theme)) {
selectedTheme = $settings.theme;
} else {
selectedTheme = defaultTheme;
}

function handleThemeChange() {
settings.update((curSettings) => ({
...curSettings,
theme: selectedTheme,
}));
}
</script>

<OverlayMenu
Expand All @@ -21,23 +37,26 @@
{open}
on:close
>
<div class="flex flex-col gap-2">
<div class="flex flex-col gap-4">
<div class="item">
<div class="flex-1">
<p class="font-medium mb-2">Name</p>
<p class="text-sm text-zinc-400">
How you appear to other users online.
Choose how you appear to other users.
</p>
</div>
<div>
<input
class="w-52 px-3 py-1.5 rounded-md bg-zinc-700 outline-none focus:ring-2 focus:ring-indigo-500"
class="input-common"
placeholder="Your name"
bind:value={nameValue}
maxlength="50"
on:input={() => {
if (nameValue.length >= 2) {
settings.set({ ...$settings, name: nameValue });
settings.update((curSettings) => ({
...curSettings,
name: nameValue,
}));
}
}}
/>
Expand All @@ -46,19 +65,30 @@
<div class="item">
<div class="flex-1">
<p class="font-medium mb-2">Color palette</p>
<p class="text-sm text-zinc-400">Color scheme for text in terminals.</p>
<p class="text-sm text-zinc-400">Color theme for text in terminals.</p>
</div>
<div class="relative">
<ChevronDownIcon
class="absolute top-[11px] right-2.5 w-4 h-4 text-zinc-400"
/>
<select
class="input-common !pr-5"
bind:value={selectedTheme}
on:change={handleThemeChange}
>
{#each Object.keys(themes) as themeName (themeName)}
<option value={themeName}>{themeName}</option>
{/each}
</select>
</div>
<div class="text-red-500">Coming soon</div>
</div>
<div class="item">
<!-- <div class="item">
<div class="flex-1">
<p class="font-medium mb-2">Cursor style</p>
<p class="text-sm text-zinc-400">
How live cursors should be displayed.
</p>
<p class="text-sm text-zinc-400">Style of live cursors.</p>
</div>
<div class="text-red-500">Coming soon</div>
</div>
</div> -->
</div>

<!-- svelte-ignore missing-declaration -->
Expand All @@ -71,6 +101,12 @@

<style lang="postcss">
.item {
@apply bg-zinc-800/25 rounded-lg p-4 flex gap-4 flex-col sm:flex-row;
@apply bg-zinc-800/25 rounded-lg p-4 flex gap-4 flex-col sm:flex-row items-start;
}

.input-common {
@apply w-52 px-3 py-2 text-sm rounded-md bg-transparent hover:bg-white/5;
@apply border border-zinc-700 outline-none focus:ring-2 focus:ring-indigo-500/50;
@apply appearance-none transition-colors;
}
</style>
14 changes: 11 additions & 3 deletions src/lib/ui/XTerm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,12 @@
import type { Terminal } from "sshx-xterm";
import { Buffer } from "buffer";

import themes from "./themes";
import themes, { defaultTheme } from "./themes";
import CircleButton from "./CircleButton.svelte";
import CircleButtons from "./CircleButtons.svelte";
import { settings } from "$lib/settings";
import { TypeAheadAddon } from "$lib/typeahead";

const theme = themes.defaultDark;

/** Used to determine Cmd versus Ctrl keyboard shortcuts. */
const isMac = browser && navigator.platform.startsWith("Mac");

Expand All @@ -68,6 +67,15 @@
export let termEl: HTMLDivElement = null as any; // suppress "missing prop" warning
let term: Terminal | null = null;

$: theme = Object.hasOwn(themes, $settings.theme)
? themes[$settings.theme]
: themes[defaultTheme];

$: if (term) {
// If the theme changes, update existing terminals' appearance.
term.options.theme = theme;
}

let loaded = false;
let focused = false;
let currentTitle = "Remote Terminal";
Expand Down
174 changes: 171 additions & 3 deletions src/lib/ui/themes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ITheme } from "sshx-xterm";

/** VSCode default dark theme, from https://glitchbone.github.io/vscode-base16-term/. */
export const defaultDark: ITheme = {
const defaultDark: ITheme = {
foreground: "#d8d8d8",
background: "#181818",

Expand All @@ -27,7 +27,7 @@ export const defaultDark: ITheme = {
};

/** Hybrid theme from https://terminal.sexy/, using Alacritty export format. */
export const hybrid: ITheme = {
const hybrid: ITheme = {
foreground: "#c5c8c6",
background: "#1d1f21",

Expand All @@ -50,4 +50,172 @@ export const hybrid: ITheme = {
brightWhite: "#c5c8c6",
};

export default { defaultDark, hybrid };
/** Below themes are converted from https://github.com/alacritty/alacritty-theme/. */
const rosePine: ITheme = {
foreground: "#e0def4",
background: "#191724",

cursor: "#524f67",

black: "#26233a",
red: "#eb6f92",
green: "#31748f",
yellow: "#f6c177",
blue: "#9ccfd8",
magenta: "#c4a7e7",
cyan: "#ebbcba",
white: "#e0def4",

brightBlack: "#6e6a86",
brightRed: "#eb6f92",
brightGreen: "#31748f",
brightYellow: "#f6c177",
brightBlue: "#9ccfd8",
brightMagenta: "#c4a7e7",
brightCyan: "#ebbcba",
brightWhite: "#e0def4",
};

const ubuntu: ITheme = {
foreground: "#eeeeec",
background: "#300a24",
black: "#2e3436",
red: "#cc0000",
green: "#4e9a06",
yellow: "#c4a000",
blue: "#3465a4",
magenta: "#75507b",
cyan: "#06989a",
white: "#d3d7cf",
brightBlack: "#555753",
brightRed: "#ef2929",
brightGreen: "#8ae234",
brightYellow: "#fce94f",
brightBlue: "#729fcf",
brightMagenta: "#ad7fa8",
brightCyan: "#34e2e2",
brightWhite: "#eeeeec",
};

const dracula: ITheme = {
foreground: "#f8f8f2",
background: "#282a36",
black: "#000000",
red: "#ff5555",
green: "#50fa7b",
yellow: "#f1fa8c",
blue: "#bd93f9",
magenta: "#ff79c6",
cyan: "#8be9fd",
white: "#bbbbbb",
brightBlack: "#555555",
brightRed: "#ff5555",
brightGreen: "#50fa7b",
brightYellow: "#f1fa8c",
brightBlue: "#caa9fa",
brightMagenta: "#ff79c6",
brightCyan: "#8be9fd",
brightWhite: "#ffffff",
};

const githubDark: ITheme = {
foreground: "#d1d5da",
background: "#24292e",
black: "#586069",
red: "#ea4a5a",
green: "#34d058",
yellow: "#ffea7f",
blue: "#2188ff",
magenta: "#b392f0",
cyan: "#39c5cf",
white: "#d1d5da",
brightBlack: "#959da5",
brightRed: "#f97583",
brightGreen: "#85e89d",
brightYellow: "#ffea7f",
brightBlue: "#79b8ff",
brightMagenta: "#b392f0",
brightCyan: "#56d4dd",
brightWhite: "#fafbfc",
};

const gruvboxDark: ITheme = {
foreground: "#ebdbb2",
background: "#282828",
black: "#282828",
red: "#cc241d",
green: "#98971a",
yellow: "#d79921",
blue: "#458588",
magenta: "#b16286",
cyan: "#689d6a",
white: "#a89984",
brightBlack: "#928374",
brightRed: "#fb4934",
brightGreen: "#b8bb26",
brightYellow: "#fabd2f",
brightBlue: "#83a598",
brightMagenta: "#d3869b",
brightCyan: "#8ec07c",
brightWhite: "#ebdbb2",
};

const solarizedDark: ITheme = {
foreground: "#839496",
background: "#002b36",
black: "#073642",
red: "#dc322f",
green: "#859900",
yellow: "#b58900",
blue: "#268bd2",
magenta: "#d33682",
cyan: "#2aa198",
white: "#eee8d5",
brightBlack: "#002b36",
brightRed: "#cb4b16",
brightGreen: "#586e75",
brightYellow: "#657b83",
brightBlue: "#839496",
brightMagenta: "#6c71c4",
brightCyan: "#93a1a1",
brightWhite: "#fdf6e3",
};

const tokyoNight: ITheme = {
foreground: "#a9b1d6",
background: "#1a1b26",
black: "#32344a",
red: "#f7768e",
green: "#9ece6a",
yellow: "#e0af68",
blue: "#7aa2f7",
magenta: "#ad8ee6",
cyan: "#449dab",
white: "#787c99",
brightBlack: "#444b6a",
brightRed: "#ff7a93",
brightGreen: "#b9f27c",
brightYellow: "#ff9e64",
brightBlue: "#7da6ff",
brightMagenta: "#bb9af7",
brightCyan: "#0db9d7",
brightWhite: "#acb0d0",
};

const themes = {
"VS Code Dark": defaultDark,
Hybrid: hybrid,
"Rosé Pine": rosePine,
Ubuntu: ubuntu,
Dracula: dracula,
"GitHub Dark": githubDark,
"Gruvbox Dark": gruvboxDark,
"Solarized Dark": solarizedDark,
"Tokyo Night": tokyoNight,
};

export type ThemeName = keyof typeof themes;

export const defaultTheme: ThemeName = "VS Code Dark";

export default themes;
Loading