Skip to content

Commit ea991c2

Browse files
committed
feat: directory loading & error states
1 parent 165c2f0 commit ea991c2

2 files changed

Lines changed: 51 additions & 19 deletions

File tree

src/features/dashboard/sandbox/inspect/dir.tsx

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { FilesystemNode } from './filesystem/types'
2+
import type { CSSProperties } from 'react'
23
import { ChevronRight } from 'lucide-react'
34
import SandboxInspectNode from './node'
45
import { useDirectory } from './hooks/use-directory'
56
import { cn } from '@/lib/utils'
6-
import { Loader } from '@/ui/loader'
77
import { DataTableRow } from '@/ui/data-table'
88
import { motion } from 'motion/react'
99
import { FileType } from 'e2b'
@@ -15,40 +15,59 @@ interface SandboxInspectDirProps {
1515
}
1616

1717
export default function SandboxInspectDir({ dir }: SandboxInspectDirProps) {
18-
const { isExpanded, toggle, isLoading, hasChildren, children } = useDirectory(
19-
dir.path
20-
)
18+
const {
19+
hasError,
20+
error,
21+
isExpanded,
22+
toggle,
23+
isLoading,
24+
isLoaded,
25+
hasChildren,
26+
children,
27+
} = useDirectory(dir.path)
2128

2229
return (
2330
<>
2431
<DataTableRow
2532
role="button"
2633
tabIndex={0}
27-
onClick={() => toggle()}
28-
onKeyDown={(e) => {
29-
if (e.key === 'Enter' || e.key === ' ') {
30-
toggle()
31-
}
32-
}}
34+
onClick={toggle}
3335
className={cn(
34-
'hover:bg-bg-200 cursor-pointer gap-1 py-1 transition-none select-none',
35-
{
36-
'animate-pulse': isLoading,
37-
}
36+
'hover:bg-bg-200 cursor-pointer gap-1 truncate py-1 transition-none select-none'
3837
)}
3938
>
4039
<motion.span
4140
animate={{
42-
rotate: isExpanded ? 90 : 0,
41+
rotate: isExpanded && isLoaded ? 90 : 0,
42+
color:
43+
isExpanded && isLoaded
44+
? 'var(--color-fg)'
45+
: 'var(--color-fg-500)',
4346
}}
4447
>
45-
<ChevronRight className="text-fg-300 size-4" />
48+
<ChevronRight className="size-4" />
4649
</motion.span>
47-
<span className="text-left font-sans">{dir.name}</span>
48-
{isLoading && <Loader className="ml-2" />}
50+
<span
51+
style={{ '--shiny-width': '100px' } as CSSProperties}
52+
className={cn('truncate text-left font-sans', {
53+
// Shine effect
54+
'text-fg-500 animate-shiny-text [background-size:var(--shiny-width)_100%] bg-clip-text [background-position:0_0] bg-no-repeat duration-1000 [transition:background-position_1s_ease-in-out]':
55+
isLoading,
56+
// Shine gradient
57+
'bg-gradient-to-r from-transparent via-[var(--color-fg)] via-50% to-transparent':
58+
isLoading,
59+
})}
60+
>
61+
{dir.name}
62+
</span>
63+
{hasError && (
64+
<span className="text-error truncate text-sm text-ellipsis">
65+
{error}
66+
</span>
67+
)}
4968
</DataTableRow>
5069

51-
{isExpanded && (
70+
{isExpanded && hasChildren && (
5271
<div className="flex flex-col pl-2">
5372
{children.map((child) => (
5473
<SandboxInspectNode key={child.path} path={child.path} />

src/styles/theme.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,25 @@
154154
}
155155
}
156156

157+
@keyframes shiny-text {
158+
0%,
159+
90%,
160+
100% {
161+
background-position: calc(-100% - var(--shiny-width)) 0;
162+
}
163+
30%,
164+
60% {
165+
background-position: calc(100% + var(--shiny-width)) 0;
166+
}
167+
}
168+
157169
--animate-accordion-down: accordion-down 0.2s ease-out;
158170
--animate-accordion-up: accordion-up 0.2s ease-out;
159171
--animate-shimmer: shimmer 1s ease-in-out infinite;
160172
--animate-grid: grid 30s linear infinite;
161173
--animate-wave: wave 2s linear linear infinite;
162174
--animate-fade-slide-in: fade-slide-in-from-bottom 0.1s cubic-bezier(0.16, 1, 0.3, 1);
175+
--animate-shiny-text: shiny-text 0.8s infinite;
163176
}
164177

165178
@utility container {

0 commit comments

Comments
 (0)