diff --git a/docs/pr/project-browser/login.png b/docs/pr/project-browser/login.png index 7043491d..84139cb4 100644 Binary files a/docs/pr/project-browser/login.png and b/docs/pr/project-browser/login.png differ diff --git a/docs/pr/project-browser/projects.png b/docs/pr/project-browser/projects.png index 3fca1ac3..a2025cba 100644 Binary files a/docs/pr/project-browser/projects.png and b/docs/pr/project-browser/projects.png differ diff --git a/public/auth/README.md b/public/auth/README.md new file mode 100644 index 00000000..dcabd0d6 --- /dev/null +++ b/public/auth/README.md @@ -0,0 +1,8 @@ +# Official provider logos + +Unmodified standalone color logos displayed inside HeroUI buttons; labels and controls belong to Recordly. + +- `google-logo.png`: https://developers.google.com/static/identity/images/g-logo.png — linked by https://developers.google.com/identity/branding-guidelines +- `microsoft-logo.svg`: https://learn.microsoft.com/en-us/entra/identity-platform/media/howto-add-branding-in-apps/ms-symbollockup_mssymbol_19.svg — linked by https://learn.microsoft.com/en-us/entra/identity-platform/howto-add-branding-in-apps + +Downloaded September 23, 2026. Trademarks belong to the respective providers. Preserve original colors and aspect ratio. diff --git a/public/auth/google-logo.png b/public/auth/google-logo.png new file mode 100644 index 00000000..cd6d16ac Binary files /dev/null and b/public/auth/google-logo.png differ diff --git a/public/auth/microsoft-logo.svg b/public/auth/microsoft-logo.svg new file mode 100644 index 00000000..1f739764 --- /dev/null +++ b/public/auth/microsoft-logo.svg @@ -0,0 +1 @@ +MS-SymbolLockup \ No newline at end of file diff --git a/src/components/auth/RecordlySignInDialog.tsx b/src/components/auth/RecordlySignInDialog.tsx index 07b23bef..5b8e47bd 100644 --- a/src/components/auth/RecordlySignInDialog.tsx +++ b/src/components/auth/RecordlySignInDialog.tsx @@ -1,9 +1,9 @@ +import { AnimatePresence, motion, useReducedMotion } from "motion/react"; import { demoLoginEnabled } from "@/lib/auth/demoSession"; -import { WindowsLogo } from "@phosphor-icons/react"; import { useI18n } from "@/contexts/I18nContext"; -import { GoogleLogo, SignOut } from "@/components/ui/icons"; +import { SignOut } from "@/components/ui/icons"; import type { User } from "@supabase/supabase-js"; -import { type FormEvent, useEffect, useState } from "react"; +import { type FormEvent, useEffect, useState, useRef } from "react"; import { Modal, Button, @@ -23,9 +23,12 @@ import { signOutRecordly, } from "@/lib/auth/recordlyAuth"; +const MotionDialog = motion.create(Modal.Dialog); + export type SignInReason = "account" | "share"; type Props = { + variant?: "compact" | "wide"; open: boolean; onOpenChange: (open: boolean) => void; reason?: SignInReason; @@ -52,15 +55,17 @@ function friendlyAuthError( } export function RecordlySignInDialog({ + variant = "compact", open, onOpenChange, - reason = "account", user, configured, callbackError, onAuthenticated, }: Props) { const { t } = useI18n(); + const awaitingSignIn = useRef(false); + const wide = variant === "wide"; const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [busy, setBusy] = useState(); @@ -70,6 +75,7 @@ export function RecordlySignInDialog({ useEffect(() => { if (!open) { setPassword(""); + awaitingSignIn.current = false; setBusy(undefined); setMessage(undefined); setResetSent(false); @@ -77,8 +83,14 @@ export function RecordlySignInDialog({ }, [open]); useEffect(() => { - if (open && user && reason === "share") onAuthenticated(); - }, [onAuthenticated, open, reason, user]); + if (!open) return; + if (!user) awaitingSignIn.current = true; + else if (awaitingSignIn.current) { + awaitingSignIn.current = false; + setMessage(undefined); + onAuthenticated(); + } + }, [open, user, onAuthenticated]); const run = async (label: string, action: () => Promise) => { setBusy(label); @@ -101,7 +113,6 @@ export function RecordlySignInDialog({ throw new Error("Email sign-in is not available yet."); } await signInWithEmail(email.trim(), password); - onAuthenticated(); }); }; @@ -117,37 +128,73 @@ export function RecordlySignInDialog({ }); }; + const reduceMotion = useReducedMotion(); + const transition = { duration: reduceMotion ? 0 : 0.28, ease: [0.22, 1, 0.36, 1] as const }; + const reveal = { + initial: { opacity: 0, y: reduceMotion ? 0 : 10 }, + animate: { opacity: 1, y: 0 }, + transition, + }; const disabled = Boolean(busy); const expanded = email.trim().length > 0; const artwork = `${import.meta.env.BASE_URL}wallpapers/wallpaper1.jpg`; return ( - + - + + -
-
- - - {user ? "Your account" : "Welcome back"} - - - {user - ? user.email - : reason === "share" - ? "Sign in to share your recordings." - : "Sign in to your Recordly account."} - - + + +
+ + +
+ + + Recordly + +
+ + {user + ? "Your account" + : "Beautiful, shareable screen recordings"} + + {user && ( + + {user.email} + + )} +
+
{user ? ( -
+
@@ -197,10 +261,7 @@ export function RecordlySignInDialog({
-
+ - {expanded && ( -
- + {expanded && ( + - - - - - {configured && ( - - )} - -
- )} + + + + + + {configured && ( + + )} + + + + )} +
)} @@ -284,24 +367,8 @@ export function RecordlySignInDialog({ )}
-
-
- -
- - Recordly - -

- Make something -
- worth sharing. -

-
- + + diff --git a/src/components/video-editor/dashboard/DashboardFilters.tsx b/src/components/video-editor/dashboard/DashboardFilters.tsx index bb1d41a0..6d66b65a 100644 --- a/src/components/video-editor/dashboard/DashboardFilters.tsx +++ b/src/components/video-editor/dashboard/DashboardFilters.tsx @@ -1,14 +1,12 @@ import type { DashboardProps } from "./types"; import { Dropdown } from "@heroui/react"; -import { CaretDown, Trash, UploadSimple } from "@/components/ui/icons"; +import { CaretDown, Trash } from "@/components/ui/icons"; import { Button } from "@/components/ui/button"; import type { DashboardModel } from "./useDashboardModel"; export function DashboardFilters({ - onImportFile, - run, isRaw, period, setPeriod, @@ -23,8 +21,6 @@ export function DashboardFilters({ setConfirmDelete, }: Pick< DashboardModel & DashboardProps, - | "onImportFile" - | "run" | "isRaw" | "period" | "setPeriod" @@ -74,16 +70,6 @@ export function DashboardFilters({
-
)} diff --git a/src/components/video-editor/dashboard/DashboardSidebar.tsx b/src/components/video-editor/dashboard/DashboardSidebar.tsx index 21097509..758e1744 100644 --- a/src/components/video-editor/dashboard/DashboardSidebar.tsx +++ b/src/components/video-editor/dashboard/DashboardSidebar.tsx @@ -1,3 +1,4 @@ +import { RecordNewButton } from "./RecordNewButton"; import { SidebarCards } from "./SidebarCards"; import { FolderRow } from "./FolderRow"; import { Cloud, File, GearSix, House, Plus, UserCircle } from "@/components/ui/icons"; @@ -10,6 +11,8 @@ import type { DashboardModel } from "./useDashboardModel"; import { FOLDER_COLORS } from "./useProjectFolders"; export function DashboardSidebar({ + busy, + run, folders, save, section, @@ -21,6 +24,8 @@ export function DashboardSidebar({ accountLabel, }: Pick< DashboardProps & DashboardModel, + | "busy" + | "run" | "folders" | "save" | "section" @@ -37,7 +42,7 @@ export function DashboardSidebar({ aria-label="Library navigation" className="flex w-48 shrink-0 flex-col bg-transparent px-4 pb-5 pt-12 lg:w-56" > -
+
Recordly
+
- +
+ +
); diff --git a/src/components/video-editor/dashboard/RecordNewButton.tsx b/src/components/video-editor/dashboard/RecordNewButton.tsx new file mode 100644 index 00000000..a671cf34 --- /dev/null +++ b/src/components/video-editor/dashboard/RecordNewButton.tsx @@ -0,0 +1,27 @@ +import { Plus } from "@/components/ui/icons"; +import { Button } from "@/components/ui/button"; +import { cn } from "@/lib/utils"; + +export function RecordNewButton({ + busy, + run, + className, + first = false, +}: { + busy: boolean; + run: (action: () => Promise) => Promise; + className?: string; + first?: boolean; +}) { + return ( + + ); +} diff --git a/src/components/video-editor/layout/EditorHeader.tsx b/src/components/video-editor/layout/EditorHeader.tsx index a1e9a48f..69bf87cc 100644 --- a/src/components/video-editor/layout/EditorHeader.tsx +++ b/src/components/video-editor/layout/EditorHeader.tsx @@ -184,7 +184,7 @@ export function EditorHeader(props: Props) { )}
- +