feat: UX improvements — copy buttons, shortcuts modal, breadcrumb rewind, create tree CTA

- Add copy-to-clipboard buttons on command blocks (action + custom step nodes)
- Add keyboard shortcuts modal (?) with option loading spinners and [Esc] hint
- Restyle session timer as a pill badge for better visibility
- Add prominent "Create Tree" CTA to MyTreesPage header and empty state
- Make breadcrumb items clickable to rewind navigation to any previous step

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-02-13 02:19:24 -05:00
parent ad59446332
commit 2fc4e69c38
3 changed files with 182 additions and 46 deletions

View File

@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react'
import { useNavigate, Link } from 'react-router-dom'
import { Play, Pencil, Share2, Trash2, GitBranch, Clock, TrendingUp, FolderTree } from 'lucide-react'
import { Play, Pencil, Share2, Trash2, GitBranch, Clock, TrendingUp, FolderTree, Plus } from 'lucide-react'
import { treesApi } from '@/api/trees'
import { sessionsApi } from '@/api/sessions'
import type { TreeListItem } from '@/types'
@@ -22,7 +22,7 @@ interface TreeWithStats extends TreeListItem {
export function MyTreesPage() {
const navigate = useNavigate()
const { user } = useAuthStore()
const { canEditTree } = usePermissions()
const { canEditTree, canCreateTrees } = usePermissions()
const [trees, setTrees] = useState<TreeWithStats[]>([])
const [isLoading, setIsLoading] = useState(true)
const [treeToDelete, setTreeToDelete] = useState<TreeWithStats | null>(null)
@@ -101,11 +101,22 @@ export function MyTreesPage() {
return (
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
<div className="mb-6 sm:mb-8">
<h1 className="text-2xl font-bold text-white sm:text-3xl">My Trees</h1>
<p className="mt-2 text-white/40">
Your forked and custom decision trees
</p>
<div className="mb-6 flex items-center justify-between sm:mb-8">
<div>
<h1 className="text-2xl font-bold text-white sm:text-3xl">My Trees</h1>
<p className="mt-2 text-white/40">
Your forked and custom decision trees
</p>
</div>
{canCreateTrees && (
<Link
to="/trees/new"
className="flex items-center gap-2 rounded-md bg-white px-4 py-2 text-sm font-medium text-black hover:bg-white/90"
>
<Plus className="h-4 w-4" />
Create Tree
</Link>
)}
</div>
{/* Loading State */}
@@ -120,15 +131,29 @@ export function MyTreesPage() {
<p className="mb-4 text-sm text-white/40">
Fork a tree from the library to customize it for your workflow
</p>
<Link
to="/trees"
className={cn(
'inline-flex items-center gap-2 rounded-md bg-white px-4 py-2 text-sm font-medium text-black',
'hover:bg-white/90'
<div className="flex items-center justify-center gap-3">
<Link
to="/trees"
className={cn(
'inline-flex items-center gap-2 rounded-md bg-white px-4 py-2 text-sm font-medium text-black',
'hover:bg-white/90'
)}
>
Browse Library
</Link>
{canCreateTrees && (
<Link
to="/trees/new"
className={cn(
'inline-flex items-center gap-2 rounded-md border border-white/10 px-4 py-2 text-sm font-medium text-white/60',
'hover:bg-white/10 hover:text-white'
)}
>
<Plus className="h-4 w-4" />
Create from Scratch
</Link>
)}
>
Browse Trees
</Link>
</div>
</div>
) : (
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">