From a83eef57e260b8596c6d4cee60d857bc76205f4e Mon Sep 17 00:00:00 2001 From: bkellam Date: Tue, 27 Aug 2024 21:00:59 -0700 Subject: [PATCH] Add settings dropdown --- package.json | 1 + src/app/page.tsx | 14 ++-- src/app/settingsDropdown.tsx | 109 ++++++++++++++++++++++++++++++++ src/app/themeSelectorButton.tsx | 41 ------------ src/lib/types.ts | 4 +- yarn.lock | 5 ++ 6 files changed, 128 insertions(+), 46 deletions(-) create mode 100644 src/app/settingsDropdown.tsx delete mode 100644 src/app/themeSelectorButton.tsx diff --git a/package.json b/package.json index 6903f56a..24136e0d 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", "@replit/codemirror-vim": "^6.2.1", + "@uidotdev/usehooks": "^2.4.1", "@uiw/react-codemirror": "^4.23.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", diff --git a/src/app/page.tsx b/src/app/page.tsx index cd69d001..d71a78bd 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -7,7 +7,7 @@ import { } from "@/components/ui/resizable"; import { Separator } from "@/components/ui/separator"; import { useNonEmptyQueryParam } from "@/hooks/useNonEmptyQueryParam"; -import { GetSourceResponse, pathQueryParamName, repoQueryParamName, ZoektFileMatch } from "@/lib/types"; +import { GetSourceResponse, KeymapType, pathQueryParamName, repoQueryParamName, ZoektFileMatch } from "@/lib/types"; import { createPathWithQueryParams } from "@/lib/utils"; import { SymbolIcon } from "@radix-ui/react-icons"; import Image from "next/image"; @@ -18,7 +18,8 @@ import logoLight from "../../public/sb_logo_light.png"; import { CodePreview } from "./codePreview"; import { SearchBar } from "./searchBar"; import { SearchResults } from "./searchResults"; -import { ThemeSelectorButton } from "./themeSelectorButton"; +import { SettingsDropdown } from "./settingsDropdown"; +import { useLocalStorage } from "@uidotdev/usehooks"; export default function Home() { const router = useRouter(); @@ -36,6 +37,8 @@ export default function Home() { const [isLoading, setIsLoading] = useState(false); const [searchDurationMs, setSearchDurationMs] = useState(0); + const [keymapType, saveKeymapType] = useLocalStorage("keymapType", "default"); + // @todo: We need to be able to handle the case when the user navigates backwards / forwards. // Currently we do not re-query. @@ -73,7 +76,10 @@ export default function Home() { )} - +
@@ -115,7 +121,7 @@ export default function Home() { code={code} filepath={filepath} onClose={() => setIsCodePanelOpen(false)} - keymapType="default" + keymapType={keymapType} /> diff --git a/src/app/settingsDropdown.tsx b/src/app/settingsDropdown.tsx new file mode 100644 index 00000000..1ef33f6e --- /dev/null +++ b/src/app/settingsDropdown.tsx @@ -0,0 +1,109 @@ +import { + CodeIcon, + Laptop, + Moon, + Settings, + Sun +} from "lucide-react" +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuLabel, + DropdownMenuPortal, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuSeparator, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { useTheme } from "next-themes" +import { useMemo } from "react" +import { KeymapType } from "@/lib/types" + +interface SettingsDropdownProps { + keymapType: KeymapType; + onKeymapTypeChange: (keymapType: KeymapType) => void; +} + +export const SettingsDropdown = ({ + keymapType, + onKeymapTypeChange, +}: SettingsDropdownProps) => { + + const { theme: _theme, setTheme } = useTheme(); + const theme = useMemo(() => { + return _theme ?? "light"; + }, [_theme]); + + const ThemeIcon = useMemo(() => { + switch (theme) { + case "light": + return ; + case "dark": + return ; + case "system": + return ; + default: + return ; + } + }, [theme]); + + return ( + + + + + + Settings + + + + + {ThemeIcon} + Theme + + + + + + Light + + + Dark + + + System + + + + + + + + + Code navigation + + + + onKeymapTypeChange(value as KeymapType)}> + + Default + + + Vim + + + + + + + + + ) +} diff --git a/src/app/themeSelectorButton.tsx b/src/app/themeSelectorButton.tsx deleted file mode 100644 index 299fec61..00000000 --- a/src/app/themeSelectorButton.tsx +++ /dev/null @@ -1,41 +0,0 @@ -"use client" - -import * as React from "react" -import { Moon, Sun } from "lucide-react" -import { useTheme } from "next-themes" - -import { Button } from "@/components/ui/button" -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu" - - -export const ThemeSelectorButton = () => { - const { setTheme } = useTheme() - - return ( - - - - - - setTheme("light")}> - Light - - setTheme("dark")}> - Dark - - setTheme("system")}> - System - - - - ) -} \ No newline at end of file diff --git a/src/lib/types.ts b/src/lib/types.ts index 2a8e2430..a2532b30 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -37,4 +37,6 @@ export interface ZoektResult { export interface ZoektSearchResponse { result: ZoektResult, -} \ No newline at end of file +} + +export type KeymapType = "default" | "vim"; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 5d748551..18ac5cf7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -677,6 +677,11 @@ "@typescript-eslint/types" "7.2.0" eslint-visitor-keys "^3.4.1" +"@uidotdev/usehooks@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@uidotdev/usehooks/-/usehooks-2.4.1.tgz#4b733eaeae09a7be143c6c9ca158b56cc1ea75bf" + integrity sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg== + "@uiw/codemirror-extensions-basic-setup@4.23.0": version "4.23.0" resolved "https://registry.yarnpkg.com/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.23.0.tgz#c3c181153335c208a25d59b8ecbc7fc87fe85356"