feat: switcher
This commit is contained in:
@@ -9,7 +9,6 @@ import { RecollectionMenubarProvider } from './RecollectionMenubarContext'
|
|||||||
import { RecollectionActionsProvider } from './RecollectionActionsContext'
|
import { RecollectionActionsProvider } from './RecollectionActionsContext'
|
||||||
import { RecollectionTitleContent } from './RecollectionTitleContent'
|
import { RecollectionTitleContent } from './RecollectionTitleContent'
|
||||||
import { RecollectionMenubar } from './RecollectionMenubar'
|
import { RecollectionMenubar } from './RecollectionMenubar'
|
||||||
import { RecollectionViewSwitcher } from './RecollectionViewSwitcher'
|
|
||||||
import { FlippingCardView } from './FlippingCardView'
|
import { FlippingCardView } from './FlippingCardView'
|
||||||
|
|
||||||
export function RecollectionLayout() {
|
export function RecollectionLayout() {
|
||||||
@@ -38,12 +37,11 @@ export function RecollectionLayout() {
|
|||||||
<RecollectionMenubarProvider>
|
<RecollectionMenubarProvider>
|
||||||
<RecollectionActionsProvider>
|
<RecollectionActionsProvider>
|
||||||
<RecollectionTitleContent />
|
<RecollectionTitleContent />
|
||||||
<div className="relative flex min-h-0 flex-1 flex-col">
|
<div className="flex min-h-0 flex-1 flex-col">
|
||||||
<RecollectionMenubar />
|
<RecollectionMenubar />
|
||||||
<div className="flex min-h-0 flex-1 flex-col overflow-hidden">
|
<div className="flex min-h-0 flex-1 flex-col overflow-hidden">
|
||||||
<FlippingCardView />
|
<FlippingCardView />
|
||||||
</div>
|
</div>
|
||||||
<RecollectionViewSwitcher />
|
|
||||||
</div>
|
</div>
|
||||||
</RecollectionActionsProvider>
|
</RecollectionActionsProvider>
|
||||||
</RecollectionMenubarProvider>
|
</RecollectionMenubarProvider>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { usePlatform } from '@/app/kosmos/KosmosContext'
|
|||||||
import { ArrowLeft } from 'lucide-react'
|
import { ArrowLeft } from 'lucide-react'
|
||||||
import { useRecollectionMenubar } from './RecollectionMenubarContext'
|
import { useRecollectionMenubar } from './RecollectionMenubarContext'
|
||||||
import { RecollectionEditViewMenus } from './RecollectionEditViewMenus'
|
import { RecollectionEditViewMenus } from './RecollectionEditViewMenus'
|
||||||
|
import { RecollectionViewSwitcher } from './RecollectionViewSwitcher'
|
||||||
|
|
||||||
export function RecollectionMenubar() {
|
export function RecollectionMenubar() {
|
||||||
const { recollectionId } = useParams<{ recollectionId: string }>()
|
const { recollectionId } = useParams<{ recollectionId: string }>()
|
||||||
@@ -34,6 +35,7 @@ export function RecollectionMenubar() {
|
|||||||
<div className="flex min-w-0 flex-1 items-center gap-1 overflow-visible">
|
<div className="flex min-w-0 flex-1 items-center gap-1 overflow-visible">
|
||||||
<RecollectionEditViewMenus />
|
<RecollectionEditViewMenus />
|
||||||
</div>
|
</div>
|
||||||
|
<RecollectionViewSwitcher />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* Elevator-style view switcher: circular button moves between top (Logos) and bottom (Flux).
|
* Circular view switcher: icon and title use the same vertical elevator-style animation.
|
||||||
* Click toggles; shortcut and tooltip on hover.
|
* Click toggles; tooltip includes shortcut.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useEffect } from 'react'
|
import React, { useCallback, useEffect } from 'react'
|
||||||
import { useLocation, useNavigate, useParams } from 'react-router-dom'
|
import { useLocation, useNavigate, useParams } from 'react-router-dom'
|
||||||
import { usePlatform } from '@/app/kosmos/KosmosContext'
|
|
||||||
import { FluxIcon, LogosIcon } from '@/lib/icons'
|
import { FluxIcon, LogosIcon } from '@/lib/icons'
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
||||||
import { Kbd } from '@/components/ui/kbd'
|
|
||||||
|
|
||||||
const VIEW_TOGGLE_KEYS = { key: 'v', shiftKey: true }
|
const VIEW_TOGGLE_KEYS = { key: 'v', shiftKey: true }
|
||||||
|
|
||||||
@@ -21,7 +19,7 @@ function shortcutLabel() {
|
|||||||
if (typeof navigator !== 'undefined' && /Mac|iPod|iPhone|iPad/.test(navigator.platform)) {
|
if (typeof navigator !== 'undefined' && /Mac|iPod|iPhone|iPad/.test(navigator.platform)) {
|
||||||
return '⌘⇧V'
|
return '⌘⇧V'
|
||||||
}
|
}
|
||||||
return 'Ctrl+⇧+V'
|
return 'Ctrl+Shift+V'
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RecollectionViewSwitcher() {
|
export function RecollectionViewSwitcher() {
|
||||||
@@ -50,12 +48,13 @@ export function RecollectionViewSwitcher() {
|
|||||||
|
|
||||||
if (!base) return null
|
if (!base) return null
|
||||||
|
|
||||||
|
const shortcut = shortcutLabel()
|
||||||
const tooltipText = isFlux
|
const tooltipText = isFlux
|
||||||
? `Switch to Logos`
|
? `Flux · Switch to Logos (${shortcut})`
|
||||||
: `Switch to Flux`
|
: `Logos · Switch to Flux (${shortcut})`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="absolute left-1/2 top-[18px] z-10 flex -translate-x-1/2 -translate-y-1/2 items-center gap-2">
|
<div className="flex shrink-0 items-center gap-2">
|
||||||
<TooltipProvider delayDuration={300}>
|
<TooltipProvider delayDuration={300}>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
@@ -63,26 +62,42 @@ export function RecollectionViewSwitcher() {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={toggle}
|
onClick={toggle}
|
||||||
aria-label={isFlux ? 'Switch to Logos' : 'Switch to Flux'}
|
aria-label={isFlux ? 'Switch to Logos' : 'Switch to Flux'}
|
||||||
className="flex items-center gap-2 rounded-full border border-border/60 bg-background shadow-md transition-colors hover:bg-accent hover:text-accent-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
className="h-7 w-7 shrink-0 overflow-hidden rounded-full border border-border/60 bg-background shadow-md transition-colors hover:bg-accent hover:text-accent-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||||
>
|
>
|
||||||
<div className="relative h-14 w-8 rounded-full bg-muted/50 p-0.5">
|
<div className="h-full w-full overflow-hidden">
|
||||||
<span
|
<div
|
||||||
className="absolute left-1/2 flex h-6 w-6 -translate-x-1/2 items-center justify-center rounded-full border bg-background shadow-sm transition-[top] duration-200 ease-out"
|
className="flex w-full flex-col transition-transform duration-200 ease-out"
|
||||||
style={{ top: isFlux ? 28 : 4 }}
|
style={{
|
||||||
|
height: '200%',
|
||||||
|
transform: isFlux ? 'translateY(-50%)' : 'translateY(0)',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{isFlux ? (
|
<div className="flex h-9 w-full items-center justify-center">
|
||||||
<FluxIcon className="size-3.5 text-muted-foreground" />
|
<LogosIcon className="size-3.5 shrink-0 text-muted-foreground" />
|
||||||
) : (
|
</div>
|
||||||
<LogosIcon className="size-3.5 text-muted-foreground" />
|
<div className="flex h-9 w-full items-center justify-center">
|
||||||
)}
|
<FluxIcon className="size-3.5 shrink-0 text-muted-foreground" />
|
||||||
</span>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent side="bottom">{tooltipText}</TooltipContent>
|
<TooltipContent side="bottom">{tooltipText}</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
<Kbd className="text-[10px]">{shortcutLabel()}</Kbd>
|
<div className="h-9 min-w-[3.5rem] overflow-hidden">
|
||||||
|
<div
|
||||||
|
className="flex w-full flex-col transition-transform duration-200 ease-out"
|
||||||
|
style={{ transform: isFlux ? 'translateY(-50%)' : 'translateY(0)' }}
|
||||||
|
>
|
||||||
|
<span className="flex h-9 flex-shrink-0 items-center text-sm font-medium text-foreground">
|
||||||
|
Logos
|
||||||
|
</span>
|
||||||
|
<span className="flex h-9 flex-shrink-0 items-center text-sm font-medium text-foreground">
|
||||||
|
Flux
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user