diff --git a/src/lib/settings.ts b/src/lib/settings.ts
index 9bdfed2..c5febe5 100644
--- a/src/lib/settings.ts
+++ b/src/lib/settings.ts
@@ -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,
 });
diff --git a/src/lib/ui/ChooseName.svelte b/src/lib/ui/ChooseName.svelte
index 0ad1102..c6e0c23 100644
--- a/src/lib/ui/ChooseName.svelte
+++ b/src/lib/ui/ChooseName.svelte
@@ -7,7 +7,10 @@
   let value = "";
 
   function handleSubmit() {
-    settings.set({ ...settings, name: value });
+    settings.update((curSettings) => ({
+      ...curSettings,
+      name: value,
+    }));
   }
 </script>
 
diff --git a/src/lib/ui/Settings.svelte b/src/lib/ui/Settings.svelte
index 0a33965..e12fa6a 100644
--- a/src/lib/ui/Settings.svelte
+++ b/src/lib/ui/Settings.svelte
@@ -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;
 
@@ -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
@@ -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,
+              }));
             }
           }}
         />
@@ -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 -->
@@ -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>
diff --git a/src/lib/ui/XTerm.svelte b/src/lib/ui/XTerm.svelte
index 8fb763e..6eed2bf 100644
--- a/src/lib/ui/XTerm.svelte
+++ b/src/lib/ui/XTerm.svelte
@@ -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");
 
@@ -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";
diff --git a/src/lib/ui/themes.ts b/src/lib/ui/themes.ts
index 18dc7bf..d326a74 100644
--- a/src/lib/ui/themes.ts
+++ b/src/lib/ui/themes.ts
@@ -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",
 
@@ -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",
 
@@ -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;