Skip to content

feat(assistant-wizard): reorder step 2 and add rich-radio sensitivity - #207

Merged
martinyde merged 3 commits into
developfrom
feature/issue-202-step2-reorder-radio-cards
Jul 10, 2026
Merged

feat(assistant-wizard): reorder step 2 and add rich-radio sensitivity#207
martinyde merged 3 commits into
developfrom
feature/issue-202-step2-reorder-radio-cards

Conversation

@martinydeAI

Copy link
Copy Markdown
Collaborator

Links to issues

Fixes #202

Description

Step 2 of the assistant create/edit wizard groups its fields in an
order that no longer matches how curators think about the
assistant. The tagline sits below the long description, knowledge
sits below the language model, and language model + organisation
each occupy a full-width row when they should read as a matched
pair. The data-sensitivity choice hides behind a plain <select>
whose default is whichever case happens to sit first in the enum.

  • Reorder (both src/Form/AssistantMetadataStepType.php and
    templates/assistant/_step_metadata.html.twig):
    1. Title
    2. Short description (tagline) — now required
    3. Description
    4. Knowledge description
    5. Language model + Organisation (paired via
      grid gap-4 md:grid-cols-2, stacked below md:)
    6. Tags
    7. Data sensitivity
  • Tagline requiredrequired => true + NotBlank under
    the metadata validation group. A new
    assistant.new.step_metadata.tagline_required translation key
    ("Angiv en kort beskrivelse.") wires the message. Curators can
    no longer ship an assistant without the short one-line summary
    the catalog surfaces on card lists.
  • Rich-radio sensitivityEnumType gets
    expanded => true, the empty placeholder is dropped, and the
    template iterates the field's children directly. Each card
    pairs the enum's short label (DataSensitivity::label()) with
    its longer description (DataSensitivity::description());
    choice_attr surfaces the description key on each child's
    vars.attr so the template can reach it without dragging the
    whole enum case through the view. Card hover darkens the
    border; the selected card gets primary border +
    surface-2 background via has-[input:checked]: selectors.
  • The language-model picker's Stimulus / Choices.js wrapper is
    unchanged — just relocated into the paired column.
  • Baseline-badge behaviour is intact for the four fields that
    have jsonBaseline entries today (title, description,
    languageModel, tags). Tagline isn't in the baseline, so it
    never got a badge before and doesn't get one now — that
    matches the current AssistantDraftPrefiller::prefillForCreate
    behaviour.

Screenshot of the result

To be added — please walk both the create and edit paths
(POST /assistant/new → step 2, GET /assistant/{id}/edit
→ step 2) before merging. Confirm the paired columns collapse
correctly on narrow viewports and the three sensitivity cards
render distinct hover / checked states.

Checklist

  • My code is covered by test cases.
  • My code passes our test (all our tests).
  • My code passes our static analysis suite.
  • My code passes our continuous integration process.

Test edits (approved on the issue thread):

  • AssistantCreateControllerTest.php — set tagline before
    submitting step 2 in two happy-path tests (the wizard no
    longer accepts a blank tagline).
  • AssistantEditControllerTest.php — the radio
    ChoiceFormField rejects an empty-string assignment
    ("" not in choices), so the "unset dataSensitivity"
    negative case now calls disableValidation() on the field
    before setting it. The badge assertion's selector narrows
    from label span to label span.uppercase so the new
    rich-radio card spans no longer match.

Minor: templates/assistant/show.html.twig gets a
twig-cs-fixer whitespace normalisation on the #} alignment in
the sensitivity-pill comment block. Zero behaviour change.


Details - AI specificities

Goal

Two things at once:

  1. Give step 2 an order that matches how a curator narrates the
    assistant: identity (title, tagline) → what it does
    (description) → what it draws on (knowledge, language model +
    organisation) → how it's classified (tags, data sensitivity).
  2. Make the data-sensitivity choice the visual centre of gravity
    it deserves — a hidden <select> lets a curator ship an
    assistant without ever consciously picking, and the persisted
    default is whichever case happens to be first in the enum.
    Rich radios force the pick and communicate the weight of the
    three options inline.

On top: tagline is now required so the catalog surface (cards)
never falls back to the long description silently.

Scope

  • src/Form/AssistantMetadataStepType.php — reorder ->add()
    calls, promote tagline to required, promote
    dataSensitivity to expanded: true + choice_attr.
  • templates/assistant/_step_metadata.html.twig — reorder rows,
    add two-column wrapper for language-model + organisation,
    render the rich-radio card list.
  • translations/validators.da.yaml — add tagline_required.
  • Tests as listed above.

Non-goals

  • No entity or DTO change — every field already exists on
    AssistantDraft / Assistant.
  • No change to the DataSensitivity enum values, labels, or
    descriptions.
  • No change to step 1 (upload), step 3 (receipt), or the
    wizard's navigation.
  • No change to the language-model picker's Stimulus controller
    — it keeps working exactly as today, just relocated into the
    paired column.
  • No new spacing / radius tokens under @theme. Card sizing
    uses Tailwind utilities directly, matching the rest of the
    codebase.

