diff --git a/README.md b/README.md index 63a51022c8..4d25f86713 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ packages/dev/ # Dev tooling (storybook-addon-helpers, enviro apps/docs/ # Storybook documentation apps/site/ # Documentation site (Next.js) configs/ # Shared build and test configs +skills/ # Consumer-facing agent skills ``` ## Packages @@ -81,6 +82,37 @@ configs/ # Shared build and test configs See individual package READMEs for installation and usage instructions. +### Antares Builder skill + +[Antares Builder](./skills/antares-builder/SKILL.md) helps coding agents build +consumer interfaces with the public `@godaddy/antares` API. Run either command +from your consuming application: + +```sh +npx skills add godaddy/antares --skill antares-builder --agent codex +``` + +Or, with [Agent Package Manager (APM)](https://microsoft.github.io/apm/) installed: + +```sh +apm install godaddy/antares --skill antares-builder --target codex +``` + +Select your agent with `--agent` for the skills CLI or `--target` for APM; for +example, use `claude-code` with the skills CLI or `claude` with APM. The installer +places the skill and its references in the consumer's agent directory. + +Then ask your agent, for example: + +> Build a responsive settings form with Antares, including validation and a confirmation dialog. + +The root [`apm.yml`](./apm.yml) describes the published `skills/` collection. +Contributor tooling stays in `.agents/skills/`. The collection is versioned +independently of `@godaddy/antares`; keep its version aligned with the skill's +`metadata.version` for releases of this single-skill collection. To pin an APM +release, append `#` to `godaddy/antares` and commit the consumer's +`apm.yml` and `apm.lock.yaml`. + ## Documentation Documentation is powered by Storybook and a Next.js docs site. diff --git a/apm.yml b/apm.yml new file mode 100644 index 0000000000..47b4cbb62b --- /dev/null +++ b/apm.yml @@ -0,0 +1,14 @@ +name: antares-skills +version: "0.1.0" +description: Skills for building React interfaces with the public Antares API. +author: GoDaddy LLC +license: MIT +repository: https://github.com/godaddy/antares +keywords: + - godaddy + - antares + - react + - design-system + - skills +type: skill +includes: auto diff --git a/packages/@godaddy/antares/README.mdx b/packages/@godaddy/antares/README.mdx index f64818a7cc..7021dd044b 100644 --- a/packages/@godaddy/antares/README.mdx +++ b/packages/@godaddy/antares/README.mdx @@ -38,6 +38,20 @@ import { BarChart } from '@godaddy/antares/Chart'; This also works with autocomplete in IDEs and LLMs, so you can import from the root package and let your editor/agent suggest the available components. +## AI Agent Skills + +Install the `antares-builder` skill from your consuming application's directory so AI coding agents can build with Antares: + +```bash +npx skills add godaddy/antares --skill antares-builder --agent claude-code +``` + +Select your coding agent with `--agent` (e.g. `claude-code`, `codex`); omit it to be prompted. The installer places the skill and its references into the consumer app's agent directory. Then ask your agent, for example: + +> Build a responsive settings form with Antares, including validation and a confirmation dialog. + +See the [repository README](https://github.com/godaddy/antares#antares-builder-skill) for the full reference, including an Agent Package Manager (APM) alternative and version-pinning notes. + ## Framework Setup Antares ships CSS alongside its JavaScript modules. Each component chunk imports a corresponding `.css` file (e.g., `import './src-BZhWcxqJ.css'`). Most bundlers handle this automatically, but some frameworks need extra configuration to process CSS imports from `node_modules`. diff --git a/skills/antares-builder/SKILL.md b/skills/antares-builder/SKILL.md new file mode 100644 index 0000000000..d924b1c83d --- /dev/null +++ b/skills/antares-builder/SKILL.md @@ -0,0 +1,49 @@ +--- +name: antares-builder +description: Build, adapt, fix, or review React interfaces with @godaddy/antares. Use for component selection and composition, forms, accessible interactions, responsive layouts, charts (including chart data and rendering bugs), and consumer setup. Do not use for authoring the Antares library itself. +metadata: + version: "0.1.0" + author: GoDaddy LLC +--- + +# Antares Builder + +Build consumer UI with the public `@godaddy/antares` API. Choose the interaction before its appearance. Many components use React Aria Components (RAC); Antares's own exports, props and slots define the consumer contract. + +Follow the steps relevant to the request. Load only the reference sections needed for the selected feature. + +## Step 1 — Read the project context + +Inspect `package.json`, the lockfile, framework configuration and existing components and pages in the consuming application. Identify the Antares version, package manager, routing, form library, CSS conventions and locale. Preserve those conventions when adapting existing UI. + +Resolve the Antares version used by the consuming application and verify its public exports and types before using unfamiliar APIs. Use the [Antares repository](https://github.com/godaddy/antares) for documentation matching that version. When sources disagree, prioritize the installed public API over documentation and this skill's examples. + +For installation, imports, CSS failures or server/client boundaries, read the relevant [setup](references/setup.md) sections. + +Use public root or subpath imports. Do not derive Antares APIs from another design system or import `#components/*`, `dist` files or transitive internals. + +## Step 2 — Choose the component by behavior + +Identify the action, value, navigation or information the user needs. Read the relevant branch of the [component decision tree](references/component-decision-tree.md) when choosing a component or comparing alternatives. The decision tree and examples describe one point in Antares's release history. Before using a component the tree recommends, verify it — and the specific props/children an example shows — still exist in the installed version's public exports and types: a newer install may add components the tree doesn't list yet, and an older install may lack a component the tree recommends or expose different props for it. If no matching export exists, use the application's established solution or semantic HTML and explain the gap. + +## Step 3 — Arrange and style the interface + +For page structure, responsive behavior, typography, icons or sizing, read [layout and styling](references/layout-and-styling.md). Prefer Antares's existing variants and layout primitives. Responsive changes use the application's CSS media/container queries; Antares has no breakpoint prop syntax or mandatory provider. + +## Step 4 — Compose the selected components + +Read the relevant [composition patterns](references/composition-patterns.md) for slots and state, collections, disclosures, tabs, overlays, files or feedback. For any chart implementation or customization, read [charts](references/charts.md). Include the required children and wire controlled callbacks. A RAC base provides behavior but does not render missing Antares parts. + +## Step 5 — Build complete forms + +For form UI, follow [fields and validation](references/composition-patterns.md#fields-and-validation), then the selection, date or file sections as needed. Field roots own validation and relationships; `Input` and `TextArea` are controls within them. Integrate with the application's submission and error handling rather than introducing a second form architecture. + +## Step 6 — Supply the accessibility the app owns + +Provide visible field labels, names for icon-only controls and collections, suitable heading levels and image alternatives. Preserve the selected component's keyboard model, focus indicator and DOM semantics. For dialogs, follow the title, dismissal and focus contracts in [modal layers](references/composition-patterns.md#modal-layers). Check locale/RTL when the feature depends on direction or date/number formatting. + +## Step 7 — Verify and deliver + +Use the consumer project's task runner for appropriate type, lint, build and meaningful interaction checks. Verify labels, validation, overlay focus/return, loading/empty states and narrow layouts for the changed feature. Advice-only requests need focused API inspection rather than unrelated tasks. + +For implementation, deliver runnable code with real imports and data flow, then briefly explain the component choices and any gap. For review, report actionable findings and minimal fixes. diff --git a/skills/antares-builder/evals/evals.json b/skills/antares-builder/evals/evals.json new file mode 100644 index 0000000000..7df9c29b94 --- /dev/null +++ b/skills/antares-builder/evals/evals.json @@ -0,0 +1,183 @@ +{ + "skill_name": "antares-builder", + "evals": [ + { + "id": 1, + "prompt": "Adapt the supplied contact form to Antares. Keep ExistingContactForm and its save prop. Use Antares field components and no third-party form library. Validate email, preserve its label and help, prevent duplicate saves, and announce success or a retryable error.", + "expected_output": "An Antares form with inline field validation and async saving.", + "files": ["evals/files/contact-form.tsx.txt"], + "assertions": [ + "Uses TextField, Label, Input and FieldError with associated help.", + "Invalid email activates the Antares field error state, shows its associated FieldError, receives focus, and does not call save.", + "Valid submission calls save({ email }); pending requests prevent duplicate saves.", + "Failure retains the value and announces an error; success is announced only after saving resolves." + ] + }, + { + "id": 2, + "prompt": "Build Antares preferences for email/SMS opt-ins, one of three shipping plans, and a notifications toggle. Show current choices and support keyboard use.", + "expected_output": "Working independent, exclusive and on/off preferences.", + "files": [], + "assertions": [ + "A labeled CheckboxGroup allows independent email and SMS choices.", + "A labeled RadioGroup keeps exactly one shipping plan selected.", + "A labeled Switch controls notifications; keyboard changes update displayed choices." + ] + }, + { + "id": 3, + "prompt": "Build an Antares form with a required country popup and a visible multi-select region list. Include a country option with an icon and description. Show selections and country errors; changing country must preserve regions.", + "expected_output": "A working Select and multi-select ListBox with country validation.", + "files": [], + "assertions": [ + "Uses a labeled Select with a trigger, SelectOptions and SelectItem.", + "Uses an Antares multi-select ListBox with an accessible name (e.g. aria-label), stable item IDs, and accessible option labels and descriptions.", + "Selections update correctly; missing country blocks submission with an associated error, and country changes preserve regions." + ] + }, + { + "id": 4, + "prompt": "Use Antares for a Rename/Duplicate menu, a popover filter form, and help shown on hover or focus. Wire the actions and make all triggers keyboard accessible.", + "expected_output": "Menu, Popover and Tooltip used for their matching interactions.", + "files": [], + "assertions": [ + "MenuTrigger, Menu and MenuItem invoke working Rename/Duplicate handlers.", + "PopoverTrigger opens the filter form; TooltipTrigger shows non-interactive help on hover or focus.", + "Triggers have accessible names; menu/popover support keyboard access, dismissal and focus return." + ] + }, + { + "id": 5, + "prompt": "Add an Antares stay date-range picker with a visible label. Make only 2026-12-25 unavailable, preserve selected start and end as date-only values, and support keyboard selection and focus return.", + "expected_output": "An accessible Antares date-range picker with one unavailable date and timezone-stable values.", + "files": [], + "assertions": [ + "DateRangePicker has a visible label, working trigger and DateRangePickerCalendar.", + "Selection updates date-only start/end values without timezone shifts; only 2026-12-25 is unavailable.", + "Keyboard users can open, select a range, dismiss the calendar, and return focus to the trigger." + ] + }, + { + "id": 6, + "prompt": "Build an Antares FAQ with at most one answer open, plus Profile/Billing tabs. Support keyboard use and accessible expanded/selected states.", + "expected_output": "A working Accordion and Tabs interface.", + "files": [], + "assertions": [ + "Accordion coordinates Collapsible sections with at most one answer open.", + "Tabs has a named TabList and matching Tab/TabPanel IDs within TabPanels.", + "Keyboard interaction updates content and expanded/selected states." + ] + }, + { + "id": 7, + "prompt": "Build ConfirmOrder with Antares and an onConfirm(): Promise prop. Review order opens a titled modal. Allow Back/Escape before submission; block closing and duplicate requests while pending. Keep errors open, close on success, and return focus to the trigger.", + "expected_output": "A modal that follows the async confirmation lifecycle.", + "files": [], + "assertions": [ + "The titled Modal opens from Review order, traps focus and blocks background interaction.", + "Confirm calls onConfirm; failure keeps an error visible, and success closes the modal.", + "Pending confirmation blocks duplicate requests and all dismissal paths.", + "Back/Escape dismiss before submission; closing restores focus to Review order." + ] + }, + { + "id": 8, + "prompt": "Build an Antares product grid: one column below 48rem, three at or above it. Use a medium gap and the existing stylesheet; long names must not overflow the page.", + "expected_output": "A responsive Grid styled through consumer CSS.", + "files": [], + "assertions": [ + "Stylesheet rules set one column below 48rem and three at or above it, without conflicting inline columns.", + "Uses supported medium spacing.", + "Long names and narrow containers cause no horizontal page overflow." + ] + }, + { + "id": 9, + "prompt": "Build RevenueDashboard with Antares and dashboard-data.json: regional revenue in USD, monthly revenue with February missing, traffic share, and health 3/5. Preserve the data, provide text equivalents, and support 390px and 1024px. Export the component and stylesheet.", + "expected_output": "A responsive, accessible dashboard with accurate charts.", + "files": ["evals/files/dashboard-data.json"], + "assertions": [ + "Regional revenue and traffic shares match the supplied data, labels and units.", + "Months stay chronological; February remains missing, not zero or an interpolated line.", + "GaugeChart shows value 3 with five segments and a 3/5 label.", + "Charts have accessible names and text/table equivalents, and render without page overflow at 390px and 1024px." + ] + }, + { + "id": 10, + "prompt": "Using only the installed public Antares API, advise whether Antares supports a searchable country selector. Work offline. Do not edit files, install dependencies or compile. If no public Antares search control exists, explain the gap and the closest supported Antares components; do not recommend another library.", + "expected_output": "An evidence-based recommendation limited to the installed public Antares API.", + "files": [], + "assertions": [ + "Component and prop claims cite installed Antares public exports or declarations only.", + "Recommends a verified keyboard-accessible Antares search control, or explains that none exists and identifies the closest supported Antares components without inventing exports.", + "Respects offline, advice-only scope; does not edit files, install dependencies, compile, or recommend another library." + ] + }, + { + "id": 11, + "prompt": "Build a document library: let users browse or drag-drop files to upload, show the uploaded files in a paginated grid of cards, and let each file be removed.", + "expected_output": "A working upload surface with a paginated, removable card grid of uploaded files.", + "files": [], + "assertions": [ + "FileTrigger offers a keyboard-accessible browse button and DropZone accepts drag/drop; both add to the same uploaded-files list.", + "Uploaded files render as Cards with stable IDs and accessible names; Pagination has named previous/next controls and reflects the current/total pages correctly.", + "Removing a file updates the card grid and the pagination count without losing the other uploaded files." + ] + }, + { + "id": 12, + "prompt": "Build a 3-step onboarding wizard: a ProgressSteps indicator tracks the current step, and the middle step shows a feature carousel users can browse with next/prev controls.", + "expected_output": "A working wizard with step progress and a keyboard-accessible feature carousel.", + "files": [], + "assertions": [ + "ProgressSteps shows the zero-based currentStep and the middle step's Carousel supports keyboard and button navigation between slides, each with a meaningful label.", + "Advancing or returning between wizard steps preserves state correctly without resetting unrelated progress." + ] + }, + { + "id": 13, + "prompt": "Build a profile card that shows Skeleton placeholders matching the final layout (a circular avatar plus two lines of text) while the profile loads, then swaps to the real content once it arrives.", + "expected_output": "An accessible loading state that previews the real layout and hands off cleanly to real content.", + "files": [], + "assertions": [ + "Skeleton composition matches the final layout: a circular avatar (rounding=\"full\", width equal to height) plus two text-line Skeletons of differing widths.", + "The loading region is marked with role=\"status\", aria-busy=\"true\" and a descriptive aria-label while loading.", + "Once data resolves, aria-busy is set to false (or removed) and the real content fully replaces the Skeletons — no stale placeholders left visible." + ] + }, + { + "id": 14, + "prompt": "The attached file lists our installed Antares version's public type declarations. Build a searchable country selector with autocomplete filtering using Antares. Check the attached declarations before assuming Antares has no combobox.", + "expected_output": "An Antares combobox built from the installed version's actual exports.", + "files": ["evals/files/installed-types-newer.d.ts.txt"], + "assertions": [ + "Inspects the attached installed declarations rather than relying solely on the skill's API-gaps list, which still says Combobox does not exist.", + "Implements the installed Combobox/ComboboxTrigger/ComboboxOptions/ComboboxItem API from the fixture, not a hand-rolled autocomplete or a Select+ListBox substitute.", + "Wires selectedKey/onSelectionChange and inputValue/onInputChange per the attached declarations." + ] + }, + { + "id": 15, + "prompt": "The attached file lists our installed Antares version's public exports. Build a profile card with a loading placeholder that previews the final avatar-plus-two-lines layout before data arrives.", + "expected_output": "A loading placeholder built only from exports that actually exist at the installed version.", + "files": ["evals/files/installed-types-older.d.ts.txt"], + "assertions": [ + "Notices Skeleton is absent from the attached installed exports and does not import or render it, despite the skill's guidance recommending Skeleton for loading placeholders.", + "Falls back to a capability the installed exports actually support (e.g. existing progress/loading primitives or a semantic ARIA-busy placeholder) rather than inventing a Skeleton export.", + "States to the user that Skeleton isn't available at the installed version and explains what it used instead." + ] + }, + { + "id": 16, + "prompt": "The attached file is our installed Antares version's ProgressBar type declaration. Build a labeled file-upload progress bar with helper text below it, like 'Uploading... 42%'. Use the installed API, not older examples that may still show label/helperText props.", + "expected_output": "A ProgressBar composed per the installed declaration, with no removed props.", + "files": ["evals/files/installed-types-progressbar.d.ts.txt"], + "assertions": [ + "Composes Label, the value/track Box slots and a Text description per the attached declaration instead of passing label or helperText props to ProgressBar.", + "Does not reference a label or helperText prop on ProgressBar anywhere in the output.", + "The progress bar still has a correctly associated accessible name and description in the composed markup." + ] + } + ] +} diff --git a/skills/antares-builder/evals/files/contact-form.tsx.txt b/skills/antares-builder/evals/files/contact-form.tsx.txt new file mode 100644 index 0000000000..276185315d --- /dev/null +++ b/skills/antares-builder/evals/files/contact-form.tsx.txt @@ -0,0 +1,17 @@ +type Values = { email: string }; + +export function ExistingContactForm({ save }: { save: (values: Values) => Promise }) { + return ( +
+ +

