mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
feat(panel): dense tooltip pass — projects, products, social, KB, business, settings, notifications (178 tips)
Density bar: every dialog field, column header, filter, badge, and status pill explains itself — grounded in the backend (ladder normalization, rate-limit park/probe, self-hosted fallback, reindex scope). Disabled buttons span-wrap so tips fire; tabs re-assert data-state.
This commit is contained in:
@@ -144,9 +144,14 @@ function UnifiedHistoryRow({ row }: { row: UnifiedRow }) {
|
||||
{PLATFORM_LABELS[platform] ?? platform}: {id}
|
||||
</a>
|
||||
) : (
|
||||
<span key={platform} className="text-muted-foreground">
|
||||
{PLATFORM_LABELS[platform] ?? platform}: {id}
|
||||
</span>
|
||||
<HelpTip
|
||||
key={platform}
|
||||
label="TikTok's inbox-upload API returns no public URL — this is the platform-side post id"
|
||||
>
|
||||
<span className="text-muted-foreground">
|
||||
{PLATFORM_LABELS[platform] ?? platform}: {id}
|
||||
</span>
|
||||
</HelpTip>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
@@ -211,7 +216,9 @@ export function SocialHistorySection({ className }: { className?: string }) {
|
||||
size="sm"
|
||||
className="w-full justify-between"
|
||||
>
|
||||
<span>{open ? "Hide" : "Show"} history</span>
|
||||
<HelpTip label="Fetches both sources once, on first expand — up to 50 rows each">
|
||||
<span>{open ? "Hide" : "Show"} history</span>
|
||||
</HelpTip>
|
||||
<ChevronDown
|
||||
className={`h-4 w-4 transition-transform ${open ? "rotate-180" : ""}`}
|
||||
/>
|
||||
|
||||
@@ -76,9 +76,11 @@ function PipelineRow({ item }: { item: VideoPipelineItem }) {
|
||||
prefetch={false}
|
||||
className="ml-auto"
|
||||
>
|
||||
<Button variant="outline" size="sm">
|
||||
Review
|
||||
</Button>
|
||||
<HelpTip label="Open the task to approve or reject the rendered video">
|
||||
<Button variant="outline" size="sm">
|
||||
Review
|
||||
</Button>
|
||||
</HelpTip>
|
||||
</Link>
|
||||
)}
|
||||
{canRerender && (
|
||||
@@ -110,7 +112,9 @@ export function VideoPipelineStrip({ className }: { className?: string }) {
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Film className="h-5 w-5" />
|
||||
Video Pipeline
|
||||
<Badge variant="secondary">{items.length}</Badge>
|
||||
<HelpTip label="Videos currently authoring, in review, or rendering — not yet in the queue below">
|
||||
<Badge variant="secondary">{items.length}</Badge>
|
||||
</HelpTip>
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Every video in flight — authoring, review, or rendering — before it
|
||||
|
||||
@@ -483,7 +483,9 @@ function RequestVideoDialog({
|
||||
<>
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label>Project</Label>
|
||||
<HelpTip label="Only projects with the video engine enabled (Projects → Edit) can be picked">
|
||||
<Label>Project</Label>
|
||||
</HelpTip>
|
||||
<ProjectSelector
|
||||
value={effectiveProjectId}
|
||||
onChange={setProjectId}
|
||||
@@ -493,7 +495,9 @@ function RequestVideoDialog({
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="video-request-occasion">Occasion</Label>
|
||||
<HelpTip label="Short label for the trigger event — shown as a badge throughout the pipeline, queue, and history">
|
||||
<Label htmlFor="video-request-occasion">Occasion</Label>
|
||||
</HelpTip>
|
||||
<Input
|
||||
id="video-request-occasion"
|
||||
placeholder="e.g. v0.19.0 launch, Founder's Day..."
|
||||
@@ -502,7 +506,9 @@ function RequestVideoDialog({
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="video-request-brief">Brief</Label>
|
||||
<HelpTip label="What the video should communicate — read by the assigned UX/UI dev when building the composition">
|
||||
<Label htmlFor="video-request-brief">Brief</Label>
|
||||
</HelpTip>
|
||||
<Textarea
|
||||
id="video-request-brief"
|
||||
placeholder="What should this video cover?"
|
||||
@@ -512,7 +518,9 @@ function RequestVideoDialog({
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>Platforms</Label>
|
||||
<HelpTip label="Where the rendered clip can post once you approve it — editable again before approving">
|
||||
<Label>Platforms</Label>
|
||||
</HelpTip>
|
||||
<div className="flex gap-4">
|
||||
{REQUEST_PLATFORMS.map((platform) => (
|
||||
<div key={platform} className="flex items-center gap-2">
|
||||
@@ -521,12 +529,20 @@ function RequestVideoDialog({
|
||||
checked={platforms.includes(platform)}
|
||||
onCheckedChange={() => togglePlatform(platform)}
|
||||
/>
|
||||
<Label
|
||||
htmlFor={`video-request-${platform}`}
|
||||
className="text-sm font-normal"
|
||||
<HelpTip
|
||||
label={
|
||||
platform === "x"
|
||||
? "Posts via X's OAuth 1.0a API, 280-char caption"
|
||||
: "Posts via TikTok's inbox-upload OAuth2 API, 2200-char caption"
|
||||
}
|
||||
>
|
||||
{PLATFORM_LABELS[platform]}
|
||||
</Label>
|
||||
<Label
|
||||
htmlFor={`video-request-${platform}`}
|
||||
className="text-sm font-normal"
|
||||
>
|
||||
{PLATFORM_LABELS[platform]}
|
||||
</Label>
|
||||
</HelpTip>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -654,10 +670,12 @@ export function VideoPostQueue({ className }: { className?: string }) {
|
||||
if (isLoading) return null;
|
||||
|
||||
const requestButton = (
|
||||
<Button variant="outline" size="sm" onClick={() => setRequestOpen(true)}>
|
||||
<Sparkles className="mr-1 h-4 w-4" />
|
||||
Request a video
|
||||
</Button>
|
||||
<HelpTip label="Opens a dialog to brief a UX/UI dev on an on-demand video, independent of a release or spotlight">
|
||||
<Button variant="outline" size="sm" onClick={() => setRequestOpen(true)}>
|
||||
<Sparkles className="mr-1 h-4 w-4" />
|
||||
Request a video
|
||||
</Button>
|
||||
</HelpTip>
|
||||
);
|
||||
|
||||
if (!posts || posts.length === 0) {
|
||||
@@ -696,7 +714,9 @@ export function VideoPostQueue({ className }: { className?: string }) {
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Film className="h-5 w-5" />
|
||||
Video Post Queue
|
||||
<Badge variant="secondary">{posts.length}</Badge>
|
||||
<HelpTip label="Rendered clips waiting for your preview, caption edits, approve, or reject">
|
||||
<Badge variant="secondary">{posts.length}</Badge>
|
||||
</HelpTip>
|
||||
</CardTitle>
|
||||
<CardAction>{requestButton}</CardAction>
|
||||
<CardDescription>
|
||||
@@ -727,7 +747,9 @@ export function VideoPostQueue({ className }: { className?: string }) {
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="video-reject-reason">Reason</Label>
|
||||
<HelpTip label="Stored on the draft and shown in History next to this rejection">
|
||||
<Label htmlFor="video-reject-reason">Reason</Label>
|
||||
</HelpTip>
|
||||
<Textarea
|
||||
id="video-reject-reason"
|
||||
placeholder="e.g. off-brand tone, wrong occasion..."
|
||||
|
||||
@@ -109,17 +109,23 @@ function XPostRow({
|
||||
</span>
|
||||
</HelpTip>
|
||||
{post.release_version && (
|
||||
<Badge variant="outline">v{post.release_version}</Badge>
|
||||
<HelpTip label="The release this post announces">
|
||||
<Badge variant="outline">v{post.release_version}</Badge>
|
||||
</HelpTip>
|
||||
)}
|
||||
{post.mention && (
|
||||
<Badge variant="secondary" className="max-w-56 truncate">
|
||||
re: {post.mention.text}
|
||||
</Badge>
|
||||
<HelpTip label="The X mention this draft replies to">
|
||||
<Badge variant="secondary" className="max-w-56 truncate">
|
||||
re: {post.mention.text}
|
||||
</Badge>
|
||||
</HelpTip>
|
||||
)}
|
||||
{post.feature && (
|
||||
<Badge variant="outline" className="max-w-56 truncate">
|
||||
feature: {post.feature.title}
|
||||
</Badge>
|
||||
<HelpTip label="The shipped feature this spotlight covers">
|
||||
<Badge variant="outline" className="max-w-56 truncate">
|
||||
feature: {post.feature.title}
|
||||
</Badge>
|
||||
</HelpTip>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -266,7 +272,9 @@ export function XPostQueue({ className }: { className?: string }) {
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Rocket className="h-5 w-5" />X Post Queue
|
||||
<Badge variant="secondary">{posts.length}</Badge>
|
||||
<HelpTip label="Drafts waiting for your edit, approve, or reject">
|
||||
<Badge variant="secondary">{posts.length}</Badge>
|
||||
</HelpTip>
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Drafted release announcements, feature spotlights, and mention
|
||||
@@ -297,7 +305,9 @@ export function XPostQueue({ className }: { className?: string }) {
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="x-reject-reason">Reason</Label>
|
||||
<HelpTip label="Stored on the draft and shown in History next to this rejection">
|
||||
<Label htmlFor="x-reject-reason">Reason</Label>
|
||||
</HelpTip>
|
||||
<Textarea
|
||||
id="x-reject-reason"
|
||||
placeholder="e.g. tone doesn't match our voice; not worth a public reply..."
|
||||
|
||||
Reference in New Issue
Block a user