fix: keep saved view reorder UI native
This commit is contained in:
@@ -1384,31 +1384,20 @@ describe('Sidebar', () => {
|
||||
},
|
||||
]
|
||||
|
||||
it('renders keyboard-accessible move buttons for saved views', () => {
|
||||
const onMoveView = vi.fn()
|
||||
it('does not add visible reorder controls to saved view rows', () => {
|
||||
render(
|
||||
<Sidebar
|
||||
entries={mockEntries}
|
||||
selection={defaultSelection}
|
||||
onSelect={() => {}}
|
||||
views={mockViews}
|
||||
onMoveView={onMoveView}
|
||||
onReorderViews={vi.fn()}
|
||||
/>
|
||||
)
|
||||
|
||||
const moveUpButtons = screen.getAllByTitle('Move view up')
|
||||
const moveDownButtons = screen.getAllByTitle('Move view down')
|
||||
|
||||
expect(moveUpButtons[0]).toBeDisabled()
|
||||
expect(moveUpButtons[1]).not.toBeDisabled()
|
||||
expect(moveDownButtons[0]).not.toBeDisabled()
|
||||
expect(moveDownButtons[1]).toBeDisabled()
|
||||
|
||||
fireEvent.click(moveUpButtons[1])
|
||||
expect(onMoveView).toHaveBeenCalledWith('all-topics.yml', 'up')
|
||||
|
||||
fireEvent.click(moveDownButtons[0])
|
||||
expect(onMoveView).toHaveBeenCalledWith('active-projects.yml', 'down')
|
||||
expect(screen.queryByTitle('Move view up')).not.toBeInTheDocument()
|
||||
expect(screen.queryByTitle('Move view down')).not.toBeInTheDocument()
|
||||
expect(screen.queryByTitle('Reorder view')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('shows note count chip for each view matching the filter results', () => {
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
import { useSidebarTypeInteractions } from './sidebar/useSidebarTypeInteractions'
|
||||
import type { AppLocale } from '../lib/i18n'
|
||||
import type { FolderFileActions } from '../hooks/useFileActions'
|
||||
import type { ViewMoveDirection } from '../utils/viewOrdering'
|
||||
|
||||
interface SidebarProps {
|
||||
entries: VaultEntry[]
|
||||
@@ -45,7 +44,6 @@ interface SidebarProps {
|
||||
onEditView?: (filename: string) => void
|
||||
onDeleteView?: (filename: string) => void
|
||||
onReorderViews?: (orderedFilenames: string[]) => void
|
||||
onMoveView?: (filename: string, direction: ViewMoveDirection) => void
|
||||
folders?: FolderNode[]
|
||||
onCreateFolder?: (name: string) => Promise<boolean> | boolean
|
||||
onRenameFolder?: (folderPath: string, nextName: string) => Promise<boolean> | boolean
|
||||
@@ -72,7 +70,6 @@ interface SidebarNavigationProps extends Pick<
|
||||
| 'onEditView'
|
||||
| 'onDeleteView'
|
||||
| 'onReorderViews'
|
||||
| 'onMoveView'
|
||||
| 'folders'
|
||||
| 'onCreateFolder'
|
||||
| 'onRenameFolder'
|
||||
@@ -112,7 +109,6 @@ function SidebarNavigation({
|
||||
onEditView,
|
||||
onDeleteView,
|
||||
onReorderViews,
|
||||
onMoveView,
|
||||
folders = [],
|
||||
onCreateFolder,
|
||||
onRenameFolder,
|
||||
@@ -178,7 +174,6 @@ function SidebarNavigation({
|
||||
onEditView={onEditView}
|
||||
onDeleteView={onDeleteView}
|
||||
onReorderViews={onReorderViews}
|
||||
onMoveView={onMoveView}
|
||||
sensors={sensors}
|
||||
entries={entries}
|
||||
locale={locale}
|
||||
@@ -243,7 +238,6 @@ export const Sidebar = memo(function Sidebar({
|
||||
onEditView,
|
||||
onDeleteView,
|
||||
onReorderViews,
|
||||
onMoveView,
|
||||
folders = [],
|
||||
onCreateFolder,
|
||||
onRenameFolder,
|
||||
@@ -280,7 +274,7 @@ export const Sidebar = memo(function Sidebar({
|
||||
const reordered = computeReorder(sectionIds, active.id as string, over.id as string)
|
||||
if (reordered) onReorderSections?.(reordered.map((typeName, order) => ({ typeName, order })))
|
||||
}, [sectionIds, onReorderSections])
|
||||
const viewActions = { onCreateView, onEditView, onDeleteView, onReorderViews, onMoveView }
|
||||
const viewActions = { onCreateView, onEditView, onDeleteView, onReorderViews }
|
||||
|
||||
const sectionProps: SidebarSectionProps = {
|
||||
entries,
|
||||
|
||||
@@ -24,7 +24,6 @@ import { SidebarViewItem } from './SidebarViewItem'
|
||||
import { computeReorder } from './sidebarHooks'
|
||||
import { countByFilter } from '../../utils/noteListHelpers'
|
||||
import { translate, type AppLocale } from '../../lib/i18n'
|
||||
import { canMoveView, type ViewMoveDirection } from '../../utils/viewOrdering'
|
||||
|
||||
export { SidebarTopNav } from './SidebarTopNav'
|
||||
export { FavoritesSection } from './FavoritesSection'
|
||||
@@ -51,7 +50,6 @@ export function ViewsSection({
|
||||
onEditView,
|
||||
onDeleteView,
|
||||
onReorderViews,
|
||||
onMoveView,
|
||||
sensors,
|
||||
entries,
|
||||
locale = 'en',
|
||||
@@ -65,7 +63,6 @@ export function ViewsSection({
|
||||
onEditView?: (filename: string) => void
|
||||
onDeleteView?: (filename: string) => void
|
||||
onReorderViews?: (orderedFilenames: string[]) => void
|
||||
onMoveView?: (filename: string, direction: ViewMoveDirection) => void
|
||||
sensors: ReturnType<typeof useSensors>
|
||||
entries: VaultEntry[]
|
||||
locale?: AppLocale
|
||||
@@ -85,9 +82,6 @@ export function ViewsSection({
|
||||
onSelect={() => onSelect({ kind: 'view', filename: view.filename })}
|
||||
onEditView={onEditView}
|
||||
onDeleteView={onDeleteView}
|
||||
onMoveView={onMoveView}
|
||||
canMoveUp={canMoveView(views, view.filename, 'up')}
|
||||
canMoveDown={canMoveView(views, view.filename, 'down')}
|
||||
entries={entries}
|
||||
locale={locale}
|
||||
/>
|
||||
@@ -119,12 +113,10 @@ export function ViewsSection({
|
||||
<SortableViewItem
|
||||
key={view.filename}
|
||||
view={view}
|
||||
views={views}
|
||||
selection={selection}
|
||||
onSelect={onSelect}
|
||||
onEditView={onEditView}
|
||||
onDeleteView={onDeleteView}
|
||||
onMoveView={onMoveView}
|
||||
entries={entries}
|
||||
locale={locale}
|
||||
/>
|
||||
@@ -140,22 +132,18 @@ export function ViewsSection({
|
||||
|
||||
function SortableViewItem({
|
||||
view,
|
||||
views,
|
||||
selection,
|
||||
onSelect,
|
||||
onEditView,
|
||||
onDeleteView,
|
||||
onMoveView,
|
||||
entries,
|
||||
locale,
|
||||
}: {
|
||||
view: ViewFile
|
||||
views: ViewFile[]
|
||||
selection: SidebarSelection
|
||||
onSelect: (selection: SidebarSelection) => void
|
||||
onEditView?: (filename: string) => void
|
||||
onDeleteView?: (filename: string) => void
|
||||
onMoveView?: (filename: string, direction: ViewMoveDirection) => void
|
||||
entries: VaultEntry[]
|
||||
locale?: AppLocale
|
||||
}) {
|
||||
@@ -164,6 +152,7 @@ function SortableViewItem({
|
||||
return (
|
||||
<div
|
||||
ref={setNodeRef}
|
||||
{...attributes}
|
||||
style={{
|
||||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
@@ -176,10 +165,7 @@ function SortableViewItem({
|
||||
onSelect={() => onSelect({ kind: 'view', filename: view.filename })}
|
||||
onEditView={onEditView}
|
||||
onDeleteView={onDeleteView}
|
||||
onMoveView={onMoveView}
|
||||
canMoveUp={canMoveView(views, view.filename, 'up')}
|
||||
canMoveDown={canMoveView(views, view.filename, 'down')}
|
||||
dragHandleProps={{ ...attributes, ...listeners }}
|
||||
dragHandleProps={listeners}
|
||||
entries={entries}
|
||||
locale={locale}
|
||||
/>
|
||||
|
||||
@@ -2,13 +2,11 @@ import { useMemo, type HTMLAttributes } from 'react'
|
||||
import type { VaultEntry, ViewFile } from '../../types'
|
||||
import { evaluateView } from '../../utils/viewFilters'
|
||||
import { Funnel, PencilSimple, Trash } from '@phosphor-icons/react'
|
||||
import { ArrowDown, ArrowUp, GripVertical } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { NoteTitleIcon } from '../NoteTitleIcon'
|
||||
import { SidebarCountPill } from '../SidebarParts'
|
||||
import { SIDEBAR_ITEM_PADDING } from './sidebarStyles'
|
||||
import { translate, type AppLocale } from '../../lib/i18n'
|
||||
import type { ViewMoveDirection } from '../../utils/viewOrdering'
|
||||
import { ACCENT_COLORS } from '../../utils/typeColors'
|
||||
|
||||
interface ViewAccent {
|
||||
@@ -22,10 +20,7 @@ interface SidebarViewItemProps {
|
||||
onSelect: () => void
|
||||
onEditView?: (filename: string) => void
|
||||
onDeleteView?: (filename: string) => void
|
||||
onMoveView?: (filename: string, direction: ViewMoveDirection) => void
|
||||
canMoveUp?: boolean
|
||||
canMoveDown?: boolean
|
||||
dragHandleProps?: HTMLAttributes<HTMLButtonElement>
|
||||
dragHandleProps?: HTMLAttributes<HTMLDivElement>
|
||||
entries: VaultEntry[]
|
||||
locale?: AppLocale
|
||||
}
|
||||
@@ -88,9 +83,6 @@ export function SidebarViewItem({
|
||||
onSelect,
|
||||
onEditView,
|
||||
onDeleteView,
|
||||
onMoveView,
|
||||
canMoveUp = false,
|
||||
canMoveDown = false,
|
||||
dragHandleProps,
|
||||
entries,
|
||||
locale = 'en',
|
||||
@@ -105,54 +97,13 @@ export function SidebarViewItem({
|
||||
className={`flex cursor-pointer select-none items-center gap-2 rounded transition-colors ${isActive ? 'bg-primary/10 text-primary' : 'text-foreground hover:bg-accent'}`}
|
||||
style={getViewRowStyle(showCount, isActive, accent)}
|
||||
onClick={onSelect}
|
||||
{...dragHandleProps}
|
||||
>
|
||||
{dragHandleProps && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className="-ml-1 h-5 w-4 min-w-0 cursor-grab rounded p-0 text-muted-foreground hover:bg-transparent hover:text-foreground active:cursor-grabbing"
|
||||
title={translate(locale, 'sidebar.action.reorderView')}
|
||||
aria-label={translate(locale, 'sidebar.action.reorderView')}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
{...dragHandleProps}
|
||||
>
|
||||
<GripVertical size={12} />
|
||||
</Button>
|
||||
)}
|
||||
<ViewIcon icon={view.definition.icon} isActive={isActive} accent={accent} />
|
||||
<span className="min-w-0 flex-1 truncate text-[13px] font-medium">{view.definition.name}</span>
|
||||
<ViewCountChip count={count} isActive={isActive} accent={accent} />
|
||||
</div>
|
||||
<div className="pointer-events-none absolute right-2 top-1/2 flex -translate-y-1/2 items-center gap-0.5 opacity-0 transition-opacity group-hover:pointer-events-auto group-hover:opacity-100 group-focus-within:pointer-events-auto group-focus-within:opacity-100">
|
||||
{onMoveView && (
|
||||
<>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className="h-5 w-5 min-w-0 rounded p-0 text-muted-foreground hover:bg-transparent hover:text-foreground disabled:opacity-30"
|
||||
disabled={!canMoveUp}
|
||||
onClick={(event) => { event.stopPropagation(); onMoveView(view.filename, 'up') }}
|
||||
title={translate(locale, 'sidebar.action.moveViewUp')}
|
||||
aria-label={translate(locale, 'sidebar.action.moveViewUp')}
|
||||
>
|
||||
<ArrowUp size={12} />
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className="h-5 w-5 min-w-0 rounded p-0 text-muted-foreground hover:bg-transparent hover:text-foreground disabled:opacity-30"
|
||||
disabled={!canMoveDown}
|
||||
onClick={(event) => { event.stopPropagation(); onMoveView(view.filename, 'down') }}
|
||||
title={translate(locale, 'sidebar.action.moveViewDown')}
|
||||
aria-label={translate(locale, 'sidebar.action.moveViewDown')}
|
||||
>
|
||||
<ArrowDown size={12} />
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{onEditView && (
|
||||
<Button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user