mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 04:15:30 +00:00
Add settings dropdown
This commit is contained in:
parent
30ac9165e1
commit
a83eef57e2
6 changed files with 128 additions and 46 deletions
|
|
@ -19,6 +19,7 @@
|
||||||
"@radix-ui/react-separator": "^1.1.0",
|
"@radix-ui/react-separator": "^1.1.0",
|
||||||
"@radix-ui/react-slot": "^1.1.0",
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
"@replit/codemirror-vim": "^6.2.1",
|
"@replit/codemirror-vim": "^6.2.1",
|
||||||
|
"@uidotdev/usehooks": "^2.4.1",
|
||||||
"@uiw/react-codemirror": "^4.23.0",
|
"@uiw/react-codemirror": "^4.23.0",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {
|
||||||
} from "@/components/ui/resizable";
|
} from "@/components/ui/resizable";
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { useNonEmptyQueryParam } from "@/hooks/useNonEmptyQueryParam";
|
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 { createPathWithQueryParams } from "@/lib/utils";
|
||||||
import { SymbolIcon } from "@radix-ui/react-icons";
|
import { SymbolIcon } from "@radix-ui/react-icons";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
|
@ -18,7 +18,8 @@ import logoLight from "../../public/sb_logo_light.png";
|
||||||
import { CodePreview } from "./codePreview";
|
import { CodePreview } from "./codePreview";
|
||||||
import { SearchBar } from "./searchBar";
|
import { SearchBar } from "./searchBar";
|
||||||
import { SearchResults } from "./searchResults";
|
import { SearchResults } from "./searchResults";
|
||||||
import { ThemeSelectorButton } from "./themeSelectorButton";
|
import { SettingsDropdown } from "./settingsDropdown";
|
||||||
|
import { useLocalStorage } from "@uidotdev/usehooks";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -36,6 +37,8 @@ export default function Home() {
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [searchDurationMs, setSearchDurationMs] = useState(0);
|
const [searchDurationMs, setSearchDurationMs] = useState(0);
|
||||||
|
|
||||||
|
const [keymapType, saveKeymapType] = useLocalStorage<KeymapType>("keymapType", "default");
|
||||||
|
|
||||||
// @todo: We need to be able to handle the case when the user navigates backwards / forwards.
|
// @todo: We need to be able to handle the case when the user navigates backwards / forwards.
|
||||||
// Currently we do not re-query.
|
// Currently we do not re-query.
|
||||||
|
|
||||||
|
|
@ -73,7 +76,10 @@ export default function Home() {
|
||||||
<SymbolIcon className="h-4 w-4 animate-spin" />
|
<SymbolIcon className="h-4 w-4 animate-spin" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<ThemeSelectorButton />
|
<SettingsDropdown
|
||||||
|
keymapType={keymapType}
|
||||||
|
onKeymapTypeChange={saveKeymapType}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className="bg-accent p-2">
|
<div className="bg-accent p-2">
|
||||||
|
|
@ -115,7 +121,7 @@ export default function Home() {
|
||||||
code={code}
|
code={code}
|
||||||
filepath={filepath}
|
filepath={filepath}
|
||||||
onClose={() => setIsCodePanelOpen(false)}
|
onClose={() => setIsCodePanelOpen(false)}
|
||||||
keymapType="default"
|
keymapType={keymapType}
|
||||||
/>
|
/>
|
||||||
</ResizablePanel>
|
</ResizablePanel>
|
||||||
</ResizablePanelGroup>
|
</ResizablePanelGroup>
|
||||||
|
|
|
||||||
109
src/app/settingsDropdown.tsx
Normal file
109
src/app/settingsDropdown.tsx
Normal file
|
|
@ -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 <Sun className="h-4 w-4 mr-2" />;
|
||||||
|
case "dark":
|
||||||
|
return <Moon className="h-4 w-4 mr-2" />;
|
||||||
|
case "system":
|
||||||
|
return <Laptop className="h-4 w-4 mr-2" />;
|
||||||
|
default:
|
||||||
|
return <Laptop className="h-4 w-4 mr-2" />;
|
||||||
|
}
|
||||||
|
}, [theme]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button variant="outline" size="icon">
|
||||||
|
<Settings className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent className="w-56">
|
||||||
|
<DropdownMenuLabel>Settings</DropdownMenuLabel>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuGroup>
|
||||||
|
<DropdownMenuSub>
|
||||||
|
<DropdownMenuSubTrigger>
|
||||||
|
{ThemeIcon}
|
||||||
|
<span>Theme</span>
|
||||||
|
</DropdownMenuSubTrigger>
|
||||||
|
<DropdownMenuPortal>
|
||||||
|
<DropdownMenuSubContent>
|
||||||
|
<DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
||||||
|
<DropdownMenuRadioItem value="light">
|
||||||
|
Light
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
<DropdownMenuRadioItem value="dark">
|
||||||
|
Dark
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
<DropdownMenuRadioItem value="system">
|
||||||
|
System
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
</DropdownMenuRadioGroup>
|
||||||
|
</DropdownMenuSubContent>
|
||||||
|
</DropdownMenuPortal>
|
||||||
|
</DropdownMenuSub>
|
||||||
|
<DropdownMenuSub>
|
||||||
|
<DropdownMenuSubTrigger>
|
||||||
|
<CodeIcon className="h-4 w-4 mr-2" />
|
||||||
|
<span>Code navigation</span>
|
||||||
|
</DropdownMenuSubTrigger>
|
||||||
|
<DropdownMenuPortal>
|
||||||
|
<DropdownMenuSubContent>
|
||||||
|
<DropdownMenuRadioGroup value={keymapType} onValueChange={(value) => onKeymapTypeChange(value as KeymapType)}>
|
||||||
|
<DropdownMenuRadioItem value="default">
|
||||||
|
Default
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
<DropdownMenuRadioItem value="vim">
|
||||||
|
Vim
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
</DropdownMenuRadioGroup>
|
||||||
|
</DropdownMenuSubContent>
|
||||||
|
</DropdownMenuPortal>
|
||||||
|
</DropdownMenuSub>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -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 (
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenuTrigger asChild>
|
|
||||||
<Button variant="outline" size="icon">
|
|
||||||
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
|
||||||
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
|
||||||
<span className="sr-only">Toggle theme</span>
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent align="end">
|
|
||||||
<DropdownMenuItem onClick={() => setTheme("light")}>
|
|
||||||
Light
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem onClick={() => setTheme("dark")}>
|
|
||||||
Dark
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem onClick={() => setTheme("system")}>
|
|
||||||
System
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -37,4 +37,6 @@ export interface ZoektResult {
|
||||||
|
|
||||||
export interface ZoektSearchResponse {
|
export interface ZoektSearchResponse {
|
||||||
result: ZoektResult,
|
result: ZoektResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type KeymapType = "default" | "vim";
|
||||||
|
|
@ -677,6 +677,11 @@
|
||||||
"@typescript-eslint/types" "7.2.0"
|
"@typescript-eslint/types" "7.2.0"
|
||||||
eslint-visitor-keys "^3.4.1"
|
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":
|
"@uiw/codemirror-extensions-basic-setup@4.23.0":
|
||||||
version "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"
|
resolved "https://registry.yarnpkg.com/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.23.0.tgz#c3c181153335c208a25d59b8ecbc7fc87fe85356"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue