Skip to content

Commit fd32ffd

Browse files
authored
fix: polish Clips sharing and desktop settings
Local targeted validation passed; merging per explicit ship instruction without waiting for external CI/install failures or soak.
1 parent 61d4e0f commit fd32ffd

8 files changed

Lines changed: 1104 additions & 531 deletions

File tree

.changeset/bright-clips-share.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@agent-native/core": patch
3+
---
4+
5+
Polish sharing dialogs and controls across the core and Clips surfaces.

packages/core/src/client/sharing/ShareDialog.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,11 @@ export function ShareDialog({
119119
onOpenChange={controller.onOpenChange}
120120
title={
121121
<span
122-
className="truncate !text-base !leading-normal !tracking-normal !text-inherit"
122+
className={cn(
123+
controller.tabsEnabled
124+
? "sr-only"
125+
: "truncate !text-base !leading-normal !tracking-normal !text-inherit",
126+
)}
123127
title={controller.title}
124128
>
125129
{controller.title}
@@ -130,13 +134,13 @@ export function ShareDialog({
130134
className="!top-4 !z-[2010] !block !max-h-none !w-[calc(100vw-2rem)] !max-w-lg !translate-y-0 !gap-0 !overflow-visible !rounded-xl !border-border !bg-popover !p-0 !text-popover-foreground !shadow-2xl sm:!top-1/2 sm:!-translate-y-1/2"
131135
aria-label={controller.title}
132136
>
133-
<div className="px-5 pt-0 pb-3">
134-
{controller.ownerLabel ? (
137+
{!controller.tabsEnabled && controller.ownerLabel ? (
138+
<div className="px-5 pt-0 pb-3">
135139
<div className="truncate text-xs text-muted-foreground">
136140
{controller.ownerLabel}
137141
</div>
138-
) : null}
139-
</div>
142+
</div>
143+
) : null}
140144

141145
{controller.tabsEnabled ? (
142146
<div
@@ -224,7 +228,7 @@ function LinkTab({
224228
controller={controller}
225229
/>
226230
<div>
227-
<div className="mb-2 text-sm font-semibold">
231+
<div className="mb-2 text-xs font-medium text-muted-foreground">
228232
{controller.labels.generalAccess}
229233
</div>
230234
<div className="flex items-center gap-3">

templates/clips/app/components/meetings/share-meeting-dialog.tsx

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
CopyField,
1313
GeneralAccessSelect,
1414
MakePublicCard,
15-
ShareCardHeader,
1615
SharePeopleTab,
1716
copyToClipboard,
1817
useResourceVisibilityMutation,
@@ -30,15 +29,13 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
3029

3130
export interface ShareMeetingPopoverProps {
3231
meetingId: string;
33-
meetingTitle?: string;
3432
shareTranscript: boolean;
3533
transcriptReady: boolean;
3634
children: ReactNode;
3735
}
3836

3937
export function ShareMeetingPopover({
4038
meetingId,
41-
meetingTitle,
4239
shareTranscript,
4340
transcriptReady,
4441
children,
@@ -52,7 +49,6 @@ export function ShareMeetingPopover({
5249
>
5350
<ShareMeetingContent
5451
meetingId={meetingId}
55-
meetingTitle={meetingTitle}
5652
shareTranscript={shareTranscript}
5753
transcriptReady={transcriptReady}
5854
/>
@@ -63,12 +59,10 @@ export function ShareMeetingPopover({
6359

6460
function ShareMeetingContent({
6561
meetingId,
66-
meetingTitle,
6762
shareTranscript,
6863
transcriptReady,
6964
}: {
7065
meetingId: string;
71-
meetingTitle?: string;
7266
shareTranscript: boolean;
7367
transcriptReady: boolean;
7468
}) {
@@ -85,14 +79,9 @@ function ShareMeetingContent({
8579

8680
const data = sharesQuery.data;
8781
const canManage = data?.role === "owner" || data?.role === "admin";
88-
const titleText = meetingTitle
89-
? t("clipsFinalRaw.shareNamedMeeting", { title: meetingTitle })
90-
: t("clipsFinalRaw.shareMeeting");
9182

9283
return (
9384
<>
94-
<ShareCardHeader title={titleText} ownerEmail={data?.ownerEmail} />
95-
9685
<Tabs defaultValue="link" className="min-w-0 px-4 py-3">
9786
<TabsList className="grid w-full grid-cols-2">
9887
<TabsTrigger value="link" className="gap-1.5">

templates/clips/app/components/player/share-dialog.tsx

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import {
2727
CopyField,
2828
GeneralAccessSelect,
2929
MakePublicCard,
30-
ShareCardHeader,
3130
SharePeopleTab,
3231
copyToClipboard,
3332
useResourceVisibilityMutation,
@@ -51,6 +50,7 @@ import {
5150
} from "@/components/ui/popover";
5251
import { Switch } from "@/components/ui/switch";
5352
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
53+
import { cn } from "@/lib/utils";
5454

5555
import { buildEmailPreviewMarkup } from "../../../shared/email-preview";
5656
import { isLoomEmbedUrl } from "../../../shared/loom";
@@ -228,19 +228,12 @@ function ShareRecordingContent({
228228
absoluteAppUrl(`/share/${recordingId}`),
229229
ownerViaId,
230230
);
231-
const titleText = recordingTitle
232-
? t("shareDialog.shareTitle", { title: recordingTitle })
233-
: t("shareDialog.shareRecording");
234-
235231
return (
236232
<>
237-
<ShareCardHeader
238-
title={titleText}
239-
ownerEmail={data?.ownerEmail}
240-
reserveCloseButton={reserveCloseButton}
241-
/>
242-
243-
<Tabs defaultValue="link" className="min-w-0 px-4 py-3">
233+
<Tabs
234+
defaultValue="link"
235+
className={cn("min-w-0 px-4 py-3", reserveCloseButton && "pe-12")}
236+
>
244237
<TabsList className="grid w-full grid-cols-3">
245238
<TabsTrigger value="link" className="gap-1.5">
246239
<IconLink size={14} />
@@ -441,6 +434,25 @@ function LinkTab({
441434
? t("shareDialog.agentPrompt", { agentContextUrl: agentLink })
442435
: "";
443436
const [agentDetailsOpen, setAgentDetailsOpen] = useState(false);
437+
const showMakePublic = sharesLoaded && !isPublic && canManage;
438+
const downloadButton = videoUrl ? (
439+
<Button
440+
variant="outline"
441+
size="sm"
442+
className={isLoomRecording ? "gap-1.5" : undefined}
443+
onClick={() => window.open(videoUrl, "_blank", "noopener,noreferrer")}
444+
>
445+
{isLoomRecording ? (
446+
<>
447+
<IconExternalLink className="h-4 w-4" />
448+
{t("shareDialog.openPlayer")}
449+
</>
450+
) : (
451+
t("recordRoute.downloadRecording")
452+
)}
453+
</Button>
454+
) : null;
455+
const moveDownloadIntoMakePublicRow = showMakePublic && Boolean(videoUrl);
444456

445457
useEffect(() => {
446458
if (isPublic) setAgentDetailsOpen(false);
@@ -540,9 +552,12 @@ function LinkTab({
540552
</Collapsible>
541553
) : null}
542554

543-
{sharesLoaded && !isPublic && canManage ? (
555+
{showMakePublic ? (
544556
<MakePublicCard
545557
isPending={isPending}
558+
secondaryAction={
559+
moveDownloadIntoMakePublicRow ? downloadButton : undefined
560+
}
546561
onMakePublic={() =>
547562
setResourceVisibility("public", {
548563
onSuccess: () => copyToClipboard(shareUrl),
@@ -551,7 +566,9 @@ function LinkTab({
551566
/>
552567
) : null}
553568

554-
{emailPreviewThumbnailUrl || videoUrl || animatedThumbnailUrl ? (
569+
{emailPreviewThumbnailUrl ||
570+
animatedThumbnailUrl ||
571+
(videoUrl && !moveDownloadIntoMakePublicRow) ? (
555572
<div className="flex flex-wrap gap-2">
556573
{emailPreviewThumbnailUrl ? (
557574
<Button
@@ -571,25 +588,7 @@ function LinkTab({
571588
{t("shareDialog.gifPreview")}
572589
</Button>
573590
) : null}
574-
{videoUrl ? (
575-
<Button
576-
variant="outline"
577-
size="sm"
578-
className={isLoomRecording ? "gap-1.5" : undefined}
579-
onClick={() =>
580-
window.open(videoUrl, "_blank", "noopener,noreferrer")
581-
}
582-
>
583-
{isLoomRecording ? (
584-
<>
585-
<IconExternalLink className="h-4 w-4" />
586-
{t("shareDialog.openPlayer")}
587-
</>
588-
) : (
589-
t("recordRoute.downloadRecording")
590-
)}
591-
</Button>
592-
) : null}
591+
{!moveDownloadIntoMakePublicRow ? downloadButton : null}
593592
</div>
594593
) : null}
595594
</div>

templates/clips/app/components/sharing/share-ui.tsx

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
IconWorld,
1515
} from "@tabler/icons-react";
1616
import { useQueryClient } from "@tanstack/react-query";
17-
import { useMemo, useState } from "react";
17+
import { useMemo, useState, type ReactNode } from "react";
1818

1919
import {
2020
Avatar as UserAvatar,
@@ -136,34 +136,19 @@ export function useResourceVisibilityMutation(
136136
}
137137

138138
// ---------------------------------------------------------------------------
139-
// Header (title + owner)
139+
// Compact section labels
140140
// ---------------------------------------------------------------------------
141141

142-
export function ShareCardHeader({
143-
title,
144-
ownerEmail,
145-
reserveCloseButton = false,
142+
export function ShareSectionLabel({
143+
children,
144+
className,
146145
}: {
147-
title: string;
148-
ownerEmail?: string | null;
149-
reserveCloseButton?: boolean;
146+
children: ReactNode;
147+
className?: string;
150148
}) {
151-
const t = useT();
152149
return (
153-
<div
154-
className={cn(
155-
"min-w-0 border-b border-border px-4 pb-3 pt-3",
156-
reserveCloseButton && "pe-12",
157-
)}
158-
>
159-
<div className="min-w-0 truncate text-sm font-semibold" title={title}>
160-
{title}
161-
</div>
162-
{ownerEmail ? (
163-
<div className="mt-0.5 truncate text-xs text-muted-foreground">
164-
{t("shareUi.owner", { email: ownerEmail })}
165-
</div>
166-
) : null}
150+
<div className={cn("text-xs font-medium text-muted-foreground", className)}>
151+
{children}
167152
</div>
168153
);
169154
}
@@ -197,9 +182,9 @@ export function GeneralAccessSelect({
197182

198183
return (
199184
<div>
200-
<div className="mb-2 text-xs font-semibold">
185+
<ShareSectionLabel className="mb-2">
201186
{t("shareUi.generalAccess")}
202-
</div>
187+
</ShareSectionLabel>
203188
<div className="flex items-center gap-3">
204189
<span
205190
aria-hidden
@@ -245,9 +230,11 @@ export function GeneralAccessSelect({
245230
export function MakePublicCard({
246231
isPending,
247232
onMakePublic,
233+
secondaryAction,
248234
}: {
249235
isPending: boolean;
250236
onMakePublic: () => void;
237+
secondaryAction?: ReactNode;
251238
}) {
252239
const t = useT();
253240
return (
@@ -259,16 +246,21 @@ export function MakePublicCard({
259246
strokeWidth={1.8}
260247
className="text-muted-foreground"
261248
/>
262-
<Button
263-
type="button"
264-
variant="outline"
265-
size="sm"
266-
className="h-7"
267-
onClick={onMakePublic}
268-
disabled={isPending}
269-
>
270-
{isPending ? t("shareUi.makingPublic") : t("shareUi.makePublicAndCopy")}
271-
</Button>
249+
<div className="flex items-center gap-2">
250+
{secondaryAction}
251+
<Button
252+
type="button"
253+
variant="outline"
254+
size="sm"
255+
className="h-7"
256+
onClick={onMakePublic}
257+
disabled={isPending}
258+
>
259+
{isPending
260+
? t("shareUi.makingPublic")
261+
: t("shareUi.makePublicAndCopy")}
262+
</Button>
263+
</div>
272264
</div>
273265
);
274266
}
@@ -297,9 +289,7 @@ export function CopyField({
297289
return (
298290
<div>
299291
{label ? (
300-
<div className="mb-1 text-xs font-medium text-muted-foreground">
301-
{label}
302-
</div>
292+
<ShareSectionLabel className="mb-1">{label}</ShareSectionLabel>
303293
) : null}
304294
<div className="flex items-stretch gap-2">
305295
<Input

templates/clips/app/routes/_app.meetings.$meetingId.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,6 @@ export default function MeetingDetailRoute() {
704704
) : null}
705705
<ShareMeetingPopover
706706
meetingId={meeting.id}
707-
meetingTitle={meeting.title}
708707
shareTranscript={meeting.shareTranscript === true}
709708
transcriptReady={
710709
meeting.transcriptStatus === "ready" &&

0 commit comments

Comments
 (0)