Skip to content
Closed
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
186 changes: 14 additions & 172 deletions bun.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion components.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"hooks": "@/hooks"
},
"registries": {
"@svgl": "https://svgl.app/r/{name}.json"
"@svgl": "https://svgl.app/r/{name}.json",
"@coss": "https://coss.com/ui/r/{name}.json"
}
}
10 changes: 3 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@
"tauri": "tauri"
},
"dependencies": {
"@base-ui/react": "^1.5.0",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@radix-ui/react-scroll-area": "^1.2.2",
"@radix-ui/react-select": "^2.1.4",
"@radix-ui/react-separator": "^1.1.1",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-toolbar": "^1.1.11",
"@fontsource-variable/geist-mono": "^5.2.8",
"@fontsource-variable/inter": "^5.2.8",
"@tauri-apps/api": "^2.1.1",
"@tauri-apps/plugin-opener": "^2.2.6",
"@tauri-apps/plugin-process": "^2.2.0",
Expand All @@ -32,12 +30,10 @@
"@tauri-apps/plugin-window-state": "~2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"colord": "^2.9.3",
"leaflet": "^1.9.4",
"lucide-react": "1.16.0",
"motion": "^12.39.0",
"radix-ui": "^1.4.3",
"react": "^19.0.0",
"react-country-flag": "^3.1.0",
"react-dom": "^19.0.0",
Expand Down
150 changes: 84 additions & 66 deletions src/components/display/edit-toolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { m, AnimatePresence } from "motion/react"
import { Check, Map, MapPin, MapPinOff, Pencil, RotateCcw } from "lucide-react"
import { toast } from "sonner"
import * as Toolbar from "@radix-ui/react-toolbar"

import { Button } from "@/components/ui/button"
import { Toolbar, ToolbarButton } from "@/components/ui/toolbar"
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
import { useDisplayStore } from "@/lib/display-store"
import { clearMockIfPresent } from "@/lib/mock-data"
Expand Down Expand Up @@ -37,90 +37,108 @@ export function EditToolbar() {
className="pointer-events-none fixed inset-x-0 z-[2000] flex justify-center px-2 transition-[bottom,left] duration-500"
style={{ left: mapVisible ? sidebarWidth : 0, bottom: mapVisible ? 12 : 54 }}
>
<Toolbar.Root className="pointer-events-auto flex max-w-[calc(100vw-16px)] flex-nowrap items-center justify-center gap-1 whitespace-nowrap rounded-xl border border-sidebar-border bg-sidebar/95 px-2 py-1.5 shadow-xl backdrop-blur">
<Toolbar className="pointer-events-auto flex max-w-[calc(100vw-16px)] flex-nowrap items-center justify-center gap-1 whitespace-nowrap rounded-xl border border-sidebar-border bg-sidebar/95 px-2 py-1.5 shadow-xl backdrop-blur">
<div className="inline-flex shrink-0 items-center gap-1.5 px-1 text-[12px] font-medium">
<Pencil className="size-3.5 text-brand" />
{mapVisible && <span className="leading-tight">{t("toolbar.editing")}</span>}
</div>

<Tooltip>
<TooltipTrigger asChild>
<Toolbar.Button asChild>
<Button
variant="ghost"
size="sm"
className="h-7 shrink-0 gap-1.5 rounded-full px-2 text-xs"
onClick={() => setMapVisible(!mapVisible)}
title={mapVisible ? t("toolbar.hideMap") : t("toolbar.showMap")}
>
{mapVisible ? <Map className="size-3.5" /> : <MapPinOff className="size-3.5" />}
{mapVisible && t("toolbar.hideMap")}
{!mapVisible && <span className="sr-only">{t("toolbar.showMap")}</span>}
</Button>
</Toolbar.Button>
</TooltipTrigger>
<TooltipTrigger
render={
<ToolbarButton
render={
<Button
variant="ghost"
size="sm"
className="h-7 shrink-0 gap-1.5 rounded-full px-2 text-xs"
onClick={() => setMapVisible(!mapVisible)}
title={mapVisible ? t("toolbar.hideMap") : t("toolbar.showMap")}
>
{mapVisible ? (
<Map className="size-3.5" />
) : (
<MapPinOff className="size-3.5" />
)}
{mapVisible && t("toolbar.hideMap")}
{!mapVisible && <span className="sr-only">{t("toolbar.showMap")}</span>}
</Button>
}
/>
}
/>
<TooltipContent side="top">
{mapVisible ? t("toolbar.hideMapTooltip") : t("toolbar.showMapTooltip")}
</TooltipContent>
</Tooltip>

<Tooltip>
<TooltipTrigger asChild>
<Toolbar.Button asChild>
<Button
variant="ghost"
size="icon"
className={cn(
"size-7 shrink-0 rounded-full",
markerToolbarOpen && "bg-accent text-foreground"
)}
aria-label={t("marker.customizeTitle")}
title={t("marker.customizeTitle")}
aria-pressed={markerToolbarOpen}
onClick={() => setMarkerToolbarOpen(!markerToolbarOpen)}
>
<MapPin className="size-3.5" />
</Button>
</Toolbar.Button>
</TooltipTrigger>
<TooltipTrigger
render={
<ToolbarButton
render={
<Button
variant="ghost"
size="icon"
className={cn(
"size-7 shrink-0 rounded-full",
markerToolbarOpen && "bg-accent text-foreground"
)}
aria-label={t("marker.customizeTitle")}
title={t("marker.customizeTitle")}
aria-pressed={markerToolbarOpen}
onClick={() => setMarkerToolbarOpen(!markerToolbarOpen)}
>
<MapPin className="size-3.5" />
</Button>
}
/>
}
/>
<TooltipContent side="top">{t("marker.customizeTitle")}</TooltipContent>
</Tooltip>

<Tooltip>
<TooltipTrigger asChild>
<Toolbar.Button asChild>
<Button
variant="ghost"
size="sm"
className="h-7 shrink-0 gap-1.5 rounded-full px-2 text-xs"
onClick={() => {
resetAll()
toast.success(t("toolbar.resetSuccess"))
}}
title={t("toolbar.reset")}
>
<RotateCcw className="size-3.5" />
{mapVisible && t("toolbar.reset")}
{!mapVisible && <span className="sr-only">{t("toolbar.reset")}</span>}
</Button>
</Toolbar.Button>
</TooltipTrigger>
<TooltipTrigger
render={
<ToolbarButton
render={
<Button
variant="ghost"
size="sm"
className="h-7 shrink-0 gap-1.5 rounded-full px-2 text-xs"
onClick={() => {
resetAll()
toast.success(t("toolbar.resetSuccess"))
}}
title={t("toolbar.reset")}
>
<RotateCcw className="size-3.5" />
{mapVisible && t("toolbar.reset")}
{!mapVisible && <span className="sr-only">{t("toolbar.reset")}</span>}
</Button>
}
/>
}
/>
<TooltipContent side="top">{t("toolbar.resetTooltip")}</TooltipContent>
</Tooltip>

<Toolbar.Button asChild>
<Button
size="sm"
className="h-7 shrink-0 gap-1.5 rounded-full px-2.5 text-xs"
onClick={finishEditing}
title={t("toolbar.done")}
>
<Check className="size-3.5" />
{mapVisible && t("toolbar.done")}
{!mapVisible && <span className="sr-only">{t("toolbar.done")}</span>}
</Button>
</Toolbar.Button>
</Toolbar.Root>
<ToolbarButton
render={
<Button
size="sm"
className="h-7 shrink-0 gap-1.5 rounded-full px-2.5 text-xs"
onClick={finishEditing}
title={t("toolbar.done")}
>
<Check className="size-3.5" />
{mapVisible && t("toolbar.done")}
{!mapVisible && <span className="sr-only">{t("toolbar.done")}</span>}
</Button>
}
/>
</Toolbar>
</m.div>
)}
</AnimatePresence>
Expand Down
75 changes: 40 additions & 35 deletions src/components/display/marker-toolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { m, AnimatePresence } from "motion/react"
import { MapPin, RotateCcw } from "lucide-react"
import { useCallback, useEffect, useState } from "react"
import * as Toolbar from "@radix-ui/react-toolbar"

import { Button } from "@/components/ui/button"
import { Toolbar, ToolbarButton } from "@/components/ui/toolbar"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
import { ColorPicker, ColorPickerHue, ColorPickerSelection } from "@/components/ui/color-picker"
Expand Down Expand Up @@ -62,25 +62,26 @@ function MarkerColorButton({ label, value, onChange }: MarkerColorButtonProps) {

return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<button
type="button"
className="inline-flex h-7 items-center gap-1.5 rounded-md border border-sidebar-border bg-background/50 px-2 text-[11px] font-medium text-muted-foreground transition-colors hover:text-foreground"
aria-label={label}
title={label}
>
<span
className="size-3.5 rounded-sm border border-sidebar-border"
style={{ backgroundColor: value }}
/>
<span className="font-mono uppercase">{value.replace("#", "")}</span>
</button>
</PopoverTrigger>
<PopoverTrigger
render={
<button
type="button"
className="inline-flex h-7 items-center gap-1.5 rounded-md border border-sidebar-border bg-background/50 px-2 text-[11px] font-medium text-muted-foreground transition-colors hover:text-foreground"
aria-label={label}
title={label}
>
<span
className="size-3.5 rounded-sm border border-sidebar-border"
style={{ backgroundColor: value }}
/>
<span className="font-mono uppercase">{value.replace("#", "")}</span>
</button>
}
/>
<PopoverContent
side="top"
align="center"
sideOffset={10}
collisionPadding={12}
className="z-[2300] w-64 rounded-lg border border-sidebar-border bg-popover p-4 shadow-2xl"
>
<ColorPicker value={value} onChange={handleChange} className="flex flex-col gap-3">
Expand Down Expand Up @@ -146,7 +147,7 @@ export function MarkerToolbar() {
className="pointer-events-none fixed inset-x-0 z-[2100] flex justify-center px-2 transition-[bottom,left] duration-500"
style={{ left: mapVisible ? sidebarWidth : 0, bottom: mapVisible ? 64 : 106 }}
>
<Toolbar.Root className="pointer-events-auto flex max-w-[calc(100vw-16px)] items-center gap-1 rounded-xl border border-sidebar-border bg-sidebar/95 px-2 py-1.5 shadow-lg backdrop-blur">
<Toolbar className="pointer-events-auto flex max-w-[calc(100vw-16px)] items-center gap-1 rounded-xl border border-sidebar-border bg-sidebar/95 px-2 py-1.5 shadow-lg backdrop-blur">
<div className="inline-flex items-center gap-1.5 px-1 text-[12px] font-medium">
<MapPin className="size-3.5 text-brand" />
<span>{t("marker.customizeTitle")}</span>
Expand Down Expand Up @@ -181,26 +182,30 @@ export function MarkerToolbar() {
</div>

<Tooltip>
<TooltipTrigger asChild>
<Toolbar.Button asChild>
<Button
variant="ghost"
size="icon"
className="size-7 rounded-md"
onClick={() => {
setMarkerColor(DEFAULT_MARKER_COLOR)
setMarkerBorderColor(DEFAULT_MARKER_BORDER)
setMarkerSize(DEFAULT_MARKER_SIZE)
}}
aria-label={t("selection.reset")}
>
<RotateCcw className="size-3.5" />
</Button>
</Toolbar.Button>
</TooltipTrigger>
<TooltipTrigger
render={
<ToolbarButton
render={
<Button
variant="ghost"
size="icon"
className="size-7 rounded-md"
onClick={() => {
setMarkerColor(DEFAULT_MARKER_COLOR)
setMarkerBorderColor(DEFAULT_MARKER_BORDER)
setMarkerSize(DEFAULT_MARKER_SIZE)
}}
aria-label={t("selection.reset")}
>
<RotateCcw className="size-3.5" />
</Button>
}
/>
}
/>
<TooltipContent side="top">{t("selection.reset")}</TooltipContent>
</Tooltip>
</Toolbar.Root>
</Toolbar>
</m.div>
)}
</AnimatePresence>
Expand Down
Loading
Loading