Polish workspace board settings
This commit is contained in:
parent
8b77dffec2
commit
e9a79b8280
|
|
@ -48,8 +48,6 @@ export default function WorkspaceKanbanDrawer({
|
|||
const updateWorktreesMeta = useAppStore((s) => s.updateWorktreesMeta)
|
||||
const workspaceStatuses = useAppStore((s) => s.workspaceStatuses)
|
||||
const setWorkspaceStatuses = useAppStore((s) => s.setWorkspaceStatuses)
|
||||
const workspaceBoardOpacity = useAppStore((s) => s.workspaceBoardOpacity)
|
||||
const setWorkspaceBoardOpacity = useAppStore((s) => s.setWorkspaceBoardOpacity)
|
||||
const workspaceBoardCompact = useAppStore((s) => s.workspaceBoardCompact)
|
||||
const setWorkspaceBoardCompact = useAppStore((s) => s.setWorkspaceBoardCompact)
|
||||
const workspaceBoardColumnWidth = useAppStore((s) => s.workspaceBoardColumnWidth)
|
||||
|
|
@ -219,13 +217,6 @@ export default function WorkspaceKanbanDrawer({
|
|||
onOpenChange(false)
|
||||
}, [onOpenChange])
|
||||
|
||||
const handleOpacityChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setWorkspaceBoardOpacity(Number(event.target.value) / 100)
|
||||
},
|
||||
[setWorkspaceBoardOpacity]
|
||||
)
|
||||
|
||||
const handleRenameStatus = useCallback(
|
||||
(statusId: string, label: string) => {
|
||||
const trimmed = label.trim()
|
||||
|
|
@ -341,7 +332,6 @@ export default function WorkspaceKanbanDrawer({
|
|||
return () => document.removeEventListener('pointerdown', clearSelectionOutsideBoard, true)
|
||||
}, [clearSelection, open, selectedWorktreeIds.size])
|
||||
|
||||
const opacityPercent = Math.round(workspaceBoardOpacity * 100)
|
||||
const drawerLeft = sidebarOpen ? sidebarWidth : 0
|
||||
const drawerLeftCss = sidebarOpen
|
||||
? `var(--workspace-sidebar-live-width, ${sidebarWidth}px)`
|
||||
|
|
@ -361,8 +351,7 @@ export default function WorkspaceKanbanDrawer({
|
|||
left: drawerLeftCss,
|
||||
top: 36,
|
||||
height: 'calc(100% - 36px)',
|
||||
width: `min(calc(100vw - ${drawerLeftCss}), 1294px)`,
|
||||
opacity: workspaceBoardOpacity
|
||||
width: `min(calc(100vw - ${drawerLeftCss}), 1294px)`
|
||||
} as React.CSSProperties
|
||||
}
|
||||
data-workspace-board-compact={workspaceBoardCompact ? 'true' : 'false'}
|
||||
|
|
@ -397,10 +386,8 @@ export default function WorkspaceKanbanDrawer({
|
|||
<WorkspaceKanbanDrawerHeader
|
||||
selectedCount={selectedWorktrees.length}
|
||||
compact={workspaceBoardCompact}
|
||||
opacityPercent={opacityPercent}
|
||||
workspaceStatuses={workspaceStatuses}
|
||||
onCompactChange={setWorkspaceBoardCompact}
|
||||
onOpacityChange={handleOpacityChange}
|
||||
onRenameStatus={handleRenameStatus}
|
||||
onChangeStatusColor={handleChangeStatusColor}
|
||||
onChangeStatusIcon={handleChangeStatusIcon}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import React from 'react'
|
||||
import { LayoutList, Rows3, X } from 'lucide-react'
|
||||
import { X } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { SheetClose, SheetDescription, SheetHeader, SheetTitle } from '@/components/ui/sheet'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
|
||||
import type { WorkspaceStatusDefinition } from '../../../../shared/types'
|
||||
import SidebarFilter from './SidebarFilter'
|
||||
import WorkspaceKanbanSettingsMenu from './WorkspaceKanbanSettingsMenu'
|
||||
|
|
@ -10,10 +9,8 @@ import WorkspaceKanbanSettingsMenu from './WorkspaceKanbanSettingsMenu'
|
|||
type WorkspaceKanbanDrawerHeaderProps = {
|
||||
selectedCount: number
|
||||
compact: boolean
|
||||
opacityPercent: number
|
||||
workspaceStatuses: readonly WorkspaceStatusDefinition[]
|
||||
onCompactChange: (compact: boolean) => void
|
||||
onOpacityChange: (event: React.ChangeEvent<HTMLInputElement>) => void
|
||||
onRenameStatus: (statusId: string, label: string) => void
|
||||
onChangeStatusColor: (statusId: string, color: string) => void
|
||||
onChangeStatusIcon: (statusId: string, icon: string) => void
|
||||
|
|
@ -26,10 +23,8 @@ type WorkspaceKanbanDrawerHeaderProps = {
|
|||
export default function WorkspaceKanbanDrawerHeader({
|
||||
selectedCount,
|
||||
compact,
|
||||
opacityPercent,
|
||||
workspaceStatuses,
|
||||
onCompactChange,
|
||||
onOpacityChange,
|
||||
onRenameStatus,
|
||||
onChangeStatusColor,
|
||||
onChangeStatusIcon,
|
||||
|
|
@ -38,8 +33,6 @@ export default function WorkspaceKanbanDrawerHeader({
|
|||
onAddStatus,
|
||||
onFilterMenuOpenChange
|
||||
}: WorkspaceKanbanDrawerHeaderProps): React.JSX.Element {
|
||||
const BoardModeIcon = compact ? Rows3 : LayoutList
|
||||
|
||||
return (
|
||||
<>
|
||||
<SheetHeader className="border-b border-sidebar-border px-4 py-3 pr-32">
|
||||
|
|
@ -63,27 +56,10 @@ export default function WorkspaceKanbanDrawerHeader({
|
|||
contentSide="bottom"
|
||||
onMenuOpenChange={onFilterMenuOpenChange}
|
||||
/>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
type="button"
|
||||
variant={compact ? 'secondary' : 'ghost'}
|
||||
size="icon-xs"
|
||||
aria-pressed={compact}
|
||||
aria-label={compact ? 'Compact workspace cards' : 'Detailed workspace cards'}
|
||||
onClick={() => onCompactChange(!compact)}
|
||||
>
|
||||
<BoardModeIcon className="size-3.5" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top" sideOffset={4}>
|
||||
{compact ? 'Show detailed cards' : 'Show compact cards'}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<WorkspaceKanbanSettingsMenu
|
||||
opacityPercent={opacityPercent}
|
||||
compact={compact}
|
||||
workspaceStatuses={workspaceStatuses}
|
||||
onOpacityChange={onOpacityChange}
|
||||
onCompactChange={onCompactChange}
|
||||
onRenameStatus={onRenameStatus}
|
||||
onChangeStatusColor={onChangeStatusColor}
|
||||
onChangeStatusIcon={onChangeStatusIcon}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import { ArrowDown, ArrowUp, Plus, Settings2, Trash2 } from 'lucide-react'
|
||||
import { ArrowDown, ArrowUp, LayoutList, Plus, Rows3, Settings, Trash2 } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
DropdownMenu,
|
||||
|
|
@ -8,15 +8,17 @@ import {
|
|||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
|
||||
import { cn } from '@/lib/utils'
|
||||
import type { WorkspaceStatusDefinition } from '../../../../shared/types'
|
||||
import { getWorkspaceStatusVisualMeta } from './workspace-status'
|
||||
import WorkspaceStatusAppearancePopover from './WorkspaceStatusAppearancePopover'
|
||||
|
||||
type WorkspaceKanbanSettingsMenuProps = {
|
||||
opacityPercent: number
|
||||
compact: boolean
|
||||
workspaceStatuses: readonly WorkspaceStatusDefinition[]
|
||||
onOpacityChange: (event: React.ChangeEvent<HTMLInputElement>) => void
|
||||
onCompactChange: (compact: boolean) => void
|
||||
onRenameStatus: (statusId: string, label: string) => void
|
||||
onChangeStatusColor: (statusId: string, color: string) => void
|
||||
onChangeStatusIcon: (statusId: string, icon: string) => void
|
||||
|
|
@ -26,9 +28,9 @@ type WorkspaceKanbanSettingsMenuProps = {
|
|||
}
|
||||
|
||||
export default function WorkspaceKanbanSettingsMenu({
|
||||
opacityPercent,
|
||||
compact,
|
||||
workspaceStatuses,
|
||||
onOpacityChange,
|
||||
onCompactChange,
|
||||
onRenameStatus,
|
||||
onChangeStatusColor,
|
||||
onChangeStatusIcon,
|
||||
|
|
@ -38,14 +40,27 @@ export default function WorkspaceKanbanSettingsMenu({
|
|||
}: WorkspaceKanbanSettingsMenuProps): React.JSX.Element {
|
||||
return (
|
||||
<DropdownMenu modal={false}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon-xs" aria-label="Workspace board settings">
|
||||
<Settings2 className="size-3.5" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
aria-label="Workspace board settings"
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
<Settings className="size-3.5" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top" sideOffset={4}>
|
||||
Board settings
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<DropdownMenuContent
|
||||
align="end"
|
||||
sideOffset={8}
|
||||
collisionPadding={8}
|
||||
className="max-h-[min(80vh,720px)] w-80 overflow-y-auto p-2 scrollbar-sleek"
|
||||
onInteractOutside={(event) => {
|
||||
const target = event.target
|
||||
|
|
@ -57,21 +72,37 @@ export default function WorkspaceKanbanSettingsMenu({
|
|||
}
|
||||
}}
|
||||
>
|
||||
<DropdownMenuLabel>Board opacity</DropdownMenuLabel>
|
||||
<DropdownMenuLabel>Card density</DropdownMenuLabel>
|
||||
<div className="px-2 pb-2">
|
||||
<div className="mb-1 flex items-center justify-between text-[11px] text-muted-foreground">
|
||||
<span>Pane opacity</span>
|
||||
<span>{opacityPercent}%</span>
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min={20}
|
||||
max={100}
|
||||
value={opacityPercent}
|
||||
onChange={onOpacityChange}
|
||||
className="h-5 w-full accent-foreground"
|
||||
aria-label="Workspace board opacity"
|
||||
/>
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
value={compact ? 'compact' : 'detailed'}
|
||||
onValueChange={(value) => {
|
||||
if (value) {
|
||||
onCompactChange(value === 'compact')
|
||||
}
|
||||
}}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-7 w-full justify-stretch"
|
||||
>
|
||||
<ToggleGroupItem
|
||||
value="detailed"
|
||||
className="h-7 grow basis-0 gap-1.5 px-1.5 text-[11px] data-[state=on]:bg-foreground/10 data-[state=on]:font-semibold data-[state=on]:text-foreground"
|
||||
aria-label="Detailed workspace cards"
|
||||
>
|
||||
<LayoutList className="size-3.5" />
|
||||
Detailed
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem
|
||||
value="compact"
|
||||
className="h-7 grow basis-0 gap-1.5 px-1.5 text-[11px] data-[state=on]:bg-foreground/10 data-[state=on]:font-semibold data-[state=on]:text-foreground"
|
||||
aria-label="Compact workspace cards"
|
||||
>
|
||||
<Rows3 className="size-3.5" />
|
||||
Compact
|
||||
</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</div>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuLabel>Statuses</DropdownMenuLabel>
|
||||
|
|
|
|||
Loading…
Reference in New Issue