From 4796e11c1c59215d07dee459e0649d2ba87dab7c Mon Sep 17 00:00:00 2001 From: David Anthony Date: Fri, 16 Oct 2026 14:58:14 -0700 Subject: [PATCH 1/3] feat(apollo-wind): add ReferenceChip for variables, resources and connections Add a shared ReferenceChip primitive that pairs the existing info tokens (background, text, icon) for valid references and the error tokens for invalid ones. PromptEditor's TokenPill and markdown preview now render through it, and VariableValueControl shows its bound variable as a chip. Docs: usage guidance with do/don't examples, an all-themes story, README section, and token usage notes on the Future colors page. Tests lock the token pairing so chips cannot drift to primary fills. Co-Authored-By: Claude Opus 5.5 --- packages/apollo-wind/README.md | 25 ++ .../components/ui/code-editors.stories.tsx | 2 +- .../apollo-wind/src/components/ui/index.ts | 6 +- .../components/MarkdownPreview.tsx | 6 +- .../ui/prompt-editor/components/TokenPill.tsx | 94 ++------ .../src/components/ui/prompt-editor/types.ts | 20 +- .../components/ui/reference-chip-colors.ts | 15 ++ .../components/ui/reference-chip.stories.tsx | 219 ++++++++++++++++++ .../src/components/ui/reference-chip.test.tsx | 101 ++++++++ .../src/components/ui/reference-chip.tsx | 106 +++++++++ .../components/ui/variable-value-control.tsx | 4 +- .../src/foundation/Future/colors.stories.tsx | 8 +- packages/apollo-wind/src/index.ts | 156 +++++++------ 13 files changed, 584 insertions(+), 178 deletions(-) create mode 100644 packages/apollo-wind/src/components/ui/reference-chip-colors.ts create mode 100644 packages/apollo-wind/src/components/ui/reference-chip.stories.tsx create mode 100644 packages/apollo-wind/src/components/ui/reference-chip.test.tsx create mode 100644 packages/apollo-wind/src/components/ui/reference-chip.tsx diff --git a/packages/apollo-wind/README.md b/packages/apollo-wind/README.md index 408e0e2b67..a404a11743 100644 --- a/packages/apollo-wind/README.md +++ b/packages/apollo-wind/README.md @@ -213,3 +213,28 @@ MIT - see [LICENSE](./LICENSE) **Peer Dependencies:** React ≥18.0.0 Built with ❤️ by UiPath | Inspired by [shadcn/ui](https://ui.shadcn.com) + +## Reference Chip + +`ReferenceChip` displays selected variables, resources and connections with paired +semantic background, text and icon colors. Find its API and state examples in +Storybook under **Apollo Wind → Components → Data Display → Reference Chip**. +The **Patterns → Code Editors → Editor Variables** example uses it through +`PromptEditor`; existing editor consumers need no API changes. + +```tsx +import { ReferenceChip } from '@uipath/apollo-wind'; + +} + onRemove={clearConnection} + removeLabel="Remove Outlook connection" +/> +``` + +The host supplies the icon, selection behavior and localized removal label. +`readOnly` hides removal, `disabled` disables removal, `invalid` uses the paired +error palette, and `selected` adds a visual outline. Keep removable chips outside +other buttons. Inside a picker trigger, omit `onRemove` and use a separate clear +button. Product connection fields must adopt this primitive to receive its styles. diff --git a/packages/apollo-wind/src/components/ui/code-editors.stories.tsx b/packages/apollo-wind/src/components/ui/code-editors.stories.tsx index 1d95172b43..ec109c1904 100644 --- a/packages/apollo-wind/src/components/ui/code-editors.stories.tsx +++ b/packages/apollo-wind/src/components/ui/code-editors.stories.tsx @@ -1205,7 +1205,7 @@ function EditorVariablesUsagePage() { ariaLabel="Prompt" />

- Try both: choose{' '} + PromptEditor uses the shared ReferenceChip for inserted variables. Try both: choose{' '} Insert → $vars → firstName above, or type $ in the editor and pick from the menu that appears. diff --git a/packages/apollo-wind/src/components/ui/index.ts b/packages/apollo-wind/src/components/ui/index.ts index 77ab25aa62..bb179a6529 100644 --- a/packages/apollo-wind/src/components/ui/index.ts +++ b/packages/apollo-wind/src/components/ui/index.ts @@ -54,6 +54,7 @@ export * from './message-scroller'; export * from './model-picker'; export * from './multi-select'; export * from './pagination'; +export * from './panel-tabs'; export * from './popover'; export * from './portal-container'; export * from './progress'; @@ -62,13 +63,15 @@ export * from './prompt-suggestions'; export * from './prompt-value-control'; export * from './quick-form-field'; export * from './radio-group'; +export { ReferenceChip, type ReferenceChipProps } from './reference-chip'; +export { getReferenceChipColors } from './reference-chip-colors'; export * from './resizable'; export * from './scroll-area'; export * from './search'; export * from './select'; export * from './separator'; -export * from './sidebar'; export * from './sheet'; +export * from './sidebar'; export * from './skeleton'; export * from './slider'; export * from './sonner'; @@ -78,7 +81,6 @@ export * from './stats-card'; export * from './stepper'; export * from './switch'; export * from './table'; -export * from './panel-tabs'; export * from './tabs'; export * from './textarea'; export * from './thinking-indicator'; diff --git a/packages/apollo-wind/src/components/ui/prompt-editor/components/MarkdownPreview.tsx b/packages/apollo-wind/src/components/ui/prompt-editor/components/MarkdownPreview.tsx index ea187234c2..a248ff9664 100644 --- a/packages/apollo-wind/src/components/ui/prompt-editor/components/MarkdownPreview.tsx +++ b/packages/apollo-wind/src/components/ui/prompt-editor/components/MarkdownPreview.tsx @@ -1,6 +1,7 @@ import DOMPurify from 'dompurify'; import { Marked } from 'marked'; import { useMemo } from 'react'; +import { getReferenceChipColors } from '../../reference-chip-colors'; import { usePromptEditorConfig } from '../prompt-editor-config'; import { type PromptEditorToken } from '../types'; import { buildTokenIconSvgMarkup } from './token-icon-markup'; @@ -13,6 +14,7 @@ const marked = new Marked({ async: false, gfm: true, breaks: true }); * do), and without a per-component JS `.css` import (which doesn't resolve in the bundleless build). * Scoped under `.prompt-editor-preview`; colors use design tokens. */ +const referenceColors = getReferenceChipColors().valid; const MARKDOWN_PREVIEW_STYLES = ` .prompt-editor-preview { color: var(--color-foreground); } .prompt-editor-preview-empty { color: var(--color-muted-foreground); } @@ -39,8 +41,8 @@ const MARKDOWN_PREVIEW_STYLES = ` .prompt-editor-preview th { font-weight: 600; background-color: var(--color-muted); } .prompt-editor-preview strong { font-weight: 700; } .prompt-editor-preview em { font-style: italic; } -.prompt-editor-preview .token-pill { display: inline-flex; align-items: center; gap: 3px; height: 20px; padding: 0 4px; border-radius: 4px; font-size: 13px; line-height: 20px; vertical-align: middle; background: var(--color-info-background); color: var(--color-info-text); } -.prompt-editor-preview .token-pill svg { display: block; flex-shrink: 0; color: var(--color-info-icon); width: 14px; height: 14px; } +.prompt-editor-preview .token-pill { display: inline-flex; align-items: center; gap: 3px; height: 20px; padding: 0 4px; border-radius: 4px; font-size: 13px; line-height: 20px; vertical-align: middle; background: ${referenceColors.background}; color: ${referenceColors.text}; } +.prompt-editor-preview .token-pill svg { display: block; flex-shrink: 0; color: ${referenceColors.icon}; width: 14px; height: 14px; } `; /** Host override for a variable pill's preview rendering (icon markup and/or label). */ diff --git a/packages/apollo-wind/src/components/ui/prompt-editor/components/TokenPill.tsx b/packages/apollo-wind/src/components/ui/prompt-editor/components/TokenPill.tsx index 2211ac4a25..86c3858539 100644 --- a/packages/apollo-wind/src/components/ui/prompt-editor/components/TokenPill.tsx +++ b/packages/apollo-wind/src/components/ui/prompt-editor/components/TokenPill.tsx @@ -1,8 +1,8 @@ import { Database, Paperclip, SquareFunction, Variable } from 'lucide-react'; import { memo } from 'react'; +import { ReferenceChip } from '../../reference-chip'; import { usePromptEditorConfig } from '../prompt-editor-config'; import type { PromptEditorDiffType, PromptEditorTokenType } from '../types'; -import { getPromptEditorTokenColors } from '../types'; /** Leading icon per token type — mirrors the SVG markup `MarkdownPreview` inlines for preview mode. */ const TOKEN_TYPE_ICON: Record< @@ -41,83 +41,27 @@ const TokenPillBase = ({ onMouseDown, }: TokenPillProps) => { const { strings } = usePromptEditorConfig(); - const PROMPT_EDITOR_TOKEN_COLORS = getPromptEditorTokenColors(); - const colors = - isInvalid && !diffType ? PROMPT_EDITOR_TOKEN_COLORS.invalid : PROMPT_EDITOR_TOKEN_COLORS.valid; const Icon = TOKEN_TYPE_ICON[tokenType]; - - const handleRemoveMouseDown = (e: React.MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - }; - - const handleRemoveClick = (e: React.MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - onRemove?.(); - }; - - const bgColor = diffType - ? diffType === 'added' - ? 'rgba(76, 175, 80, 0.15)' - : 'rgba(244, 67, 54, 0.15)' - : colors.background; - - const outerClassName = [ - 'relative inline-flex items-center align-middle gap-[3px] h-5 rounded px-1 text-[13px] leading-5 outline-offset-1', - readonly ? 'cursor-default' : 'cursor-pointer', - diffType === 'removed' ? 'line-through opacity-60' : '', - isSelected ? 'z-10' : '', - ] - .filter(Boolean) - .join(' '); - return ( - // biome-ignore lint/a11y/noStaticElementInteractions: the pill is a Lexical decorator chip; mousedown sets node selection. Keyboard selection is handled by Lexical at the editor root, and the chip exposes a focusable Remove button. - } + onRemove={onRemove} + removeLabel={strings.removeToken} + readOnly={readonly} + invalid={isInvalid && !diffType} + selected={isSelected} onMouseDown={onMouseDown} - className={outerClassName} - style={{ - backgroundColor: bgColor, - outline: isSelected ? `2px solid ${colors.border}` : 'none', - }} - > - - - - - {value} - - {!readonly && ( - - )} - + className={`${readonly ? 'cursor-default' : 'cursor-pointer'} ${diffType === 'removed' ? 'line-through opacity-60' : ''}`} + style={ + diffType + ? { + backgroundColor: + diffType === 'added' ? 'rgba(76, 175, 80, 0.15)' : 'rgba(244, 67, 54, 0.15)', + } + : undefined + } + /> ); }; diff --git a/packages/apollo-wind/src/components/ui/prompt-editor/types.ts b/packages/apollo-wind/src/components/ui/prompt-editor/types.ts index 2815c9e8a4..2fcf39d15b 100644 --- a/packages/apollo-wind/src/components/ui/prompt-editor/types.ts +++ b/packages/apollo-wind/src/components/ui/prompt-editor/types.ts @@ -1,3 +1,5 @@ +import { getReferenceChipColors } from '../reference-chip-colors'; + export type PromptEditorTokenType = 'input' | 'output' | 'state' | 'resource' | 'text'; interface BaseToken { @@ -89,23 +91,7 @@ export interface PromptEditorTokenColorConfig { * Two-state palette: invalid = red, valid = blue. Backed by apollo-wind's semantic design tokens, * which already resolve per light/dark theme via CSS — no JS theme detection needed. */ -export const getPromptEditorTokenColors = (): Record< - 'valid' | 'invalid', - PromptEditorTokenColorConfig -> => ({ - valid: { - background: 'var(--color-info-background)', - border: 'var(--color-info-icon)', - text: 'var(--color-info-text)', - icon: 'var(--color-info-icon)', - }, - invalid: { - background: 'var(--color-error-background)', - border: 'var(--color-error-icon)', - text: 'var(--color-error-text)', - icon: 'var(--color-error-icon)', - }, -}); +export const getPromptEditorTokenColors = getReferenceChipColors; /** The token-type label subset of `PromptEditorStrings` (structural, to avoid a config↔types cycle). */ export interface PromptEditorTokenTypeLabels { diff --git a/packages/apollo-wind/src/components/ui/reference-chip-colors.ts b/packages/apollo-wind/src/components/ui/reference-chip-colors.ts new file mode 100644 index 0000000000..27b29ea773 --- /dev/null +++ b/packages/apollo-wind/src/components/ui/reference-chip-colors.ts @@ -0,0 +1,15 @@ +/** Paired reference colors. Keep labels, icons and backgrounds on the same semantic palette. */ +export const getReferenceChipColors = () => ({ + valid: { + background: 'var(--color-info-background)', + border: 'var(--color-info-icon)', + text: 'var(--color-info-text)', + icon: 'var(--color-info-icon)', + }, + invalid: { + background: 'var(--color-error-background)', + border: 'var(--color-error-icon)', + text: 'var(--color-error-text)', + icon: 'var(--color-error-icon)', + }, +}); diff --git a/packages/apollo-wind/src/components/ui/reference-chip.stories.tsx b/packages/apollo-wind/src/components/ui/reference-chip.stories.tsx new file mode 100644 index 0000000000..3717b7f1a9 --- /dev/null +++ b/packages/apollo-wind/src/components/ui/reference-chip.stories.tsx @@ -0,0 +1,219 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { Check, Database, Mail, Variable, X } from 'lucide-react'; +import { type ReactNode, useState } from 'react'; +import { Button } from './button'; +import { ReferenceChip } from './reference-chip'; +import { getReferenceChipColors } from './reference-chip-colors'; + +const meta = { + title: 'Components/Data Display/Reference Chip', + component: ReferenceChip, + tags: ['autodocs'], + decorators: [ + (Story) => ( +

+ +
+ ), + ], + args: { label: 'vars.firstName', icon: }, + parameters: { + docs: { + description: { + component: `A compact reference to a variable, resource or connection. PromptEditor uses this primitive through TokenPill. The connection picker owns its popup and selection behavior; ReferenceChip owns the selected value's appearance. + +Colors come from existing semantic tokens, always as a pair from one family. Valid references use --color-info-background with --color-info-text and --color-info-icon. Invalid references use --color-error-background with --color-error-text and --color-error-icon. The selected outline uses the icon token of the same family. getReferenceChipColors() returns these values for hosts that cannot render the component. Do not fill a chip with a primary or accent color and pick a foreground separately: that is how low-contrast chips happen. Branded icons may retain their colors. The Themes story shows every theme side by side. + +Pass onRemove to expose a keyboard-accessible remove button and removeLabel for localization. readOnly hides removal; disabled disables it. selected is visual only: the host owns selection semantics. Keep a removable chip outside other buttons. Inside a picker trigger, omit onRemove and provide a separate clear button. + +Import { ReferenceChip } from '@uipath/apollo-wind'. Existing PromptEditor consumers inherit this treatment without changing their API. Product connection fields must adopt the component; this does not update external product repositories.`, + }, + }, + }, +} satisfies Meta; +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; + +export const States: Story = { + render: () => ( +
+ } onRemove={() => {}} /> + } selected onRemove={() => {}} /> + } + invalid + onRemove={() => {}} + /> + } disabled onRemove={() => {}} /> + } readOnly onRemove={() => {}} /> + } + onRemove={() => {}} + /> +
+ ), +}; + +function ConnectionExample() { + const [connection, setConnection] = useState('alex@example.com'); + return ( +
+

+ Microsoft Outlook 365 connection +

+
+ {connection ? ( + } + removeLabel="Remove Outlook connection" + onRemove={() => setConnection('')} + /> + ) : ( + No connection selected + )} +
+ {!connection && ( + + )} +

+ The same chip used by prompt variables, with a connection icon and accessible removal. +

+
+ ); +} +export const Connection: Story = { render: () => }; + +function GuidanceCard({ + kind, + note, + children, +}: { + kind: 'do' | 'dont'; + note: string; + children: ReactNode; +}) { + return ( +
+
+ {kind === 'do' ? ( +
+
{children}
+

{note}

+
+ ); +} + +function PickerTrigger({ children }: { children: ReactNode }) { + return ( +
+ {children} +
+ ); +} + +export const UsageGuidance: Story = { + name: 'Usage guidance', + parameters: { + // The Don't example fails contrast on purpose; keep the check on for every real chip. + a11y: { + config: { + rules: [{ id: 'color-contrast', selector: '*:not([data-dont-example])' }], + }, + }, + }, + render: () => ( +
+ + } onRemove={() => {}} /> + + + {/* Deliberately wrong: approximates a product chip reported with low contrast. */} + + + + +
+ + } /> + + +
+
+ + + } onRemove={() => {}} /> + + +
+ ), +}; + +const THEMES = [ + { className: 'light', label: 'Light' }, + { className: 'light-hc', label: 'Light high contrast' }, + { className: 'dark', label: 'Dark' }, + { className: 'dark-hc', label: 'Dark high contrast' }, + { className: 'future-light', label: 'Future light' }, + { className: 'future-dark', label: 'Future dark' }, +] as const; + +export const Themes: Story = { + parameters: { + docs: { + description: { + story: `Every theme on one page, for review and visual comparison. Valid chips use ${getReferenceChipColors().valid.background}; invalid chips use ${getReferenceChipColors().invalid.background}.`, + }, + }, + }, + render: () => ( +
+ {THEMES.map((theme) => ( +
+

{theme.label}

+ } onRemove={() => {}} /> + } selected onRemove={() => {}} /> + } invalid onRemove={() => {}} /> +
+ ))} +
+ ), +}; diff --git a/packages/apollo-wind/src/components/ui/reference-chip.test.tsx b/packages/apollo-wind/src/components/ui/reference-chip.test.tsx new file mode 100644 index 0000000000..c5b4b7b1ba --- /dev/null +++ b/packages/apollo-wind/src/components/ui/reference-chip.test.tsx @@ -0,0 +1,101 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { axe } from 'jest-axe'; +import { describe, expect, it, vi } from 'vitest'; +import { ReferenceChip } from './reference-chip'; +import { getReferenceChipColors } from './reference-chip-colors'; + +describe('ReferenceChip', () => { + it('removes by keyboard without activating the containing picker or submitting a form', async () => { + const user = userEvent.setup(); + const remove = vi.fn(); + const submit = vi.fn((event) => event.preventDefault()); + const hostClick = vi.fn(); + render( +
+ + + ); + await user.tab(); + expect(screen.getByRole('button', { name: 'Clear connection' })).toHaveFocus(); + await user.keyboard('{Enter}'); + expect(remove).toHaveBeenCalledOnce(); + expect(hostClick).not.toHaveBeenCalled(); + expect(submit).not.toHaveBeenCalled(); + }); + + it('preserves editor focus and does not select the chip when removing with the mouse', async () => { + const user = userEvent.setup(); + const select = vi.fn(); + const remove = vi.fn(); + render( + <> + + + + ); + screen.getByRole('textbox').focus(); + await user.click(screen.getByRole('button')); + expect(screen.getByRole('textbox')).toHaveFocus(); + expect(select).not.toHaveBeenCalled(); + expect(remove).toHaveBeenCalledOnce(); + }); + + it('does not expose removal without a handler or in read-only mode, and disables it when disabled', async () => { + const remove = vi.fn(); + const { rerender } = render(); + expect(screen.queryByRole('button')).not.toBeInTheDocument(); + rerender(); + expect(screen.queryByRole('button')).not.toBeInTheDocument(); + rerender(); + expect(screen.getByRole('button')).toBeDisabled(); + await userEvent.click(screen.getByRole('button')); + expect(remove).not.toHaveBeenCalled(); + }); + + it('pairs background, text and icon from one semantic family', () => { + const { rerender } = render(} selected />); + const chip = screen.getByText('Connection').closest('[data-slot="reference-chip"]'); + const icon = chip?.querySelector('[aria-hidden="true"]'); + expect(chip).toHaveStyle({ + backgroundColor: 'var(--color-info-background)', + color: 'var(--color-info-text)', + outline: '2px solid var(--color-info-icon)', + }); + expect(icon).toHaveStyle({ color: 'var(--color-info-icon)' }); + + rerender(} invalid />); + expect(chip).toHaveStyle({ + backgroundColor: 'var(--color-error-background)', + color: 'var(--color-error-text)', + }); + expect(icon).toHaveStyle({ color: 'var(--color-error-icon)' }); + }); + + it('never uses primary or accent tokens', () => { + const colors = Object.values(getReferenceChipColors()).flatMap(Object.values); + for (const value of colors) { + expect(value).toMatch(/^var\(--color-(info|error)-/); + } + }); + + it('has no accessibility violations with a custom decorative icon', async () => { + const { container } = render( + + Mail + + } + onRemove={() => {}} + /> + ); + expect(await axe(container)).toHaveNoViolations(); + }); +}); diff --git a/packages/apollo-wind/src/components/ui/reference-chip.tsx b/packages/apollo-wind/src/components/ui/reference-chip.tsx new file mode 100644 index 0000000000..e9b2842df9 --- /dev/null +++ b/packages/apollo-wind/src/components/ui/reference-chip.tsx @@ -0,0 +1,106 @@ +import { forwardRef, type HTMLAttributes, type ReactNode } from 'react'; +import { cn } from '@/lib'; +import { getReferenceChipColors } from './reference-chip-colors'; + +export interface ReferenceChipProps extends Omit, 'children'> { + /** Display name of the referenced variable, resource or connection. */ + label: string; + /** Decorative icon. Branded icons may preserve their original colors. */ + icon?: ReactNode; + onRemove?: () => void; + /** Localized accessible name for the remove button. */ + removeLabel?: string; + readOnly?: boolean; + disabled?: boolean; + invalid?: boolean; + /** Visual selection only. The containing editor or picker owns selection semantics. */ + selected?: boolean; +} + +/** Shared visual primitive. Picker behavior and editor selection remain with the host. */ +export const ReferenceChip = forwardRef( + ( + { + label, + icon, + onRemove, + removeLabel, + readOnly = false, + disabled = false, + invalid = false, + selected = false, + className, + style, + ...props + }, + ref + ) => { + const colors = getReferenceChipColors()[invalid ? 'invalid' : 'valid']; + return ( + + {icon && ( + + )} + + {label} + + {onRemove && !readOnly && ( + + )} + + ); + } +); +ReferenceChip.displayName = 'ReferenceChip'; diff --git a/packages/apollo-wind/src/components/ui/variable-value-control.tsx b/packages/apollo-wind/src/components/ui/variable-value-control.tsx index 1194c8c33f..c236d022b7 100644 --- a/packages/apollo-wind/src/components/ui/variable-value-control.tsx +++ b/packages/apollo-wind/src/components/ui/variable-value-control.tsx @@ -1,3 +1,4 @@ +import { Variable } from 'lucide-react'; import * as React from 'react'; import { joinIds } from '@/components/forms/aria-ids'; import { @@ -6,6 +7,7 @@ import { } from '@/components/ui/field-addons/value-mode-strings'; import { InputGroupPopoverTrigger } from '@/components/ui/input-group'; import { Popover, PopoverContent } from '@/components/ui/popover'; +import { ReferenceChip } from '@/components/ui/reference-chip'; import { VariablePickerContent, type VariablePickerItem } from '@/components/ui/variable-picker'; import { composeRefs } from '@/lib'; @@ -99,7 +101,7 @@ const VariableValueControl = React.forwardRef - {reference && {reference}} + {reference && } />} Date: Fri, 16 Oct 2026 14:58:15 -0700 Subject: [PATCH 2/3] fix(apollo-react): share reference chip colors in chat and flow examples The ap-chat resource chip now reads its background, text and icon colors from getReferenceChipColors, and the Flow Send Email example uses ReferenceChip for its connection and body variable. Co-Authored-By: Claude Opus 5.5 --- .../src/canvas/stories/templates/Flow.stories.tsx | 14 +++++++------- .../input/tiptap/resource-chip-node-view.tsx | 11 ++++++++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/apollo-react/src/canvas/stories/templates/Flow.stories.tsx b/packages/apollo-react/src/canvas/stories/templates/Flow.stories.tsx index 897fe5075a..cac8c82ef8 100644 --- a/packages/apollo-react/src/canvas/stories/templates/Flow.stories.tsx +++ b/packages/apollo-react/src/canvas/stories/templates/Flow.stories.tsx @@ -33,6 +33,7 @@ import { type QuickFormFieldMode, RadioGroup, RadioGroupItem, + ReferenceChip, RequiredIndicator, ResizableHandle, ResizablePanel, @@ -84,6 +85,7 @@ import { Redo2, SlidersHorizontal, Sparkles, + SquareFunction, StickyNote, Trash2, Underline, @@ -1326,10 +1328,7 @@ function SendEmailForm({ spacious = false }: { spacious?: boolean }) {
- - - anurag.krishna@uipath.com - + } />
@@ -1363,9 +1362,10 @@ function SendEmailForm({ spacious = false }: { spacious?: boolean }) { ))}
- - ƒx $vars.recordUpdated1.output.Description - + } + />
diff --git a/packages/apollo-react/src/material/components/ap-chat/components/input/tiptap/resource-chip-node-view.tsx b/packages/apollo-react/src/material/components/ap-chat/components/input/tiptap/resource-chip-node-view.tsx index 9ca64bffdd..b71a400b48 100644 --- a/packages/apollo-react/src/material/components/ap-chat/components/input/tiptap/resource-chip-node-view.tsx +++ b/packages/apollo-react/src/material/components/ap-chat/components/input/tiptap/resource-chip-node-view.tsx @@ -5,17 +5,21 @@ import { type NodeViewProps, NodeViewWrapper } from '@tiptap/react'; import token, { Typography } from '@uipath/apollo-core'; import { useChatState } from '@uipath/apollo-react/chat/headless/providers/chat-state-provider'; import { CHAT_RESOURCE_CHIP_MAX_WIDTH } from '@uipath/apollo-react/chat/service'; +import { getReferenceChipColors } from '@uipath/apollo-wind/components/ui/reference-chip-colors'; import React from 'react'; import { fontByVariant } from '../../../utils/font-by-variant'; import { AutopilotChatActionButton } from '../../common/action-button'; import { AutopilotChatTooltip } from '../../common/tooltip'; +// Shared with apollo-wind's ReferenceChip so every reference chip uses the same token pair. +const chipColors = getReferenceChipColors().valid; + const ChipContent = styled('span')<{ readonly?: boolean }>(({ readonly }) => ({ display: 'inline-flex', alignItems: 'center', padding: `0 ${token.Padding.PadS}`, - backgroundColor: 'var(--color-info-background)', - color: 'var(--color-info-text)', + backgroundColor: chipColors.background, + color: chipColors.text, borderRadius: `calc(${token.Border.BorderRadiusL} * 2)`, verticalAlign: 'middle', ...(!readonly && { @@ -27,6 +31,7 @@ const ChipContent = styled('span')<{ readonly?: boolean }>(({ readonly }) => ({ const ChipIcon = styled('span')(() => ({ fontFamily: '"Material Icons Outlined"', + color: chipColors.icon, fontSize: token.Icon.IconXs, flexShrink: 0, userSelect: 'none', @@ -49,7 +54,7 @@ const ChipDeleteContainer = styled('span')<{ visible: boolean; compactMode: bool transform: 'translateY(-50%)', display: 'flex', alignItems: 'center', - backgroundColor: 'var(--color-info-background)', + backgroundColor: chipColors.background, borderRadius: `calc(${token.Border.BorderRadiusL} * 2)`, transition: 'opacity 0.15s ease-in-out', From 54c827feae2f9ae2862ccc32e35b2a8327c87d34 Mon Sep 17 00:00:00 2001 From: David Anthony Date: Fri, 16 Oct 2026 14:58:16 -0700 Subject: [PATCH 3/3] docs(storybook): use ReferenceChip in the Gmail connection picker Co-Authored-By: Claude Opus 5.5 --- apps/storybook/src/patterns/DapLayoutsPage.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/storybook/src/patterns/DapLayoutsPage.tsx b/apps/storybook/src/patterns/DapLayoutsPage.tsx index 013b23a43d..c2c900b98d 100644 --- a/apps/storybook/src/patterns/DapLayoutsPage.tsx +++ b/apps/storybook/src/patterns/DapLayoutsPage.tsx @@ -27,6 +27,7 @@ import { PromptEditor, RadioGroup, RadioGroupItem, + ReferenceChip, RequiredIndicator, Search, Select, @@ -1043,10 +1044,7 @@ function GmailConnectionPickerExample() { variant="ghost" > {selectedConnection ? ( - - - {selectedConnection} - + } /> ) : ( Select a Gmail connection )}