feat(ui): enhance timeline sidebar with slide-in animation and responsive layout
- Add slide-in animation to timeline sidebar using framer-motion - Implement responsive layout adjustments for main content area - Add proper timeline header with close button - Fix floating prompt input positioning to accommodate timeline - Reorder CSS imports for proper style precedence - Fix animation scaling issue in rotating symbol keyframes The timeline now slides in from the right with a smooth spring animation and properly adjusts the main content area width on larger screens.
This commit is contained in:
@@ -1076,7 +1076,10 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
|
|||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Main Content Area */}
|
{/* Main Content Area */}
|
||||||
<div className="flex-1 overflow-hidden">
|
<div className={cn(
|
||||||
|
"flex-1 overflow-hidden transition-all duration-300",
|
||||||
|
showTimeline && "sm:mr-96"
|
||||||
|
)}>
|
||||||
{showPreview ? (
|
{showPreview ? (
|
||||||
// Split pane layout when preview is active
|
// Split pane layout when preview is active
|
||||||
<SplitPane
|
<SplitPane
|
||||||
@@ -1241,6 +1244,10 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
|
|||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<div className={cn(
|
||||||
|
"fixed bottom-0 left-0 right-0 transition-all duration-300 z-50",
|
||||||
|
showTimeline && "sm:right-96"
|
||||||
|
)}>
|
||||||
<FloatingPromptInput
|
<FloatingPromptInput
|
||||||
ref={floatingPromptRef}
|
ref={floatingPromptRef}
|
||||||
onSend={handleSendPrompt}
|
onSend={handleSendPrompt}
|
||||||
@@ -1249,6 +1256,7 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
|
|||||||
disabled={!projectPath}
|
disabled={!projectPath}
|
||||||
projectPath={projectPath}
|
projectPath={projectPath}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Token Counter - positioned under the Send button */}
|
{/* Token Counter - positioned under the Send button */}
|
||||||
{totalTokens > 0 && (
|
{totalTokens > 0 && (
|
||||||
@@ -1274,7 +1282,31 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
|
|||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
|
||||||
{/* Timeline */}
|
{/* Timeline */}
|
||||||
|
<AnimatePresence>
|
||||||
{showTimeline && effectiveSession && (
|
{showTimeline && effectiveSession && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ x: "100%" }}
|
||||||
|
animate={{ x: 0 }}
|
||||||
|
exit={{ x: "100%" }}
|
||||||
|
transition={{ type: "spring", damping: 20, stiffness: 300 }}
|
||||||
|
className="fixed right-0 top-0 h-full w-full sm:w-96 bg-background border-l border-border shadow-xl z-30 overflow-hidden"
|
||||||
|
>
|
||||||
|
<div className="h-full flex flex-col">
|
||||||
|
{/* Timeline Header */}
|
||||||
|
<div className="flex items-center justify-between p-4 border-b border-border">
|
||||||
|
<h3 className="text-lg font-semibold">Session Timeline</h3>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => setShowTimeline(false)}
|
||||||
|
className="h-8 w-8"
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Timeline Content */}
|
||||||
|
<div className="flex-1 overflow-y-auto p-4">
|
||||||
<TimelineNavigator
|
<TimelineNavigator
|
||||||
sessionId={effectiveSession.id}
|
sessionId={effectiveSession.id}
|
||||||
projectId={effectiveSession.project_id}
|
projectId={effectiveSession.project_id}
|
||||||
@@ -1284,7 +1316,11 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
|
|||||||
onFork={handleFork}
|
onFork={handleFork}
|
||||||
refreshVersion={timelineVersion}
|
refreshVersion={timelineVersion}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Fork Dialog */}
|
{/* Fork Dialog */}
|
||||||
|
@@ -2,8 +2,8 @@ import React from "react";
|
|||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
import { ErrorBoundary } from "./components/ErrorBoundary";
|
import { ErrorBoundary } from "./components/ErrorBoundary";
|
||||||
import "./styles.css";
|
|
||||||
import "./assets/shimmer.css";
|
import "./assets/shimmer.css";
|
||||||
|
import "./styles.css";
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
@@ -423,9 +423,9 @@ button:focus-visible,
|
|||||||
/* Rotating symbol animation */
|
/* Rotating symbol animation */
|
||||||
@keyframes rotate-symbol {
|
@keyframes rotate-symbol {
|
||||||
0% { content: "◐"; transform: scale(1); }
|
0% { content: "◐"; transform: scale(1); }
|
||||||
25% { content: "◓"; transform: scale(10); }
|
25% { content: "◓"; transform: scale(1); }
|
||||||
50% { content: "◑"; transform: scale(1); }
|
50% { content: "◑"; transform: scale(1); }
|
||||||
75% { content: "◒"; transform: scale(10); }
|
75% { content: "◒"; transform: scale(1); }
|
||||||
100% { content: "◐"; transform: scale(1); }
|
100% { content: "◐"; transform: scale(1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user