diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 49eb8f37a8..5a3388bc64 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -18,7 +18,7 @@ "@cap/utils": "workspace:*", "@cap/web-api-contract": "workspace:*", "@corvu/tooltip": "^0.2.1", - "@kobalte/core": "^0.13.7", + "@kobalte/core": "^0.13.11", "@radix-ui/colors": "^3.0.0", "@rive-app/canvas": "^2.32.2", "@solid-primitives/bounds": "^0.0.122", @@ -74,13 +74,16 @@ }, "devDependencies": { "@fontsource/geist-sans": "^5.0.3", - "@webgpu/types": "^0.1.44", "@iconify/json": "^2.2.239", + "@tailwindcss/postcss": "^4.2.2", + "@tailwindcss/typography": "^0.5.9", "@tauri-apps/cli": ">=2.1.0", "@total-typescript/ts-reset": "^0.6.1", "@types/dom-webcodecs": "^0.1.11", "@types/uuid": "^9.0.8", + "@webgpu/types": "^0.1.44", "cross-env": "^7.0.3", + "tailwind-scrollbar": "^3.1.0", "typescript": "^5.8.3", "vite": "^6.3.5", "vite-plugin-top-level-await": "^1.4.4", diff --git a/apps/desktop/postcss.config.cjs b/apps/desktop/postcss.config.cjs index a1d89157e4..eebbe271c7 100644 --- a/apps/desktop/postcss.config.cjs +++ b/apps/desktop/postcss.config.cjs @@ -1 +1,6 @@ -module.exports = require("@cap/ui/postcss"); +module.exports = { + plugins: { + "@tailwindcss/postcss": {}, + autoprefixer: {}, + }, +}; diff --git a/apps/desktop/src/components/CapErrorBoundary.tsx b/apps/desktop/src/components/CapErrorBoundary.tsx index 5bf7fc132e..2dca68d1d4 100644 --- a/apps/desktop/src/components/CapErrorBoundary.tsx +++ b/apps/desktop/src/components/CapErrorBoundary.tsx @@ -9,9 +9,9 @@ export function CapErrorBoundary(props: ParentProps) { fallback={(e: Error) => { console.error(e); return ( -
+
-

+

An Error Occured

diff --git a/apps/desktop/src/components/Cropper.tsx b/apps/desktop/src/components/Cropper.tsx index 6509ce71cf..2a22e1b5f9 100644 --- a/apps/desktop/src/components/Cropper.tsx +++ b/apps/desktop/src/components/Cropper.tsx @@ -1018,7 +1018,7 @@ export function Cropper( return (

{(transform) => ( @@ -1110,7 +1110,7 @@ export function Cropper( handle.isCorner ? (
)} -
+
{ if (part.toLowerCase() === lowercaseQuery) { return ( - {part} + {part} ); } return part; @@ -314,12 +314,12 @@ export default function TargetCard(props: TargetCardProps) { disabled={local.disabled} data-variant={local.variant} class={cx( - "group flex flex-col overflow-hidden rounded-lg border border-transparent bg-gray-3 text-left outline-none transition-colors duration-100 hover:bg-gray-4 focus-visible:ring-2 focus-visible:ring-blue-9 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-1", + "group flex flex-col overflow-hidden rounded-lg border border-transparent bg-gray-3 text-left outline-hidden transition-colors duration-100 hover:bg-gray-4 focus-visible:ring-2 focus-visible:ring-blue-9 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-1", local.disabled && "pointer-events-none opacity-60", local.class, )} > -
+
-
+
-
+
{recordingFailed() ? "Recording failed" : "Upload failed"} @@ -391,7 +391,7 @@ export default function TargetCard(props: TargetCardProps) { role="button" tabIndex={-1} onClick={handleOpenEditor} - class="flex-1 flex items-center justify-center p-1 rounded hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" + class="flex-1 flex items-center justify-center p-1 rounded-sm hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" >
@@ -401,7 +401,7 @@ export default function TargetCard(props: TargetCardProps) { role="button" tabIndex={-1} onClick={handleCopy} - class="flex-1 flex items-center justify-center p-1 rounded hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" + class="flex-1 flex items-center justify-center p-1 rounded-sm hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" >
@@ -411,7 +411,7 @@ export default function TargetCard(props: TargetCardProps) { role="button" tabIndex={-1} onClick={handleSave} - class="flex-1 flex items-center justify-center p-1 rounded hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" + class="flex-1 flex items-center justify-center p-1 rounded-sm hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" >
@@ -436,7 +436,7 @@ export default function TargetCard(props: TargetCardProps) { role="button" tabIndex={-1} onClick={handleOpenRecordingEditor} - class="flex-1 flex items-center justify-center p-1 rounded hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" + class="flex-1 flex items-center justify-center p-1 rounded-sm hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" >
@@ -453,7 +453,7 @@ export default function TargetCard(props: TargetCardProps) { role="button" tabIndex={-1} onClick={handleReupload} - class="flex-1 flex items-center justify-center p-1 rounded hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" + class="flex-1 flex items-center justify-center p-1 rounded-sm hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" >
@@ -475,7 +475,7 @@ export default function TargetCard(props: TargetCardProps) { role="button" tabIndex={-1} onClick={handleOpenRecordingLink} - class="flex-1 flex items-center justify-center p-1 rounded hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" + class="flex-1 flex items-center justify-center p-1 rounded-sm hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" >
@@ -486,7 +486,7 @@ export default function TargetCard(props: TargetCardProps) { role="button" tabIndex={-1} onClick={handleOpenRecordingFolder} - class="flex-1 flex items-center justify-center p-1 rounded hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" + class="flex-1 flex items-center justify-center p-1 rounded-sm hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" >
@@ -496,7 +496,7 @@ export default function TargetCard(props: TargetCardProps) { role="button" tabIndex={-1} onClick={handleDeleteRecording} - class="flex-1 flex items-center justify-center p-1 rounded hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" + class="flex-1 flex items-center justify-center p-1 rounded-sm hover:bg-gray-5 text-gray-11 hover:text-gray-12 transition-colors" >
@@ -522,12 +522,12 @@ export function TargetCardSkeleton(props: { class?: string }) { props.class, )} > -
+
-
-
-
+
+
+
diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/TargetDropdownButton.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/TargetDropdownButton.tsx index 5865e5c860..4c6c7b2619 100644 --- a/apps/desktop/src/routes/(window-chrome)/new-main/TargetDropdownButton.tsx +++ b/apps/desktop/src/routes/(window-chrome)/new-main/TargetDropdownButton.tsx @@ -27,7 +27,7 @@ export default function TargetDropdownButton< aria-expanded={local.expanded ? "true" : "false"} data-expanded={local.expanded ? "true" : "false"} class={cx( - "flex w-5 shrink-0 items-center justify-center rounded-lg bg-gray-4 text-gray-12 transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-9 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-1 hover:bg-gray-5", + "flex w-5 shrink-0 items-center justify-center rounded-lg bg-gray-4 text-gray-12 transition-colors duration-150 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-blue-9 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-1 hover:bg-gray-5", local.expanded && "bg-gray-5", local.disabled && "pointer-events-none opacity-60", local.class, diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/TargetTypeButton.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/TargetTypeButton.tsx index eea046c313..c295d46de8 100644 --- a/apps/desktop/src/routes/(window-chrome)/new-main/TargetTypeButton.tsx +++ b/apps/desktop/src/routes/(window-chrome)/new-main/TargetTypeButton.tsx @@ -24,7 +24,7 @@ function TargetTypeButton(props: TargetTypeButtonProps) { disabled={local.disabled} aria-pressed={local.selected ? "true" : "false"} class={cx( - "flex flex-1 flex-col items-center justify-end gap-1 rounded-lg border border-gray-5 bg-gray-3 py-2 text-center transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-9 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-1", + "flex flex-1 flex-col items-center justify-end gap-1 rounded-lg border border-gray-5 bg-gray-3 py-2 text-center transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-blue-9 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-1", local.selected ? "text-gray-12" : "text-gray-12 hover:bg-gray-4", local.disabled && "pointer-events-none opacity-60", local.class, diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/index.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/index.tsx index d0ea2d8d78..78b851c639 100644 --- a/apps/desktop/src/routes/(window-chrome)/new-main/index.tsx +++ b/apps/desktop/src/routes/(window-chrome)/new-main/index.tsx @@ -202,59 +202,59 @@ const createDisplaySignature = ( type TargetMenuPanelProps = | { - variant: "display"; - targets?: CaptureDisplayWithThumbnail[]; - onSelect: (target: CaptureDisplayWithThumbnail) => void; - } + variant: "display"; + targets?: CaptureDisplayWithThumbnail[]; + onSelect: (target: CaptureDisplayWithThumbnail) => void; + } | { - variant: "window"; - targets?: CaptureWindowWithThumbnail[]; - onSelect: (target: CaptureWindowWithThumbnail) => void; - } + variant: "window"; + targets?: CaptureWindowWithThumbnail[]; + onSelect: (target: CaptureWindowWithThumbnail) => void; + } | { - variant: "recording"; - targets?: RecordingWithPath[]; - onSelect: (target: RecordingWithPath) => void; - onViewAll: () => void; - uploadProgress?: Record; - reuploadingPaths?: Set; - onReupload?: (path: string) => void; - onRefetch?: () => void; - } + variant: "recording"; + targets?: RecordingWithPath[]; + onSelect: (target: RecordingWithPath) => void; + onViewAll: () => void; + uploadProgress?: Record; + reuploadingPaths?: Set; + onReupload?: (path: string) => void; + onRefetch?: () => void; + } | { - variant: "screenshot"; - targets?: ScreenshotWithPath[]; - onSelect: (target: ScreenshotWithPath) => void; - onViewAll: () => void; - } + variant: "screenshot"; + targets?: ScreenshotWithPath[]; + onSelect: (target: ScreenshotWithPath) => void; + onViewAll: () => void; + } | { - variant: "camera"; - targets?: CameraWithDetails[]; - selectedTarget: CameraWithDetails | null; - onSelect: (target: CameraWithDetails | null) => void; - permissions?: OSPermissionsCheck; - deviceSettings?: RecordingDeviceSettingsStore; - onCameraSettingsChange: ( - camera: CameraWithDetails, - settings: CameraDeviceSettings, - ) => void; - compatibilityStudioMode: boolean; - initialSettingsTarget?: CameraWithDetails | null; - } + variant: "camera"; + targets?: CameraWithDetails[]; + selectedTarget: CameraWithDetails | null; + onSelect: (target: CameraWithDetails | null) => void; + permissions?: OSPermissionsCheck; + deviceSettings?: RecordingDeviceSettingsStore; + onCameraSettingsChange: ( + camera: CameraWithDetails, + settings: CameraDeviceSettings, + ) => void; + compatibilityStudioMode: boolean; + initialSettingsTarget?: CameraWithDetails | null; + } | { - variant: "microphone"; - targets?: MicrophoneWithDetails[]; - selectedTarget: MicrophoneWithDetails | null; - onSelect: (target: MicrophoneWithDetails | null) => void; - permissions?: OSPermissionsCheck; - deviceSettings?: RecordingDeviceSettingsStore; - onMicrophoneSettingsChange: ( - key: string, - settings: MicrophoneDeviceSettings, - ) => void; - compatibilityStudioMode: boolean; - initialSettingsTarget?: MicrophoneWithDetails | null; - }; + variant: "microphone"; + targets?: MicrophoneWithDetails[]; + selectedTarget: MicrophoneWithDetails | null; + onSelect: (target: MicrophoneWithDetails | null) => void; + permissions?: OSPermissionsCheck; + deviceSettings?: RecordingDeviceSettingsStore; + onMicrophoneSettingsChange: ( + key: string, + settings: MicrophoneDeviceSettings, + ) => void; + compatibilityStudioMode: boolean; + initialSettingsTarget?: MicrophoneWithDetails | null; + }; type SharedTargetMenuProps = { isLoading: boolean; @@ -265,41 +265,41 @@ type SharedTargetMenuProps = { type DeviceListPanelProps = | { - variant: "camera"; - targets: CameraWithDetails[]; - selectedTarget: CameraWithDetails | null; - onSelect: (target: CameraWithDetails | null) => void; - isLoading?: boolean; - errorMessage?: string; - disabled?: boolean; - emptyMessage?: string; - permissions?: OSPermissionsCheck; - deviceSettings?: RecordingDeviceSettingsStore; - onCameraSettingsChange: ( - camera: CameraWithDetails, - settings: CameraDeviceSettings, - ) => void; - compatibilityStudioMode: boolean; - initialSettingsTarget?: CameraWithDetails | null; - } + variant: "camera"; + targets: CameraWithDetails[]; + selectedTarget: CameraWithDetails | null; + onSelect: (target: CameraWithDetails | null) => void; + isLoading?: boolean; + errorMessage?: string; + disabled?: boolean; + emptyMessage?: string; + permissions?: OSPermissionsCheck; + deviceSettings?: RecordingDeviceSettingsStore; + onCameraSettingsChange: ( + camera: CameraWithDetails, + settings: CameraDeviceSettings, + ) => void; + compatibilityStudioMode: boolean; + initialSettingsTarget?: CameraWithDetails | null; + } | { - variant: "microphone"; - targets: MicrophoneWithDetails[]; - selectedTarget: MicrophoneWithDetails | null; - onSelect: (target: MicrophoneWithDetails | null) => void; - isLoading?: boolean; - errorMessage?: string; - disabled?: boolean; - emptyMessage?: string; - permissions?: OSPermissionsCheck; - deviceSettings?: RecordingDeviceSettingsStore; - onMicrophoneSettingsChange: ( - key: string, - settings: MicrophoneDeviceSettings, - ) => void; - compatibilityStudioMode: boolean; - initialSettingsTarget?: MicrophoneWithDetails | null; - }; + variant: "microphone"; + targets: MicrophoneWithDetails[]; + selectedTarget: MicrophoneWithDetails | null; + onSelect: (target: MicrophoneWithDetails | null) => void; + isLoading?: boolean; + errorMessage?: string; + disabled?: boolean; + emptyMessage?: string; + permissions?: OSPermissionsCheck; + deviceSettings?: RecordingDeviceSettingsStore; + onMicrophoneSettingsChange: ( + key: string, + settings: MicrophoneDeviceSettings, + ) => void; + compatibilityStudioMode: boolean; + initialSettingsTarget?: MicrophoneWithDetails | null; + }; function CameraListItem(props: { camera: CameraWithDetails; @@ -321,7 +321,7 @@ function CameraListItem(props: { return (
@@ -971,7 +971,7 @@ function DeviceListPanel(props: DeviceListPanelProps) { return (
@@ -1000,7 +1000,7 @@ function DeviceListPanel(props: DeviceListPanelProps) { disabled={props.disabled} onClick={() => handleSelect(null)} class={cx( - "flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm text-left outline-none", + "flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm text-left outline-hidden", isNoneSelected() ? "bg-blue-500 text-white" : focusedIndex() === 0 @@ -1281,7 +1281,7 @@ function TargetMenuPanel(props: TargetMenuPanelProps & SharedTargetMenuProps) { onClick={() => props.onBack()} class="flex gap-1 items-center rounded-md px-1.5 text-xs text-gray-11 transition-opacity hover:opacity-70 hover:text-gray-12 - focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-9 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-1" + focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-blue-9 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-1" > Back @@ -1479,7 +1479,7 @@ function MainWindowHelpButton() { onClick={() => { commands.showWindow("Onboarding"); }} - class="flex shrink-0 justify-center items-center size-5 focus:outline-none" + class="flex shrink-0 justify-center items-center size-5 focus:outline-hidden" > @@ -1654,7 +1654,7 @@ function Page() { await commands.uploadExportedVideo( path, "Reupload", - new Channel(() => {}), + new Channel(() => { }), null, ); } finally { @@ -2095,8 +2095,7 @@ function Page() { await commands.stopRecording(); } catch (error) { await dialog.message( - `Failed to stop recording: ${ - error instanceof Error ? error.message : String(error) + `Failed to stop recording: ${error instanceof Error ? error.message : String(error) }`, { title: "Stop Recording", kind: "error" }, ); @@ -2188,7 +2187,7 @@ function Page() { class={cx( "flex flex-1 overflow-hidden rounded-lg border border-gray-5 bg-gray-3 ring-1 ring-transparent ring-offset-2 ring-offset-gray-1 transition focus-within:ring-blue-9 focus-within:ring-offset-2 focus-within:ring-offset-gray-1", (rawOptions.targetMode === "display" || displayMenuOpen()) && - "ring-blue-9", + "ring-blue-9", )} > {}); + await signIn.mutateAsync(abort).catch(() => { }); for (const win of await getAllWebviewWindows()) { if (win.label.startsWith("target-select-overlay")) { @@ -2320,7 +2319,7 @@ function Page() { return (
@@ -2356,7 +2355,7 @@ function Page() { return next; }); }} - class="flex justify-center items-center size-5 focus:outline-none" + class="flex justify-center items-center size-5 focus:outline-hidden" > @@ -2375,7 +2374,7 @@ function Page() { return next; }); }} - class="flex justify-center items-center size-5 focus:outline-none" + class="flex justify-center items-center size-5 focus:outline-hidden" > @@ -2387,7 +2386,7 @@ function Page() { onClick={() => { new WebviewWindow("debug", { url: "/debug" }); }} - class="flex justify-center items-center focus:outline-none" + class="flex justify-center items-center focus:outline-hidden" > @@ -2399,7 +2398,7 @@ function Page() {
-
+
@@ -1342,7 +1342,7 @@ function RecordingBar(props: {