mirror of
https://github.com/davidkaya/aryx.git
synced 2026-07-29 07:58:47 +02:00
feat: add animated transitions and micro-interactions
Add entrance animations to overlays, modals, chat messages, sidebar session items, and approval banners: - overlay-slide-enter: settings and project settings panels - overlay-backdrop-enter + overlay-panel-enter: modals - message-enter: chat message fade-up on mount - session-item-enter: sidebar item slide-in - banner-slide-enter: approval banner slide-down All animations use cubic-bezier(0.16, 1, 0.3, 1) for a snappy feel and stay under 250ms. Respects prefers-reduced-motion. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -345,7 +345,7 @@ export function ChatPane({
|
||||
phase === 'thinking' ? 'Thinking' : phase === 'final' ? 'Final' : undefined;
|
||||
|
||||
return (
|
||||
<div className="group py-3" data-message-id={message.id} key={message.id}>
|
||||
<div className="message-enter group py-3" data-message-id={message.id} key={message.id}>
|
||||
<div className="flex gap-3">
|
||||
<div
|
||||
className={`mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-full ${
|
||||
@@ -448,7 +448,7 @@ export function ChatPane({
|
||||
<div className="mx-auto max-w-3xl">
|
||||
{/* Pending approval banner */}
|
||||
{pendingApproval && (
|
||||
<div className="mb-3 space-y-2">
|
||||
<div className="banner-slide-enter mb-3 space-y-2">
|
||||
<ApprovalBanner
|
||||
approval={pendingApproval}
|
||||
isResolving={isResolvingApproval}
|
||||
|
||||
@@ -81,10 +81,10 @@ export function DiscoveredToolingModal({
|
||||
<div
|
||||
aria-labelledby="discovered-tooling-title"
|
||||
aria-modal="true"
|
||||
className="fixed inset-0 z-50 flex items-center justify-center bg-[#07080e]/90 backdrop-blur-sm"
|
||||
className="overlay-backdrop-enter fixed inset-0 z-50 flex items-center justify-center bg-[#07080e]/90 backdrop-blur-sm"
|
||||
role="dialog"
|
||||
>
|
||||
<div className="flex max-h-[80vh] w-full max-w-lg flex-col rounded-xl border border-[var(--color-border)] bg-[var(--color-surface-1)] shadow-[0_16px_64px_rgba(0,0,0,0.5)]">
|
||||
<div className="overlay-panel-enter flex max-h-[80vh] w-full max-w-lg flex-col rounded-xl border border-[var(--color-border)] bg-[var(--color-surface-1)] shadow-[0_16px_64px_rgba(0,0,0,0.5)]">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between border-b border-[var(--color-border)] px-5 py-4">
|
||||
<div className="flex items-center gap-2.5">
|
||||
|
||||
@@ -57,8 +57,8 @@ export function NewSessionModal({
|
||||
const canCreate = projectId && patternId;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-[#07080e]/90 backdrop-blur-sm" role="dialog" aria-modal="true" aria-labelledby="new-session-title">
|
||||
<div className="w-full max-w-md rounded-xl border border-[var(--color-border)] bg-[var(--color-surface-1)] shadow-[0_16px_64px_rgba(0,0,0,0.5)]">
|
||||
<div className="overlay-backdrop-enter fixed inset-0 z-50 flex items-center justify-center bg-[#07080e]/90 backdrop-blur-sm" role="dialog" aria-modal="true" aria-labelledby="new-session-title">
|
||||
<div className="overlay-panel-enter w-full max-w-md rounded-xl border border-[var(--color-border)] bg-[var(--color-surface-1)] shadow-[0_16px_64px_rgba(0,0,0,0.5)]">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between border-b border-[var(--color-border)] px-5 py-4">
|
||||
<h2 id="new-session-title" className="font-display text-[13px] font-semibold text-[var(--color-text-primary)]">New Session</h2>
|
||||
|
||||
@@ -111,7 +111,7 @@ export function ProjectSettingsPanel({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex flex-col bg-[var(--color-surface-0)]">
|
||||
<div className="overlay-slide-enter fixed inset-0 z-50 flex flex-col bg-[var(--color-surface-0)]">
|
||||
{/* Header */}
|
||||
<div className="drag-region flex items-center gap-3 border-b border-[var(--color-border)] px-5 pb-3 pt-3">
|
||||
<button
|
||||
|
||||
@@ -212,7 +212,7 @@ export function SettingsPanel({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex flex-col bg-[var(--color-surface-0)]">
|
||||
<div className="overlay-slide-enter fixed inset-0 z-50 flex flex-col bg-[var(--color-surface-0)]">
|
||||
<div className="drag-region flex items-center gap-3 border-b border-[var(--color-border)] px-5 pb-3 pt-3">
|
||||
<button
|
||||
className="no-drag flex size-8 items-center justify-center rounded-lg text-[var(--color-text-secondary)] transition-all duration-200 hover:bg-[var(--color-surface-3)] hover:text-[var(--color-text-primary)]"
|
||||
|
||||
@@ -213,7 +213,7 @@ function SessionItem({
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`group relative flex w-full cursor-pointer items-start gap-2.5 rounded-lg px-2.5 py-2 text-left transition-all duration-200 ${
|
||||
className={`session-item-enter group relative flex w-full cursor-pointer items-start gap-2.5 rounded-lg px-2.5 py-2 text-left transition-all duration-200 ${
|
||||
isActive
|
||||
? 'bg-[var(--color-accent-muted)] ring-1 ring-[var(--color-border-glow)]'
|
||||
: 'hover:bg-[var(--color-surface-2)]/60'
|
||||
|
||||
@@ -542,6 +542,92 @@ body {
|
||||
animation: palette-backdrop-enter 0.15s ease-out;
|
||||
}
|
||||
|
||||
/* ── Overlay transitions ─────────────────────────────────────── */
|
||||
|
||||
@keyframes overlay-backdrop-in {
|
||||
from { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes overlay-panel-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(6px) scale(0.99);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes overlay-slide-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(12px);
|
||||
}
|
||||
}
|
||||
|
||||
.overlay-backdrop-enter {
|
||||
animation: overlay-backdrop-in 0.18s ease-out;
|
||||
}
|
||||
|
||||
.overlay-panel-enter {
|
||||
animation: overlay-panel-in 0.22s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.overlay-slide-enter {
|
||||
animation: overlay-slide-in 0.22s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
/* ── Chat message appearance ─────────────────────────────────── */
|
||||
|
||||
@keyframes message-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(4px);
|
||||
}
|
||||
}
|
||||
|
||||
.message-enter {
|
||||
animation: message-in 0.2s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
}
|
||||
|
||||
/* ── Sidebar session item ────────────────────────────────────── */
|
||||
|
||||
@keyframes session-item-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-6px);
|
||||
}
|
||||
}
|
||||
|
||||
.session-item-enter {
|
||||
animation: session-item-in 0.18s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
}
|
||||
|
||||
/* ── Approval banner slide ───────────────────────────────────── */
|
||||
|
||||
@keyframes banner-slide-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
}
|
||||
|
||||
.banner-slide-enter {
|
||||
animation: banner-slide-in 0.25s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
/* ── Respect reduced motion ──────────────────────────────────── */
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.palette-enter,
|
||||
.palette-backdrop-enter,
|
||||
.overlay-backdrop-enter,
|
||||
.overlay-panel-enter,
|
||||
.overlay-slide-enter,
|
||||
.message-enter,
|
||||
.session-item-enter,
|
||||
.banner-slide-enter {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Markdown prose styles ───────────────────────────────────── */
|
||||
|
||||
.markdown-content {
|
||||
|
||||
Reference in New Issue
Block a user