All posts
releaseannouncement

FlowDrop 1.13.0: Server-Driven Messages and Mobile Playground

FlowDrop 1.13.0 lets the server fully control playground message presentation via hierarchy, tags, and display fields, ships a one-pane mobile layout with a full accessibility pass, and adds dependent autocomplete form fields.

FlowDrop 1.13.0 hands message presentation to the server. Three new fields on PlaygroundMessagehierarchy, tags, and display — let the backend decide how each message is rendered without the client second-guessing. The playground also goes mobile-first with a one-pane layout under 768 px, and forms gain dependent autocomplete fields driven by sibling values.

Server-driven message annotations

PlaygroundMessage now carries three optional server-emitted fields. When the server provides them, the client renders exactly what was sent — no client-side derivation, no merging with defaults.

  • hierarchy: MessageHierarchyItem[] — an ordered path describing where the message sits (e.g. workflow > sub-workflow > iteration). Rendered as a chevron-separated trail. Display-only — this is not a navigation breadcrumb.
  • tags: MessageTag[] — classification chips with a closed-enum color (muted | primary | success | warning | error | info) and variant (subtle | solid | outline).
  • display: PlaygroundMessageDisplay — layout hint, one of bubble | log | notice | card. When omitted, the client picks a default from the role.

A pure resolveMessageDisplay(message, options) helper is exported alongside the types so consumers can mirror the dispatch logic when rendering messages outside the built-in stream. The full contract is documented in api/README.md.

Mobile-responsive playground

At viewports ≤768 px, PlaygroundStudio switches from side-by-side panes to one-at-a-time fullscreen. The pipeline panel takes the full viewport when open, and a “Back to chat” affordance inside the pipeline pane gives users a way back since the toggle lives inside the now-hidden chat pane. The drag resizer is hidden at this width — there is nothing to resize.

Message bubbles, log rows, system notices, cards, and interrupt footers flex-wrap and tighten padding at small widths. Hierarchy labels truncate to 5 rem and log timestamps hide to recover horizontal space.

Container-query log layout

The narrow-pane log layout is driven by container size, not viewport size, so it fires correctly in any embedded mount — narrow desktop chat panes, modal embeds, Drupal admin chrome — regardless of the user’s window size.

.message-stream is now a CSS container (container-name: fd-message-stream). When the stream is ≤480 px wide, log rows stack onto three lines: meta and hierarchy on row 1, message body on row 2, tags on row 3 (indented to align with the body). Timestamps hide; chronology is implied by message order. A medium 2-row variant is also available for intermediate widths.

Accessibility pass on the message stream

Nearly every element in the message stream gained proper semantics:

  • Message bubbles and cards are <article> with role-named aria-labels (e.g. “Assistant message”)
  • Log rows carry role="listitem" plus level- and source-named aria-labels
  • System notices use role="status" so screen readers announce them as live updates
  • Tag groups are role="group" aria-label="tags"; individual chips include any tag.type in their aria-label
  • Hierarchy trails wrap their <ol> in <nav aria-label="message hierarchy"> and mark the last crumb with aria-current
  • Timestamps are <time datetime=…> with natural-language aria-labels (“sent at HH:MM:SS”)
  • All decorative Iconify icons are aria-hidden="true"
  • prefers-reduced-motion is respected on bubble/card fade-in and interrupt slide-in

Dependent autocomplete fields

AutocompleteConfig gains an optional params map that wires sibling form values into the suggestion-fetch URL as query parameters:

autocomplete:
  url: https://api.example.com/cities
  params:
    country: country_field

When the country_field value changes, FormAutocomplete reactively clears the selected value, invalidates its suggestion cache, and refetches with the new dependency. The guard against firing on initial mount preserves restored config values, so reloading a saved workflow does not blank out dependent fields.

The change is end-to-end: the OpenAPI YAML schema and the regenerated JSON Schema include params.

FORM_VALUES_KEY context

The mechanism behind dependent autocomplete is exposed as public API. Custom field components registered via fieldComponentRegistry can call getContext(FORM_VALUES_KEY) to receive a () => Record<string, unknown> getter that always returns the current values of all sibling fields. The context is set by both ConfigForm and SchemaForm. This is the stable surface for building any cross-field interaction, not just autocomplete.

Registered autocomplete components also receive the full FieldSchema as a schema prop, giving access to any custom property on the schema definition without FlowDrop needing to anticipate and forward each one individually.

FormAutocomplete exposed as subpath

FormAutocomplete is now importable directly via @flowdrop/flowdrop/form/autocomplete. Consumers can wrap it to build custom autocomplete UIs without reimplementing type-ahead, debounce, and abort logic. FormField and FormFieldLight also consult fieldComponentRegistry for autocomplete fields, rendering registered overrides with the full prop set — including node, edges, and the resolved autocomplete config — before falling through to the built-in component.

awaiting_input in the session status enum

PlaygroundSessionStatus now includes awaiting_input in the OpenAPI enum. The TypeScript type already accepted this value; the schema is now in sync.

Fixes

  • Auth headers on fetchCategories and fetchPortConfig (#27) — both functions hardcoded only Content-Type and ignored both the legacy endpointConfig.auth and the AuthProvider path. They now accept an optional AuthProvider, merge its headers on top of getEndpointHeaders, and mountWorkflowEditor exposes the same option.
  • FormAutocomplete correctness — dependency-change guard replaced with value-comparison so it works on deferred and SSR mounts; AbortController timeout race fixed so the right request is always aborted; suggestions cleared on blur when params is configured; a logger warning surfaces when params is set but flowdrop:getFormValues context is missing.
  • Compact log rows in narrow panes — driven by the new container-query layout above.

Upgrading

npm install @flowdrop/flowdrop@1.13.0

No breaking changes. The new hierarchy, tags, and display fields are optional — if your server does not emit them, the client falls back to the previous role-based defaults.