We'll send receipts here.

+ + +
+ ); +} diff --git a/skills/antares-builder/evals/files/dashboard-data.json b/skills/antares-builder/evals/files/dashboard-data.json new file mode 100644 index 0000000000..2ebe5289bc --- /dev/null +++ b/skills/antares-builder/evals/files/dashboard-data.json @@ -0,0 +1,45 @@ +{ + "currency": "USD", + "regions": [ + { + "id": "na", + "region": "North America", + "revenue": 12000 + }, + { + "id": "eu", + "region": "Europe", + "revenue": 9000 + } + ], + "monthlyRevenue": [ + { + "month": "2026-01-01", + "revenue": 12000 + }, + { + "month": "2026-02-01", + "revenue": null + }, + { + "month": "2026-03-01", + "revenue": 15000 + } + ], + "traffic": [ + { + "id": "organic", + "name": "Organic", + "value": 70 + }, + { + "id": "direct", + "name": "Direct", + "value": 30 + } + ], + "health": { + "value": 3, + "segments": 5 + } +} diff --git a/skills/antares-builder/evals/files/installed-types-newer.d.ts.txt b/skills/antares-builder/evals/files/installed-types-newer.d.ts.txt new file mode 100644 index 0000000000..2b2ac8b435 --- /dev/null +++ b/skills/antares-builder/evals/files/installed-types-newer.d.ts.txt @@ -0,0 +1,48 @@ +// Installed @godaddy/antares type declarations (partial root export list). +// This is a NEWER install than the version the antares-builder skill's +// decision tree and "API gaps" list were written against. + +export declare function Button(props: ButtonProps): JSX.Element; +export declare function TextField(props: TextFieldProps): JSX.Element; +export declare function Select(props: SelectProps): JSX.Element; +export declare function ListBox(props: ListBoxProps): JSX.Element; + +// Added since the skill's decision tree was written. Not mentioned anywhere +// in component-decision-tree.md or composition-patterns.md. +export declare function Combobox(props: ComboboxProps): JSX.Element; +export declare function ComboboxTrigger(props: ComboboxTriggerProps): JSX.Element; +export declare function ComboboxOptions(props: ComboboxOptionsProps): JSX.Element; +export declare function ComboboxItem(props: ComboboxItemProps): JSX.Element; + +export interface ComboboxProps { + /** Accessible label for the combobox trigger/input. */ + label?: React.ReactNode; + /** Collection items rendered as ComboboxItem children. */ + items?: Iterable; + /** Controlled filter text shown in the input. */ + inputValue?: string; + /** Called when the user edits the filter text. */ + onInputChange?: (value: string) => void; + /** Controlled selected item key. */ + selectedKey?: React.Key | null; + /** Called when the selected item changes. */ + onSelectionChange?: (key: React.Key | null) => void; + /** Disallows free text; selection must match a listed item. */ + allowsCustomValue?: boolean; + children?: React.ReactNode; +} + +export interface ComboboxTriggerProps { + children?: React.ReactNode; +} + +export interface ComboboxOptionsProps { + items?: Iterable; + children?: React.ReactNode | ((item: T) => React.ReactNode); +} + +export interface ComboboxItemProps { + id: React.Key; + textValue?: string; + children?: React.ReactNode; +} diff --git a/skills/antares-builder/evals/files/installed-types-older.d.ts.txt b/skills/antares-builder/evals/files/installed-types-older.d.ts.txt new file mode 100644 index 0000000000..18c4848f23 --- /dev/null +++ b/skills/antares-builder/evals/files/installed-types-older.d.ts.txt @@ -0,0 +1,37 @@ +// Installed @godaddy/antares type declarations (partial root export list). +// This is an OLDER install than the version the antares-builder skill's +// decision tree currently documents. +// +// Notably absent: Skeleton. The skill's decision tree recommends Skeleton +// for "content still loading" placeholders, but this installed version +// predates that component — it is not part of this export list. + +export declare function Button(props: ButtonProps): JSX.Element; +export declare function Avatar(props: AvatarProps): JSX.Element; +export declare function Text(props: TextProps): JSX.Element; +export declare function Flex(props: FlexProps): JSX.Element; +export declare function Box(props: BoxProps): JSX.Element; +export declare function CircularProgress(props: CircularProgressProps): JSX.Element; +export declare function ProgressBar(props: ProgressBarProps): JSX.Element; + +export interface AvatarProps { + src?: string; + alt?: string; + size?: 'sm' | 'md' | 'lg'; +} + +export interface CircularProgressProps { + 'aria-label'?: string; + isIndeterminate?: boolean; + value?: number; +} + +export interface ProgressBarProps { + 'aria-label'?: string; + label?: React.ReactNode; + helperText?: React.ReactNode; + value?: number; + isIndeterminate?: boolean; +} + +// No Skeleton export exists in this installed version. diff --git a/skills/antares-builder/evals/files/installed-types-progressbar.d.ts.txt b/skills/antares-builder/evals/files/installed-types-progressbar.d.ts.txt new file mode 100644 index 0000000000..1e7bbef829 --- /dev/null +++ b/skills/antares-builder/evals/files/installed-types-progressbar.d.ts.txt @@ -0,0 +1,38 @@ +// Installed @godaddy/antares type declarations for ProgressBar. +// +// Breaking change from an older skill example or memory: `label` and +// `helperText` props were REMOVED. ProgressBar is now composed from +// Label, Box (value/track slots) and Text as children instead. + +export interface ProgressBarProps { + /** Composed label, value, track, and description. A function receives progress state. */ + children?: React.ReactNode | ((state: ProgressBarRenderProps) => React.ReactNode); + + /** Accessible value text and default value-slot content. Does not add visible output. */ + valueLabel?: string; + + /** Visual size of the track. @default 'md' */ + size?: 'xs' | 'sm' | 'md'; + + /** Color intent of the fill. @default 'default' */ + status?: 'default' | 'success' | 'warning' | 'critical'; + + value?: number; + minValue?: number; + maxValue?: number; + isIndeterminate?: boolean; + 'aria-label'?: string; + 'aria-labelledby'?: string; + 'aria-describedby'?: string; + + // NOTE: no `label` prop. + // NOTE: no `helperText` prop. + // Compose a visible label, value, and description instead: + // + // + // 42% + // Uploading... 42% + // +} + +export declare function ProgressBar(props: ProgressBarProps): JSX.Element; diff --git a/skills/antares-builder/evals/trigger-evals.json b/skills/antares-builder/evals/trigger-evals.json new file mode 100644 index 0000000000..ff3988589d --- /dev/null +++ b/skills/antares-builder/evals/trigger-evals.json @@ -0,0 +1,82 @@ +[ + { + "query": "Build an Antares contact form with validation and retryable saving.", + "should_trigger": true + }, + { + "query": "Our app uses Antares. What fits a compact Grid/List view switch?", + "should_trigger": true + }, + { + "query": "can u fix our antares filters? removing the last chip crashes", + "should_trigger": true + }, + { + "query": "Fix missing months in our Antares revenue chart.", + "should_trigger": true + }, + { + "query": "Review our Antares checkout dialog for focus and async confirmation bugs.", + "should_trigger": true + }, + { + "query": "Our Antares app is missing styles on one route. Help diagnose the consumer setup.", + "should_trigger": true + }, + { + "query": "Add a required Antares date-range picker that keeps date-only values.", + "should_trigger": true + }, + { + "query": "Build an accessible Antares dashboard with regions, traffic share and health.", + "should_trigger": true + }, + { + "query": "Antares Select or ListBox for a visible multi-select region picker?", + "should_trigger": true + }, + { + "query": "Build a responsive Antares product grid with named icon-only actions.", + "should_trigger": true + }, + { + "query": "Change the Antares library Button source and its tests.", + "should_trigger": false + }, + { + "query": "Add a public Combobox to the Antares library with exports and stories.", + "should_trigger": false + }, + { + "query": "Refactor focus management inside the Antares Modal source.", + "should_trigger": false + }, + { + "query": "Fix a chart normalization hook in Antares library internals.", + "should_trigger": false + }, + { + "query": "Write release notes and publishing config for Antares.", + "should_trigger": false + }, + { + "query": "Build a React settings form with the app's existing controls; do not use Antares.", + "should_trigger": false + }, + { + "query": "Add a country picker using the app's existing UI; do not use Antares.", + "should_trigger": false + }, + { + "query": "Build a plain HTML/CSS landing page without React or a component library.", + "should_trigger": false + }, + { + "query": "Fix Nx build caching in the Antares repo; no UI changes.", + "should_trigger": false + }, + { + "query": "Fix the backend endpoint for Antares revenue data; do not change the Antares UI.", + "should_trigger": false + } +] diff --git a/skills/antares-builder/references/charts.md b/skills/antares-builder/references/charts.md new file mode 100644 index 0000000000..9a32c9abc5 --- /dev/null +++ b/skills/antares-builder/references/charts.md @@ -0,0 +1,129 @@ +# Charts + +Read this for any chart implementation, conversion or customization. Check the installed chart props before adapting these patterns. Import `BarChart`, `LineChart`, `DonutChart` and `GaugeChart` from the package root or `@godaddy/antares/Chart`. `Chart` is a public subpath, not a generic chart component. Bar/Line/Donut use Visx; Gauge uses Antares SVG. Do not import internal legends, tooltips or Visx modules as Antares public API. + +## BarChart: categorical comparisons + +Pass a `series` array of `{ id, name, data }`. The default point shape is `{ x, y }`; custom point shapes need `xAccessor` and `yAccessor`. Multiple series produce grouped bars. Use stable series IDs across filtering/reordering. + +Vertical bars use X for categories and Y for values. Horizontal bars reverse that relationship: X must return the numeric value and Y the category. Changing only `orientation` while keeping vertical accessors is insufficient. + +```tsx +import { BarChart } from '@godaddy/antares/Chart'; + +type RegionalRevenuePoint = { region: string; revenue: number }; + +export function RegionalRevenue() { + return ( + + series={[{ + id: 'revenue', + name: 'Revenue', + data: [{ region: 'North America', revenue: 12000 }, { region: 'Europe', revenue: 9000 }] + }]} + orientation="horizontal" + xAccessor={(point) => point.revenue} + yAccessor={(point) => point.region} + xAxisTitle="Revenue (USD)" + yAxisTitle="Region" + height={280} + aria-label="Revenue by region" + desc="North America: 12,000 US dollars. Europe: 9,000 US dollars." + /> + ); +} +``` + +Use `xDomain`/`yDomain` for explicit category order or numeric bounds, matching the orientation. Keep comparison charts on consistent scales. Axis controls include labels, tick formatting, tick counts, baselines and gridlines. Series support palette `colorIndex`, per-category `categoryColors` and `opacity`; preserve meaningful labels alongside color. + +## LineChart: continuous and time trends + +Pass series with points in intended X order. Use `xType="time"` for Date values, `"linear"` for numeric X, or `"band"` for discrete labels. Custom data requires both accessors. Preserve missing observations as `y: null` rather than inventing zeros. Use `xTitle`/`yTitle`; these differ from BarChart's `xAxisTitle`/`yAxisTitle`. + +```tsx +import { LineChart } from '@godaddy/antares/Chart'; + +export function MonthlyRevenue() { + return ( + + ); +} +``` + +Check `xDomain`/`yDomain`, tick formatting/values and `xZero`/`yZero` when the scale matters. Zero is inappropriate for log/time scales. Series accept `colorIndex` and `variant="solid" | "dashed" | "dotted"`; do not copy BarChart's category color API onto lines. + +## DonutChart: parts of a whole + +Pass `data` containing `{ id, name, value }`, with numeric non-negative values, and a required center `label`; `subLabel` is optional. This is not the Bar/Line `series` API. Prefer a small set of categories that actually form a whole. + +```tsx +import { DonutChart } from '@godaddy/antares/Chart'; + +export function TrafficSources() { + return ( + + ); +} +``` + +`legend` accepts `"bottom"` or `"right"`; `formatValue` formats slice values. Zero/negative slices are omitted from the ring. Handle an empty/all-zero total explicitly. `smallSliceThreshold` groups adjacent small slices in hover feedback; it does not aggregate or rewrite the application's dataset. + +## GaugeChart: one value on a known scale + +Provide numeric `value`, visible `label` and an accessible name. Continuous mode uses 0–100. Segmented mode uses 0–`segments`; `segments` must be a finite positive integer or the component throws. Values are clamped, so keep the displayed label consistent with the intended scale. + +```tsx +import { GaugeChart } from '@godaddy/antares/Chart'; + +export function HealthScore() { + return ( + + ); +} +``` + +Omit `segments` for continuous mode. Normalize a different measurement range in application code rather than inventing min/max props. `rangeLabel` requires both min/max display labels; it does not change the numeric scale. Use `labelType="text"` for a short textual center label. Gauge exposes meter semantics; task completion belongs to ProgressBar/CircularProgress. + +## Dimensions, legends and tooltips + +Bar/Line measure their container and accept numeric `width`/`height`; ensure usable non-zero dimensions before diagnosing absent data. They scroll when their minimum plot size exceeds available space, with behavior depending on orientation. Avoid adding a competing scroll/axis system. Donut/Gauge size from container width; constrain their parent or max width to suit the layout. Test the actual dashboard cell at narrow widths. + +Bar/Line use `legendPosition="top" | "bottom" | null`; the default shows a bottom legend for multiple series. Their `tooltipValueFormatter` receives a datum, not a numeric value alone. Custom `renderTooltip` payloads differ: use the public `BarChartTooltipRenderProps`/`BarChartTooltipSeries` or `LineChartTooltipRenderProps` types. Do not replace built-in tooltip behavior unless the product needs custom content. + +## Accessibility and data states + +Supply `aria-label` and meaningful series/category/unit labels. Bar/Line also accept `desc`. Make the essential values or takeaway available in nearby text or a semantic table when users need them; do not rely on pointer tooltips or color alone. Verify actual keyboard/assistive behavior instead of assuming every Visx graphic inherits RAC collection behavior. Use the application's locale for dates, numbers and currencies, and check RTL layouts when applicable. + +Handle loading, no data, single-point/single-slice data, missing values, long labels and large datasets according to the product. Validate finite values/accessors and domain coverage. Preserve missing versus zero semantics; avoid rendering an empty frame as if it were a valid result. Do not change the library's component internals to solve a consumer data-formatting issue. diff --git a/skills/antares-builder/references/component-decision-tree.md b/skills/antares-builder/references/component-decision-tree.md new file mode 100644 index 0000000000..d4ffc92832 --- /dev/null +++ b/skills/antares-builder/references/component-decision-tree.md @@ -0,0 +1,73 @@ +# Component decision tree + +Use this when the user has not named a component, when alternatives overlap, or when replacing custom UI. Choose the interaction first. Follow the linked patterns for anatomy, state and required children. + +## 1. Is the user entering or selecting a value? + +For field composition, read [fields and validation](composition-patterns.md#fields-and-validation). + +- Short text, email, search or password → `TextField` with `Input`. +- Multiline text → `TextField` with `TextArea`. +- Exact number, currency or stepper → `NumberField`; bounded continuous adjustment → `RangeField`. +- Independent boolean or agreement → `Checkbox`; related independent options → `CheckboxGroup`. +- Immediate on/off setting → `Switch`; one answer among visible form options → `RadioGroup` with `Radio`. +- Popup form selection → `Select`; an always-visible selectable collection → `ListBox`. For autocomplete/free-text filtering, see the API gaps below. +- Compact exclusive view/mode → `SegmentedController`; contextual pressed actions such as Bold/Italic → `ToggleButtonGroup` with `ToggleButton`. +- Selectable/removable pills → `ChipGroup`; a standalone pill action → `ChipButton`. See [collections](composition-patterns.md#collections-and-actions). +- Date grid always visible → `Calendar` or `RangeCalendar`; compact field opening a grid → `DatePicker` or `DateRangePicker`. See [dates](composition-patterns.md#dates-and-locale). +- Browse for files → `FileTrigger`; drag/drop target → `DropZone`. The app handles validation/upload. See [file input](composition-patterns.md#file-input). + +## 2. Is this an action or navigation? + +- Perform an action → `Button`; navigate with button styling → `LinkButton`. +- Dismiss an overlay → `CloseButton`; enhance an existing visual child with press behavior → `Pressable`. +- Choose a command from an action list → `MenuTrigger` with `Menu`; use a Popover for a general interactive form. +- Static/linked content surface → `Card`; selectable/action card collection → `CardGroup`. + +Read [actions and slots](composition-patterns.md#actions-slots-and-state) or [collections](composition-patterns.md#collections-and-actions) for these structures. Ordinary inline links use semantic anchors or the application's router link. + +## 3. Is content revealed, switched or layered? + +- Reveal one section in place → `Collapsible`; coordinate related sections → `Accordion`. +- Expand a rail/panel within page flow → `InlineDrawer`. +- Replace peer panels in one view → `Tabs`. +- Communicate wizard stages → `ProgressSteps` with `ProgressStep`. +- Move through a dataset's pages → `Pagination`; a passive current-page dot indicator (one dot per page, no ellipsis or page-omission support) → `PaginationDots`. +- Browse sequential gallery/feature panels → `Carousel`. + +See [disclosure and tabs](composition-patterns.md#disclosure-and-tabs) and [progress, pagination and feedback](composition-patterns.md#progress-pagination-and-feedback). + +For layered content, read [modal layers](composition-patterns.md#modal-layers): + +- Non-interactive hover/focus help → `TooltipTrigger` with `Tooltip`. +- Anchored interactive content → `PopoverTrigger` with `Popover`. +- Blocking centered task/confirmation → `ModalTrigger` with `Modal`. +- Modal edge panel or bottom sheet → `DrawerTrigger` with `Drawer`. + +## 4. Is this information, feedback or data? + +- In-page live message → `Alert`; field validation → `FieldError` inside its field. +- Static status/category → `Tag`; selection/removal belongs to Chip. +- Operation progress → `ProgressBar` or compact `CircularProgress`; a numeric input belongs to RangeField. +- Text-first KPI/trend → `MetricsLockup`. +- Category comparison → `BarChart`; continuous/time trend → `LineChart`; few parts of a whole → `DonutChart`; one measure against a scale → `GaugeChart`. +- Content still loading → `Skeleton`, composed into the shape of the content it previews. + +Read [charts](charts.md) for chart data/accessors, dimensions, axes, legends and accessibility; read [progress, pagination and feedback](composition-patterns.md#progress-pagination-and-feedback) for feedback and navigation contracts. + +For content presentation, read [layout and styling](layout-and-styling.md): + +- Body/secondary copy → `Text`/`Detail`; semantic title → `Heading`; coordinated eyebrow/title/body → `TextLockup`. +- Person/entity identity → `Avatar`; image → `Image`; Antares SVG → `Icon`. + +## 5. How should it be arranged? + +Read [layout and styling](layout-and-styling.md) for composition and responsive rules. + +- One-dimensional row/column → `Flex`; two-dimensional placement → `Grid`; surface/semantic wrapper → `Box`. +- Interior regions → `Header`, `Content`, `Footer`, `ButtonGroup`, `Group`, `CornerActions`. +- Consistent adopted component size → optional `SizeProvider`. + +## API gaps + +Do not infer Antares exports such as `Combobox`, `Table`, `Toast`, `EmptyState`, `NativeSelect`, `Link`, `Breadcrumb`, `Sidebar` or `FileUpload` from other libraries. Check the installed export map first. When a required component is unavailable, use semantic HTML or the application's established solution. A separate RAC dependency is an option when its API and styling fit the requirement; it does not create an Antares export. For empty states, Antares typography, media, actions and layout can form a suitable composition. diff --git a/skills/antares-builder/references/composition-patterns.md b/skills/antares-builder/references/composition-patterns.md new file mode 100644 index 0000000000..45eb276701 --- /dev/null +++ b/skills/antares-builder/references/composition-patterns.md @@ -0,0 +1,230 @@ +# Antares composition patterns + +Read only the sections relevant to the task. These shapes are verified against the package's component READMEs and examples. Use the consumer's installed types for detailed props and adapt data and handlers to the product. RAC conventions explain behavior but do not replace Antares's explicit children and slots. + +Most composed parts also publish a matching `*Context` (for example `ButtonContext`, `InputContext`, `AccordionContext`, `ChipContext`) that lets an advanced consumer set subtree-wide defaults; ordinary composition through explicit children and props never needs these. + +## Actions, slots and state + +`Button` uses RAC button behavior; `LinkButton` uses link behavior. `Pressable` adds press/focus/hover behavior to exactly one child that forwards its ref and DOM/ARIA props, without rendering a wrapper. Prefer the semantic Button/LinkButton when they fit. Name icon-only controls on the control itself. + +Parents publish behavior and presentation through slots. Keep field triggers as `Button slot="trigger"`, steppers as `slot="decrement"`/`slot="increment"`, and dismissal as `slot="close"`. Slot names are parent-specific. Button omits RAC's `isPending` prop; use application-owned pending state and supported disabled/content props. + +Match the actual state model: field `value`/`onChange`, collection `selectedKeys`/`onSelectionChange`, boolean `isSelected`/`onChange`, and disclosure `isExpanded`/`onExpandedChange` are not interchangeable. Use defaults for uncontrolled state, or update state from the controlled callback; do not combine both modes accidentally. + +## Fields and validation + +`TextField` and `NumberField` provide the field relationship, while children provide visible parts. The field's `isInvalid` state controls whether `FieldError` renders. Use `Text slot="description"` for persistent help. + +Set `name` for native form submission and use supported root props such as `isRequired`, `isDisabled` and `isInvalid`. Keep the application's form/validation library and connect its state to the exact Antares value/change API. Place controls in a semantic form and choose submit/reset button types deliberately. On a failed submission, move focus to the first invalid field so assistive technology announces its error immediately; do not leave focus on the submit control. The following field fragments assume `emailError` comes from that validation state. + +```tsx +import { Button, FieldError, Group, Input, Label, NumberField, Text, TextArea, TextField } from '@godaddy/antares'; + + + + + We'll send receipts here. + {emailError} +; + + + +