افزودن سیستم Motion به تمام بخش‌های رابط کاربری

واژگان مشترک حرکت در globals.css: شش @keyframes و شش کلاس .anim-*
به‌همراه .anim-stagger برای ورود آبشاری. همهٔ مدت‌زمان‌ها پشت custom
property هستند تا یک override کل اپ را تنظیم کند.

- packages/ui: Button، Card، Stat، Loading/Empty/ErrorState، UsageBar،
  Timeline، Modal، Drawer، Table، ToastStack و ArtifactViewer
- ریشهٔ هر صفحهٔ (app) با .anim-stagger وارد می‌شود
- AppShell: محتوا fade، منوی کنار stagger، منوهای کشویی slide-up
- prefers-reduced-motion مدت‌زمان‌ها را به ۰.۰۱ms می‌رساند تا
  وضعیت پایانی حفظ شود
- قرارداد motion در src/test/motion.test.tsx تست می‌شود تا
  بازنویسی بعدی آن را بی‌صدا حذف نکند
- تست‌های فرانت‌اند: ۳۵ ← ۴۵
This commit is contained in:
mjalmoudy94
2026-10-13 02:48:59 +03:30
parent 55b9055b50
commit df2c8546db
29 changed files with 381 additions and 57 deletions
+4 -4
View File
@@ -66,7 +66,7 @@ export function AppShell({ children }: { children: React.ReactNode }) {
<span className="text-sm font-medium text-slate-100">Smart Organization</span>
</div>
<nav className="flex flex-1 flex-col gap-1 p-3">
<nav className="anim-stagger flex flex-1 flex-col gap-1 p-3">
{NAV_ITEMS.map((item) => {
const active = pathname === item.href || pathname.startsWith(`${item.href}/`);
return (
@@ -126,7 +126,7 @@ export function AppShell({ children }: { children: React.ReactNode }) {
{activeOrganization?.name ?? "بدون سازمان"}
</Button>
{menuOpen && (
<div className="absolute right-0 top-10 z-40 w-64 rounded-lg border border-surface-border bg-surface-overlay p-1.5">
<div className="anim-slide-up absolute right-0 top-10 z-40 w-64 rounded-lg border border-surface-border bg-surface-overlay p-1.5">
{organizations.length === 0 && (
<p className="px-2 py-2 text-xs text-slate-400">هنوز سازمانی نساخته‌اید.</p>
)}
@@ -179,7 +179,7 @@ export function AppShell({ children }: { children: React.ReactNode }) {
{user?.is_platform_owner && <Badge tone="info">مالک سامانه</Badge>}
</button>
{userMenuOpen && (
<div className="absolute end-0 top-11 z-40 w-56 rounded-lg border border-surface-border bg-surface-overlay p-1.5">
<div className="anim-slide-up absolute end-0 top-11 z-40 w-56 rounded-lg border border-surface-border bg-surface-overlay p-1.5">
<div className="px-2 py-1.5">
<p className="truncate text-xs text-slate-200">
{user?.name || "کاربر"}
@@ -215,7 +215,7 @@ export function AppShell({ children }: { children: React.ReactNode }) {
</div>
</header>
<main className="min-w-0 flex-1 p-5">{children}</main>
<main className="anim-fade-in min-w-0 flex-1 p-5">{children}</main>
</div>
</div>
);
+1 -1
View File
@@ -173,7 +173,7 @@ export function CommandPalette({ isPlatformOwner = false }: { isPlatformOwner?:
<EmptyState title="نتیجه‌ای پیدا نشد" description="عبارت دیگری را امتحان کنید." />
) : (
filteredGroups.map((group) => (
<div key={group.title} className="flex flex-col gap-1">
<div key={group.title} className="anim-stagger flex flex-col gap-1">
<p className="px-1 text-[11px] font-medium text-slate-500">{group.title}</p>
{group.items.map((item) => {
const index = visible.indexOf(item);