Annotation Config Form#
AnnotationConfigDialog (AnnotationConfigDialog.tsx) is the React form dialog used in the Phoenix Settings → Annotations page to create and edit annotation configurations. It supports three config types—Categorical, Continuous, and Freeform—whose schemas are defined as a discriminated union in types.ts.
Entry Point#
The dialog is mounted inside a DialogTrigger in SettingsAnnotationsPage.tsx. The parent page passes a handleAddAnnotationConfig callback that fires a GraphQL createAnnotationConfig (or update) mutation via Relay . The dialog itself is a pure form component; it holds no mutation logic.
Props#
| Prop | Type | Notes |
|---|---|---|
onAddAnnotationConfig | (config: AnnotationConfig, callbacks?) => void | Called on valid submit; parent owns the mutation |
initialAnnotationConfig | Partial<AnnotationConfig> (optional) | Presence switches the dialog to edit mode |
Form Structure (react-hook-form)#
The form is wired with useForm with default values annotationType: "CATEGORICAL" and two empty values rows. Key mechanics:
- Type switcher — A
RadioGroupbound toannotationTypedrives conditional rendering of type-specific fields . In edit mode the radio isisReadOnly, preventing type changes . - Categorical categories —
useFieldArraymanages thevaluesarray (label + optional numeric score). Each row renders a labelTextFieldwith a required validation rule and aNumberFieldfor score. The Add category button callsappend({ label: "", score: null })and Remove callsremove(index). Placeholder labels cycle through the alphabet (A,B,C, …) . - Continuous bounds —
lowerBoundandupperBoundNumberFields appear forCONTINUOUS.upperBoundhas a customvalidaterule that checksvalue > lowerBoundand guards againstNaN. TheminValueof the max field is dynamically set from awatch("lowerBound")call . - Optimization direction — A
RadioGroupwith valuesMAXIMIZE | MINIMIZE | NONEis shown for bothCATEGORICALandCONTINUOUS. - Freeform — Only name and description fields render; no extra controls.
Validation#
All validation is inline via react-hook-form rules:
nameis required .- Each category
labelis required . lowerBoundis required for continuous configs .upperBounduses a customvalidatefunction .
Errors surface via the <FieldError> component slotted below each input.
Submit Flow#
handleSubmit branches on data.annotationType, constructs a narrowly-typed config object (AnnotationConfigCategorical | AnnotationConfigContinuous | AnnotationConfigFreeform), then calls onAddAnnotationConfig . On success the dialog closes and a success toast fires; on error an error toast fires . The parent mutation is called with the config key lowercased to match the GraphQL CreateAnnotationConfigInput format .
Related Files#
| File | Purpose |
|---|---|
AnnotationConfigDialog.tsx | Form dialog component |
types.ts | AnnotationConfig union type and subtypes |
SettingsAnnotationsPage.tsx | Parent page; owns mutations and renders dialog trigger |
src/phoenix/db/types/annotation_configs.py | Backend schema for the three config types |