Decisions

  • Rich-radio card markup lives in the template, not a
    form-theme override.
    The codebase has no existing form
    theme, so introducing one for a single field is heavier than
    looping the field's children directly. EnumType +
    expanded: true + choice_attr gives us the raw material;
    the template's <fieldset> / <legend> / <label> / <span>
    markup does the presentation.
  • Description key is surfaced via choice_attr rather than
    passed as a separate view variable.
    Keeps the mapping on the
    field, so the template doesn't need to know the enum exists —
    it just reads child.vars.attr['data-description-key'] and
    translates it.
  • Tagline required — form-level only, no entity migration.
    The DB column stays nullable so existing rows with a null
    tagline continue to load; editing one of those forces the
    curator to fill in the tagline on step 2 (which is the point).

Verification

  • task coding-standards-check → clean.
  • task test → 690 tests, 2044 assertions, all green.
  • Visual check pending — please walk both wizards end to end.

Links

martinydeAI and others added 3 commits July 10, 2026 09:18
Step 2 of the assistant create/edit wizard groups its fields in an
order that no longer matches how curators think about the
assistant, and the data-sensitivity choice hides behind a plain
<select> whose default is whichever case sits first in the enum.

- Reorder fields (declaration + template):
    1. Title
    2. Short description (tagline)  — now REQUIRED
    3. Description
    4. Knowledge description
    5. Language model + Organisation (paired on `md:` and up,
       stacked on narrower viewports via `md:grid-cols-2`)
    6. Tags
    7. Data sensitivity
- `tagline`: `required => true`, add `NotBlank` under the
  `metadata` validation group with a new `tagline_required`
  translation key. Curators must now write the short one-line
  summary the catalog surfaces on cards; the wizard cannot ship
  an assistant without it.
- `dataSensitivity`: switch `EnumType` to `expanded => true` and
  drop the `placeholder`. In the template, iterate the field's
  children and render each as a rich radio card that pairs the
  enum's short label with its longer descriptive copy on
  `<label>` + `has-[input:checked]:` states. `choice_attr`
  surfaces the description translation key on each child's
  `vars.attr` so the template can reach it without dragging the
  whole enum case through the view. Empty case remains
  guarded by the existing `NotNull` constraint.
- Two knock-on test edits in the create-flow controller test
  (set tagline before submit) plus two in the edit-flow test
  (radio ChoiceFormField requires disableValidation() to force
  "no radio selected"; badge selector narrows to `label
  span.uppercase` so the rich-radio card spans no longer match).
- Minor whitespace normalisation in
  `templates/assistant/show.html.twig` (twig-cs-fixer:
  single-space rule before `#}`).

Fixes #202

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two visual polish fixes on the reordered step 2:

- Language-model column rendered its help text through a raw
  `<small>` tag, which the browser shrinks to ~80% of the parent's
  font size. Every other field on the step routes its help
  through Symfony's default `form_help` block (renders as a `<div>`
  inheriting the row's `text-sm` size). Swap the manual `<small>`
  for `form_help(language_model)` so all step-2 help texts sit at
  the same size.
- Choices.js's default CSS pins `.choices__inner` at `min-height:
  44px` with asymmetric `7.5px 7.5px 3.75px` padding and
  `.choices { margin-bottom: 24px }`, so the enhanced language-
  model widget rendered taller than the plain organisation
  `<select>` sharing its row — reading as an inflated gap between
  the label and the visible input. Add scoped overrides that pin
  `.choices__inner` to the shared form-input shape (`py-2 px-3`,
  `rounded-lg`, `border-line`, `bg-surface`) and zero out the
  vendor bottom margin so the two columns align at both the
  label→input baseline and the input→help baseline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The outer `md:grid-cols-2` on step 2's language-model +
organisation row stretches each column to the tallest cell's
height (grid's default `align-items: stretch`). Without an
explicit `align-content: start` on each column's inner grid,
the shorter column distributes the extra vertical space across
its tracks and inflates the gap between the label, the input,
and the help line — enough that a curator reads it as a
mis-alignment between the two columns.

Add `content-start` (align-content: flex-start) to both column
grids so their tracks stay compact at the top and any extra
space falls below the last track. Applies to the language-
model column's manual `<div>` and to the organisation field via
a `row_attr` override on `form_row`.

Same treatment for the sensitivity fieldset's help line —
swap the manual `<small>` render for `form_help(sensitivity_field)`
so every step-2 help text ships through Symfony's default
`form_help` block at the row's `text-sm` size.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@martinyde
martinyde merged commit e5801b5 into develop Jul 10, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(assistant-wizard): reorder step 2 fields and turn data sensitivity into radio cards

2 participants