From ad1ad4230e5693446f64ee74b93de8cd2292b982 Mon Sep 17 00:00:00 2001 From: Peter Vachon Date: Thu, 9 Jul 2026 10:56:02 -0400 Subject: [PATCH 1/5] docs(apollo-vertex): AI Toolkit v1.1 guidance content Add "Disclose in proportion" as second principle, add EU AI Act transparency note to Mark and wordmark section, and correct badge and button variant descriptors to frame variant choice as emphasis and placement rather than meaning. Add caveat notes for both subsections. Co-Authored-By: Claude Sonnet 4.6 --- .../app/guidelines/ai-toolkit/mark-usage.tsx | 27 ++++++++++++++----- .../app/guidelines/ai-toolkit/page.mdx | 3 +++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx b/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx index 0b3501688..2afde3e34 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx @@ -87,7 +87,7 @@ export function MarkUsage() { @@ -97,7 +97,7 @@ export function MarkUsage() { +

+ The label is sample text. Any AI label can take any variant, so choose + the variant by screen density and where the badge sits, not by the label. + The caveat that AI can make mistakes is separate: it is not a badge + passenger in any variant. It belongs to the surface around the content, + shown once at the recommendation or action level. +

+ - + ); diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx b/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx index c082e0a4b..4350e5d1d 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx @@ -6,6 +6,7 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; +import { AiCaveat } from "@/registry/ai-caveat/ai-caveat"; import { AiGlow } from "@/registry/ai-glow/ai-glow"; import { AiIcon } from "./ai-icon"; import { AiInput } from "./ai-input"; @@ -78,7 +79,7 @@ export function Surfaces() { @@ -102,13 +103,14 @@ export function Surfaces() { denial. + @@ -121,11 +123,12 @@ export function Surfaces() { recommended actions +
- + +
@@ -146,6 +150,15 @@ export function Surfaces() { Card (selectable) +

+ Caveat footer. The glow and badge carry the confidence, loud and up + top. The caveat sits quiet below a hairline, so the card can say this + is the pick and check it at the same time without the two signals + fighting. Use it only on cards that make a recommendation or offer an + action, once per card. Insight and observation cards do not need it, + they are already covered by the mark. For a group of cards, disclose + once at the group boundary, not on every card. +

@@ -185,6 +198,7 @@ export function Surfaces() { AI Identity
+
+ {children ?? "The output is AI generated. Please review."} +

+ ); + } + + return ( +
+
+ ); +} From 34eab006f5c6cc7dd33b451ce445f7b6af994970 Mon Sep 17 00:00:00 2001 From: Peter Vachon Date: Fri, 10 Jul 2026 07:56:33 -0400 Subject: [PATCH 3/5] =?UTF-8?q?feat(apollo-vertex):=20AI=20Toolkit=20v1.1?= =?UTF-8?q?=20=E2=80=94=20Legal=20index,=20nav,=20and=20content=20pass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Legal compliance index page with status badges, requirement coverage table, and source attribution; restructure AI Toolkit nav with Visual Expression and Legal children via _meta.ts; restructure Visual Expression title with metadata export and v1.1 AI badge; add withMark variant to AiCaveat with full placement/spacing JSDoc; wire AiCaveat across all AI surfaces (primary cards, selectable cards, plan selector, product grid, recommended actions); replace placeholder copy with canonical labels and real example content. Co-Authored-By: Claude Sonnet 4.6 --- .../app/guidelines/ai-toolkit/_meta.ts | 4 + .../guidelines/ai-toolkit/ai-input-field.tsx | 4 +- .../app/guidelines/ai-toolkit/input-field.tsx | 4 +- .../app/guidelines/ai-toolkit/legal/page.mdx | 120 ++++++++++++++++++ .../app/guidelines/ai-toolkit/mark-usage.tsx | 21 +-- .../app/guidelines/ai-toolkit/page.mdx | 9 +- .../ai-toolkit/selectable-cards.tsx | 4 +- .../app/guidelines/ai-toolkit/surfaces.tsx | 33 ++--- .../registry/ai-caveat/ai-caveat.tsx | 69 ++++++---- 9 files changed, 209 insertions(+), 59 deletions(-) create mode 100644 apps/apollo-vertex/app/guidelines/ai-toolkit/_meta.ts create mode 100644 apps/apollo-vertex/app/guidelines/ai-toolkit/legal/page.mdx diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/_meta.ts b/apps/apollo-vertex/app/guidelines/ai-toolkit/_meta.ts new file mode 100644 index 000000000..542f025e8 --- /dev/null +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/_meta.ts @@ -0,0 +1,4 @@ +export default { + index: "Visual Expression", + legal: "Legal", +}; diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/ai-input-field.tsx b/apps/apollo-vertex/app/guidelines/ai-toolkit/ai-input-field.tsx index d53569005..e78e05d80 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/ai-input-field.tsx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/ai-input-field.tsx @@ -16,7 +16,7 @@ import { AiIcon } from "./ai-icon"; export function AiInputField() { return ( - Job responsibility + Cost center
{/* Gradient definition for the mark. */}
+ In placeLive in the toolkit today. + PlannedComing in a near-term follow-up. + Handled elsewhereOwned by platform or product teams, outside the design system. +
+ +## Requirement coverage + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RequirementCovered byStatus
Show the user they are working with AIMark and wordmarkIn place
Mark AI-generated content visiblyAI generated badgeIn place
Prompt the user to review AI outputAiCaveat, on recommendation, action, and AI-content surfacesIn place
Show where the AI's information came fromSource line in the activity timelineIn place
State what the AI can and cannot doScope line (AI Chat pattern)Planned
Let the AI signal when it is unsureUncertainty statement (AI Chat pattern)Planned
Warn before sensitive data goes to a toolData-clearance and egress warnings (AI Chat pattern)Planned
Confirm before the AI takes an actionAction confirmation (AI Chat / actions pattern)Planned
Collect feedback with a disclosureFeedback vote widget disclosurePlanned
Data masking, access control, audit logs and retention, retrieval grounding, bias testing, human-in-the-loop configuration, approval workflowsOwned by platform, ML, and product teamsHandled elsewhere
+ +## Disclosure strings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StringSource in the docVerbatimWhere
"The output is AI generated. Please review."Human-review flagYes, verbatimAiCaveat default copy
"AI generated" (badge label)Transparency markingYes, as the labelBadge
Source line, e.g. "From [sources]"Explainability (described as a capability, no fixed phrase in the doc)N/A, our own UI labelTimeline marker
+ +## Source and legal basis + +Based on UiPath's internal in-product compliance guidance and the standards below. + +Legal basis: EU AI Act (Regulation (EU) 2024/1689), EU GDPR (Regulation 2016/679), the EU Charter of Fundamental Rights, the OECD Principles on AI, the EU HLEG Trustworthy AI Guidelines, and ISO/IEC 42001:2023. + +The requirement mapping and status reflect this team's interpretation of that guidance. diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx b/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx index 829b21357..40d3f2100 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx @@ -93,7 +93,7 @@ export function MarkUsage() { > - Picked for you + Best match

- The label is sample text. Any AI label can take any variant, so choose - the variant by screen density and where the badge sits, not by the label. - The caveat that AI can make mistakes is separate: it is not a badge - passenger in any variant. It belongs to the surface around the content, - shown once at the recommendation or action level. + These are sensible defaults; use them as-is when they fit. The variant + carries the meaning, not the label, so any label can take any variant; + choose by emphasis and how dense the surface is. The caveat that AI can + make mistakes is separate: it is not a badge passenger in any variant. + It belongs to the surface around the content, shown once at the + recommendation or action level.

@@ -197,10 +198,10 @@ export function MarkUsage() {

- The label is sample text. Any AI action can take any variant, so choose - the variant by how prominent the action should be and how dense the - surface is, not by the label. Keep one solid action per view so the - primary choice stays clear. + These are sensible defaults; use them as-is when they fit. The variant + carries the meaning, not the label, so any label can take any variant; + choose by how prominent the action should be and how dense the surface + is. Keep one solid action per view so the primary choice stays clear.

diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/page.mdx b/apps/apollo-vertex/app/guidelines/ai-toolkit/page.mdx index 6ee4ebac4..7f0f7d7db 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/page.mdx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/page.mdx @@ -1,11 +1,14 @@ +export const metadata = { title: 'AI Toolkit: Visual Expression' }; + import { ColorShowcase } from './color-showcase' +import { AiIcon } from './ai-icon' import { AiMark } from './ai-mark' import { MarkUsage } from './mark-usage' import { Surfaces } from './surfaces' import { Examples } from './examples' import { Badge } from '@/registry/badge/badge' -# AI Toolkit v1.0 +# Visual Expression v1.1 A working style guide for the AI expression across the design system: the mark (full size and small), the mark paired with the wordmark, and the mark inside @@ -69,3 +72,7 @@ Compositions that combine the mark, color, and components into real patterns. Each example shows the AI expression working alongside standard UI. + +--- + +For Legal: the [compliance index](/guidelines/ai-toolkit/legal) maps each disclosure requirement to how and where it is met in this toolkit. diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/selectable-cards.tsx b/apps/apollo-vertex/app/guidelines/ai-toolkit/selectable-cards.tsx index df03c5e1f..3d6f67b81 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/selectable-cards.tsx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/selectable-cards.tsx @@ -13,8 +13,8 @@ import { AiIcon } from "./ai-icon"; const CARDS = [ { - title: "Standard", - desc: "Uses primary color glow.", + title: "Open invoices", + desc: "1,248 this cycle, 37 flagged.", recommended: false, ai: false, }, diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx b/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx index 4350e5d1d..ec40a7ce6 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx @@ -116,11 +116,11 @@ export function Surfaces() { - Recommended action + Resubmit denied claims - A soft primary surface used for calling attention to - recommended actions + 12 have corrected modifiers ready and close their 90-day + window this week. @@ -128,17 +128,19 @@ export function Surfaces() {
- + -

- Matches your request. $350/unit cheaper with EPP applied. -

+
+

+ Matches your request. $350/unit cheaper with EPP applied. +

+ +
-
@@ -151,13 +153,14 @@ export function Surfaces() {

- Caveat footer. The glow and badge carry the confidence, loud and up - top. The caveat sits quiet below a hairline, so the card can say this - is the pick and check it at the same time without the two signals - fighting. Use it only on cards that make a recommendation or offer an - action, once per card. Insight and observation cards do not need it, - they are already covered by the mark. For a group of cards, disclose - once at the group boundary, not on every card. + Caveat footer. The glow and badge carry the confidence up top; the + caveat sits quiet below, marked by a small info icon. Show it wherever + AI generates content the user reads or acts on: recommendations, + actions, and AI-generated insights. The mark, badges, and buttons are + identity, not content, so they don't need it. Disclose once per + surface: a footer on a single card, once under the mark for a group + headed by the mark, and once below the group for a grid of + equal-height cards.

diff --git a/apps/apollo-vertex/registry/ai-caveat/ai-caveat.tsx b/apps/apollo-vertex/registry/ai-caveat/ai-caveat.tsx index 42c248a82..411a19e40 100644 --- a/apps/apollo-vertex/registry/ai-caveat/ai-caveat.tsx +++ b/apps/apollo-vertex/registry/ai-caveat/ai-caveat.tsx @@ -4,40 +4,59 @@ import { cn } from "@/lib/utils"; interface AiCaveatProps { /** - * `standalone` (default): leading muted info-circle icon + text. Use wherever - * the caveat is the first or only AI signal in that spot, so the icon marks - * it as a notice. + * `standalone` (default): info-circle icon + text. Use wherever the caveat + * is the first or only AI signal in that spot, so the icon marks it as a + * notice. Default for single-card footers and below-grid disclosures. * - * `withMark`: text only, no leading icon. Use ONLY when the caveat sits - * directly adjacent to the identity mark at a boundary, with nothing between - * the mark and the caveat. The mark carries the AI signal; repeating the icon - * would announce AI twice. + * `withMark`: text only, no icon. Use ONLY when locked directly under the + * identity mark at a group boundary, with nothing between the mark and the + * caveat. The mark carries the AI signal; the icon would be redundant. Text + * is indented (`pl-5`) to align under the mark label, not the mark icon. */ variant?: "standalone" | "withMark"; /** - * Caveat copy. Defaults to the canonical fallibility disclosure. Override - * only the action phrase ("continue", "finalize") when context genuinely - * differs. The reminder that AI can make mistakes stays constant. + * Caveat copy. Defaults to the approved verbatim string. Override via + * children only with Legal-cleared copy; do not rephrase the default. */ children?: React.ReactNode; className?: string; } /** - * A quiet caveat for AI recommendation cards. Renders a muted weight-400 line, - * optionally with a leading info-circle icon. + * A quiet fallibility disclosure for AI-generated content. * - * Tier rule: icon and text both stay `text-muted-foreground` (monochrome, - * unfilled). If either takes a color, the component has drifted into the - * warning tier and is wrong. + * ## When to show + * Wherever AI generates content the user reads or acts on: recommendations, + * actions, AI-generated insights, and summaries. Do NOT add it for identity + * or chrome alone (mark, badges, buttons, provenance markers). Disclose once + * per surface, never stacked on every element. * - * When to use: on cards that make a recommendation or offer an action, once - * per card. Insight and observation cards do not need it — they are already - * covered by the AI mark. For a group of cards, disclose once at the group - * boundary, not on every card. + * ## Variants + * - `standalone` (default): info icon + text. Footer on a single card, or a + * standalone notice below a grid of equal-height cards. + * - `withMark`: no icon, indented text. Only at a group boundary directly + * under the identity mark, nothing between. ~4px below the mark. * - * Do NOT add the AI mark, a badge, or a gradient here. The card header already - * marks the card as AI (mark once); this carries only the caveat. + * ## Placement rules + * - Single card: footer inside the card (`standalone`). + * - Group headed by a mark: once at the boundary under the mark (`withMark`), + * not per card. + * - Grid of equal-height cards: once below the grid (`standalone`), not per + * card, because a per-card footer fights the row's equal-height stretch. + * + * ## Spacing + * Content-to-caveat gap is 16px, owned by the component (`mt-4`). Host cards + * must use `gap-0` so the card's flex gap does not compound with `mt-4`. For + * `withMark`, callers use `className="-mt-2 mb-3"` to achieve the ~4px gap + * under the mark's `mb-3`. + * + * ## Tier rule + * Icon and text both stay `text-muted-foreground` (monochrome, unfilled). If + * either takes a color, the component has drifted into the warning tier. + * + * ## Copy + * Default is the approved verbatim string "The output is AI generated. Please + * review." Override via `children` only with Legal-cleared copy. */ export function AiCaveat({ variant = "standalone", @@ -46,9 +65,7 @@ export function AiCaveat({ }: AiCaveatProps) { if (variant === "withMark") { return ( -

+

{children ?? "The output is AI generated. Please review."}

); @@ -62,9 +79,7 @@ export function AiCaveat({ )} >
); } From ef2f976773d6830db8fec524bdc9253f0847a9b4 Mon Sep 17 00:00:00 2001 From: Peter Vachon Date: Fri, 10 Jul 2026 08:02:45 -0400 Subject: [PATCH 4/5] =?UTF-8?q?docs(apollo-vertex):=20AI=20Toolkit=20v1.1?= =?UTF-8?q?=20=E2=80=94=20public-safe=20cross-link=20and=20Legal=20page=20?= =?UTF-8?q?cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace internal "For Legal: compliance index" footer with a plain public cross-link; rename disclosure strings column "Source in the doc" to "Basis" and remove "in the doc" phrasing from cell copy; fix source-line anchor targets to #in-components where the timeline marker group actually lives. Co-Authored-By: Claude Sonnet 4.6 --- .../ai-toolkit/activity-timeline.tsx | 9 +++++--- .../app/guidelines/ai-toolkit/legal/page.mdx | 8 +++---- .../app/guidelines/ai-toolkit/mark-usage.tsx | 22 ++++++++++++++----- .../app/guidelines/ai-toolkit/page.mdx | 2 +- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/activity-timeline.tsx b/apps/apollo-vertex/app/guidelines/ai-toolkit/activity-timeline.tsx index a7f460713..7a7f5ae78 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/activity-timeline.tsx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/activity-timeline.tsx @@ -122,8 +122,8 @@ export function ActivityTimeline() {
    - {ACTIVITY.map((event, i) => { - const last = i === ACTIVITY.length - 1; + {ACTIVITY.map((event, idx) => { + const last = idx === ACTIVITY.length - 1; return (
  1. @@ -160,7 +160,10 @@ export function ActivityTimeline() { {event.sources.map((s, i) => ( {i > 0 && " and "} - + {s.label} diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/legal/page.mdx b/apps/apollo-vertex/app/guidelines/ai-toolkit/legal/page.mdx index 5657c6d9a..92ca5005e 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/legal/page.mdx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/legal/page.mdx @@ -42,7 +42,7 @@ How the AI Toolkit meets in-product AI transparency and disclosure requirements. Show where the AI's information came from - Source line in the activity timeline + Source line in the activity timeline In place @@ -84,7 +84,7 @@ How the AI Toolkit meets in-product AI transparency and disclosure requirements. String - Source in the doc + Basis Verbatim Where @@ -104,9 +104,9 @@ How the AI Toolkit meets in-product AI transparency and disclosure requirements. Source line, e.g. "From [sources]" - Explainability (described as a capability, no fixed phrase in the doc) + Explainability (a capability, no fixed phrase in the guidance) N/A, our own UI label - Timeline marker + Timeline marker diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx b/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx index 40d3f2100..1eb09339e 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx @@ -149,7 +149,11 @@ export function MarkUsage() {

    - +
  2. diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx b/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx index 1eb09339e..0cfaa9fed 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/mark-usage.tsx @@ -1,3 +1,5 @@ +"use client"; + import { Link2 } from "lucide-react"; import type { ReactNode } from "react"; import { Badge } from "@/components/ui/badge"; @@ -269,13 +271,21 @@ export function MarkUsage() { Compared price, warranty, and lead time

    - +

    diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/selectable-cards.tsx b/apps/apollo-vertex/app/guidelines/ai-toolkit/selectable-cards.tsx index 3d6f67b81..d9944e95c 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/selectable-cards.tsx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/selectable-cards.tsx @@ -89,7 +89,7 @@ export function SelectableCards() { style={{ background: "var(--ai-gradient-fill)" }} > - Picked for you + Best match )} diff --git a/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx b/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx index ec40a7ce6..963a89919 100644 --- a/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx +++ b/apps/apollo-vertex/app/guidelines/ai-toolkit/surfaces.tsx @@ -138,7 +138,7 @@ export function Surfaces() {

    Matches your request. $350/unit cheaper with EPP applied.

    - + diff --git a/apps/apollo-vertex/locales/en.json b/apps/apollo-vertex/locales/en.json index a569415e4..15b866a3c 100644 --- a/apps/apollo-vertex/locales/en.json +++ b/apps/apollo-vertex/locales/en.json @@ -15,6 +15,7 @@ "agents": "Agents", "agents_passed": "Agents passed", "ai_assistant": "AI Assistant", + "ai_caveat_default": "The output is AI generated. Please review.", "ai_response_disclaimer": "AI-generated responses should be reviewed for accuracy.", "all": "All", "all_tests_triggered": "All tests triggered", diff --git a/apps/apollo-vertex/registry/ai-caveat/ai-caveat.tsx b/apps/apollo-vertex/registry/ai-caveat/ai-caveat.tsx index 411a19e40..d49f00c67 100644 --- a/apps/apollo-vertex/registry/ai-caveat/ai-caveat.tsx +++ b/apps/apollo-vertex/registry/ai-caveat/ai-caveat.tsx @@ -1,85 +1,48 @@ +"use client"; + import { Info } from "lucide-react"; -import * as React from "react"; +import type * as React from "react"; +import { useTranslation } from "react-i18next"; import { cn } from "@/lib/utils"; interface AiCaveatProps { - /** - * `standalone` (default): info-circle icon + text. Use wherever the caveat - * is the first or only AI signal in that spot, so the icon marks it as a - * notice. Default for single-card footers and below-grid disclosures. - * - * `withMark`: text only, no icon. Use ONLY when locked directly under the - * identity mark at a group boundary, with nothing between the mark and the - * caveat. The mark carries the AI signal; the icon would be redundant. Text - * is indented (`pl-5`) to align under the mark label, not the mark icon. - */ + /** `standalone` (default): icon + text. `withMark`: text only, indented to sit under an identity mark. */ variant?: "standalone" | "withMark"; - /** - * Caveat copy. Defaults to the approved verbatim string. Override via - * children only with Legal-cleared copy; do not rephrase the default. - */ + /** Caveat copy. Defaults to the approved disclosure string. */ children?: React.ReactNode; className?: string; } -/** - * A quiet fallibility disclosure for AI-generated content. - * - * ## When to show - * Wherever AI generates content the user reads or acts on: recommendations, - * actions, AI-generated insights, and summaries. Do NOT add it for identity - * or chrome alone (mark, badges, buttons, provenance markers). Disclose once - * per surface, never stacked on every element. - * - * ## Variants - * - `standalone` (default): info icon + text. Footer on a single card, or a - * standalone notice below a grid of equal-height cards. - * - `withMark`: no icon, indented text. Only at a group boundary directly - * under the identity mark, nothing between. ~4px below the mark. - * - * ## Placement rules - * - Single card: footer inside the card (`standalone`). - * - Group headed by a mark: once at the boundary under the mark (`withMark`), - * not per card. - * - Grid of equal-height cards: once below the grid (`standalone`), not per - * card, because a per-card footer fights the row's equal-height stretch. - * - * ## Spacing - * Content-to-caveat gap is 16px, owned by the component (`mt-4`). Host cards - * must use `gap-0` so the card's flex gap does not compound with `mt-4`. For - * `withMark`, callers use `className="-mt-2 mb-3"` to achieve the ~4px gap - * under the mark's `mb-3`. - * - * ## Tier rule - * Icon and text both stay `text-muted-foreground` (monochrome, unfilled). If - * either takes a color, the component has drifted into the warning tier. - * - * ## Copy - * Default is the approved verbatim string "The output is AI generated. Please - * review." Override via `children` only with Legal-cleared copy. - */ +/** A quiet fallibility disclosure for AI-generated content. */ export function AiCaveat({ variant = "standalone", children, className, }: AiCaveatProps) { + const { t } = useTranslation(); + const defaultCopy = t("ai_caveat_default", { + defaultValue: "The output is AI generated. Please review.", + }); + if (variant === "withMark") { return ( -

    - {children ?? "The output is AI generated. Please review."} -

    + + {children ?? defaultCopy} + ); } return ( -
    + {children ?? defaultCopy} + ); }