mirror of
https://github.com/hanzoai/o11y.git
synced 2026-11-03 02:04:48 +00:00
* feat(ai-assistant): polish composer UX and add Cmd+K entry
- ChatInput textarea auto-grows up to 200px (was locked at 2 rows) so
long prompts aren't trapped in a scrolling porthole; default rows
bumped 2 → 3.
- Composer container shows an accent-primary focus ring via
:focus-within so the active state is visible.
- Cmd+K palette surfaces an "Open AI Assistant" entry, gated on
useIsAIAssistantEnabled() and emitting Opened with source: 'cmdk'.
* fix(ai-assistant): a11y, scroll, and routing polish
Address a punch list of UX/a11y bugs surfaced while auditing the AI
Assistant:
- Stop auto-scroll fighting the user during streaming. VirtualizedMessages
now tracks atBottom via Virtuoso's atBottomStateChange and bails the
manual scrollTo when the user has scrolled away.
- Resolve dynamic-route templates in getRouteKey so /ai-assistant/:id
picks up the new AI_ASSISTANT title entry instead of falling through to
the default browser title.
- Give the icon-only message actions (copy / thumbs up-down / regenerate)
real aria-labels, and aria-pressed reflecting vote state.
- Convert context-picker rows from divs to buttons. Categories become a
proper tablist with roving tabindex and ArrowUp/ArrowDown navigation;
entities use aria-pressed for toggle semantics. SCSS resets native
button defaults and adds focus-visible outlines.
- Enforce required clarification fields. Submit is disabled until every
required field is filled, and handleSubmit bails early to guard the
keyboard-Enter bypass.
* fix(ai-assistant): move focus to new tab on context picker arrow keys
The roving-tabindex pattern stalled because state updated but DOM focus
stayed on the original button — whose closure had the old category — so
subsequent arrow keys never advanced past the second tab. Added refs to
each tab and call `.focus()` on the newly-active one after state update.
* fix(ai-assistant): scroll regression on user send and focus polish
- VirtualizedMessages: when the user is scrolled up and sends a new
message, force-anchor to the bottom so they see their own send and
the assistant's follow-up. Previous bailout kept them stranded.
- Composer: move the :focus-within highlight from the outer .input
wrapper onto .composer so the action footer (Add Context / mic /
send) isn't visually inside the focus ring.
- Context picker: drop the :focus-visible outlines on category and
entity buttons; the existing :hover + .active / .selected styles
carry the focus story.
* fix(ai-assistant): complete tablist semantics and cross-pane keyboard nav
Finish the context picker tablist pattern and extend keyboard navigation
into the entity panel so arrow keys carry the user all the way to a
selection without reaching for the mouse.
- Tabs get `id` + `aria-controls`; the right pane becomes a real
`role="tabpanel"` with `id` + `aria-labelledby` pointing back at the
active tab.
- Add `Home` / `End` to the tablist; add `ArrowRight` to cross from the
active tab into the entity list.
- Add `ArrowUp` / `ArrowDown` / `Home` / `End` cycling within the entity
list, and `ArrowLeft` to cross back to the active tab.
* docs(app-layout): note that ROUTES order matters for ambiguous templates
* fix(ai-assistant): reset scroll anchor on conversation switch
Key `VirtualizedMessages` by `conversationId` so atBottomRef,
lastSeenUserMessageIdRef, and Virtuoso's internal scroll position
all reset together — otherwise a "scrolled up" state from the
previous conversation could block auto-scroll for the next one's
incoming stream.
* fix(app-layout): add titles for dynamic-template routes
After `getRouteKey` started matching `:param` templates (1bad9ec76),
six routes that previously fell through to DEFAULT now resolve to a
key with no translation, causing react-helmet to render the raw key
as <title>. Add explicit titles for TRACE_DETAIL_OLD,
SERVICE_TOP_LEVEL_OPERATIONS, ROLE_DETAILS, TRACES_FUNNELS_DETAIL,
INTEGRATIONS_DETAIL, and PUBLIC_DASHBOARD.
* fix(ai-assistant): polish chat input voice controls and context picker
- Convert .micDiscard / .micStop from <div onClick> to native <button>
so the voice-recording controls are keyboard-operable (WCAG 2.1.1).
Adds a small SCSS reset for native button defaults so the 24px circle
isn't inflated by browser padding / font metrics.
- Add role="status" aria-live="polite" with an aria-label to the
.micRecording container so screen-reader users hear when recording
starts.
- Truncate entityRefs.current to filteredContextOptions.length next to
the filter so switching from a large context category (e.g. 100
dashboards) to a smaller one doesn't leave stale null slots from
earlier renders. Keyboard nav math already used the new length for
its modulo, so this is housekeeping rather than a correctness fix.
- Drop redundant `messages.length` from the auto-scroll effect deps —
`messages` already covers it.
* fix(ai-assistant): polish clarification form a11y and numeric validation
- Add aria-required to text / number Inputs and to SelectTrigger so
screen readers announce "required" without needing the visual `*`.
Mark the visual `*` aria-hidden so it doesn't get double-announced
alongside the aria-required state.
- Convert the multi_select wrapper from <div> + <span> to <fieldset> +
<legend>, the WCAG 1.3.1-recommended grouping for related checkboxes
so SRs announce the group label before each option. Adds an SCSS
reset so the native fieldset border / padding / margin don't shift
the layout vs. the surrounding <div>-based field rows.
- Map an empty <Input> value to `null` for number fields instead of
Number('') === 0, so a required numeric field cleared after typing
no longer silently reads as a valid `0` in `isFieldFilled`.
* fix(ai-assistant): address Codex review findings
- ClarificationForm: parse number defaults in `initialAnswerFor`. The
generated DTO types `default` as `string | string[] | null`, so a
server-supplied numeric default arrives as `"5"`. The previous code
stored that string verbatim and `isFieldFilled` (which requires
`typeof === 'number'`) then disabled Submit for a visibly-filled
required field. Now parses to a real number, or `null` for empty /
NaN inputs.
- ChatInput context picker: share a single stable tabpanel id across
all tabs. Previously each tab's `aria-controls` pointed at
`ai-context-tabpanel-${category}`, but only the active category's
tabpanel was actually rendered — so two of three tabs always pointed
at nonexistent ids. APG permits a single dynamic panel whose
`aria-labelledby` swaps to the active tab.
- Extract analytics `source` magic strings into typed `as const`
enums in `events.ts` per the CLAUDE.local.md guidance. New
`AIAssistantOpenSource` ({ Icon, Shortcut, Cmdk }) replaces inline
strings in `AIAssistantTrigger`, `AIAssistantModal`, and
`cmdKPalette`. New `VoiceInputSource` ({ Button, Shortcut }) replaces
inline strings in `ChatInput`.
- ClarificationForm comment: the form root isn't a `<form>` element,
so an "Enter inside text field" submit-bypass can't actually happen.
Reword the comment to reflect what the guard is really for —
defensive against direct handler invocation.
* fix(ai-assistant): add tooltips to icon-only buttons
Several icon-only buttons in the AI Assistant relied on the native
`title` attribute (slow, inconsistent across browsers) or only an
`aria-label` (invisible to sighted users) for hover affordance.
Wrapped with `TooltipSimple` to match the established pattern in
`AIAssistantPanel`, `MessageFeedback`, `UserMessageActions`, etc.
- ApprovalCard: the diff toolbar view-option icons (split / unified /
wrap), the expand-diff button, and the CopyButton.
- RichCodeBlock: the per-block copy-code button.
- ChatInput: voice-recording discard / stop-and-send buttons (newly
native <button>s after the previous a11y pass), and the Send button.
* fix(ai-assistant): use component-prefixed class for multi_select fieldset
`.fieldset` is on the CLAUDE.local.md list of generic CSS-module class
names to avoid alongside `.header` / `.body` / `.label` / `.row`.
Rename to `.multiSelectFieldset` so the intent is obvious at
grep / diff time.
* refactor(ai-assistant): address PR review on composer + approval card
Migrate icon-only and icon-prefixed buttons to use the DS Button
`prefix` slot, replace the manual context-picker `<button>` rows with
DS Button (overriding centered layout via `--button-justify-content`
CSS var), extract context-picker keyboard handlers into named
useCallbacks, and move the `MessageFeedback` rating vocabulary into
typed `as const` maps keyed on `FeedbackRatingDTO`. The approval-diff
view-mode toggle stays on the manual `ToggleGroup` composition so each
`TooltipSimple` can wrap its `ToggleGroupItem` (the items-API loses
per-item tooltip anchoring). Disable Radix Dialog auto-focus on the
approval-diff modal so the first Copy button's tooltip doesn't surface
on open.
* feat(ai-assistant): surface modal in Cmd+K + fix modal header icon color
- Add an "Open AI Assistant" entry to the Cmd+K palette with a `cmd+j`
shortcut hint. Selecting it now starts a fresh conversation and opens
the modal (matching Cmd+J), rather than the side drawer.
- Modal header icons (history, new, expand, minimize, close) were
defaulting to the primary color and rendering blue. Set
`color="secondary"` to match the side-panel header.
- Migrate the modal + panel header icon buttons from icon-as-children
to the DS Button `prefix` slot for consistency with the rest of the
AI Assistant composer.
* fix(ai-assistant): refocus composer on new conversation / switch
Key ChatInput by conversationId in ConversationView (matching how
VirtualizedMessages is already keyed) so the "+ New conversation"
click remounts the composer and its mount-effect re-grabs textarea
focus. Side benefit: prior text/attachments/contexts no longer leak
across conversation switches.
80 lines
3.9 KiB
JSON
80 lines
3.9 KiB
JSON
{
|
|
"SIGN_UP": "Hanzo O11y | Sign Up",
|
|
"LOGIN": "Hanzo O11y | Login",
|
|
"FORGOT_PASSWORD": "Hanzo O11y | Forgot Password",
|
|
"HOME": "Hanzo O11y | Home",
|
|
"SERVICE_METRICS": "Hanzo O11y | Service Metrics",
|
|
"SERVICE_MAP": "Hanzo O11y | Service Map",
|
|
"GET_STARTED_OLD": "Hanzo O11y | Get Started",
|
|
"ONBOARDING": "Hanzo O11y | Get Started",
|
|
"GET_STARTED_APPLICATION_MONITORING": "Hanzo O11y | Get Started | APM",
|
|
"GET_STARTED_LOGS_MANAGEMENT": "Hanzo O11y | Get Started | Logs",
|
|
"GET_STARTED_INFRASTRUCTURE_MONITORING": "Hanzo O11y | Get Started | Infrastructure",
|
|
"GET_STARTED_AWS_MONITORING": "Hanzo O11y | Get Started | AWS",
|
|
"GET_STARTED_AZURE_MONITORING": "Hanzo O11y | Get Started | AZURE",
|
|
"GET_STARTED": "Hanzo O11y | Get Started with Hanzo O11y Cloud",
|
|
"GET_STARTED_WITH_CLOUD": "Hanzo O11y | Get Started with Hanzo O11y Cloud",
|
|
"TRACE": "Hanzo O11y | Trace",
|
|
"TRACE_DETAIL": "Hanzo O11y | Trace Detail",
|
|
"TRACES_EXPLORER": "Hanzo O11y | Traces Explorer",
|
|
"SETTINGS": "Hanzo O11y | Settings",
|
|
"USAGE_EXPLORER": "Hanzo O11y | Usage Explorer",
|
|
"APPLICATION": "Hanzo O11y | Home",
|
|
"BILLING": "Hanzo O11y | Billing",
|
|
"ALL_DASHBOARD": "Hanzo O11y | All Dashboards",
|
|
"DASHBOARD": "Hanzo O11y | Dashboard",
|
|
"DASHBOARD_WIDGET": "Hanzo O11y | Dashboard Widget",
|
|
"EDIT_ALERTS": "Hanzo O11y | Edit Alerts",
|
|
"LIST_ALL_ALERT": "Hanzo O11y | All Alerts",
|
|
"ALERTS_NEW": "Hanzo O11y | New Alert",
|
|
"ALL_CHANNELS": "Hanzo O11y | All Channels",
|
|
"CHANNELS_NEW": "Hanzo O11y | New Channel",
|
|
"CHANNELS_EDIT": "Hanzo O11y | Edit Channel",
|
|
"ALL_ERROR": "Hanzo O11y | All Errors",
|
|
"ERROR_DETAIL": "Hanzo O11y | Error Detail",
|
|
"VERSION": "Hanzo O11y | Version",
|
|
"MY_SETTINGS": "Hanzo O11y | My Settings",
|
|
"ORG_SETTINGS": "Hanzo O11y | Organization Settings",
|
|
"INGESTION_SETTINGS": "Hanzo O11y | Ingestion Settings",
|
|
"API_KEYS": "Hanzo O11y | API Keys",
|
|
"CUSTOM_DOMAIN_SETTINGS": "Hanzo O11y | Custom Domain Settings",
|
|
"SOMETHING_WENT_WRONG": "Hanzo O11y | Something Went Wrong",
|
|
"UN_AUTHORIZED": "Hanzo O11y | Unauthorized",
|
|
"NOT_FOUND": "Hanzo O11y | Page Not Found",
|
|
"LOGS": "Hanzo O11y | Logs",
|
|
"LOGS_EXPLORER": "Hanzo O11y | Logs Explorer",
|
|
"OLD_LOGS_EXPLORER": "Hanzo O11y | Old Logs Explorer",
|
|
"LIVE_LOGS": "Hanzo O11y | Live Logs",
|
|
"LOGS_PIPELINES": "Hanzo O11y | Logs Pipelines",
|
|
"HOME_PAGE": "Open source Observability Platform | Hanzo O11y",
|
|
"PASSWORD_RESET": "Hanzo O11y | Password Reset",
|
|
"LIST_LICENSES": "Hanzo O11y | List of Licenses",
|
|
"WORKSPACE_LOCKED": "Hanzo O11y | Workspace Locked",
|
|
"WORKSPACE_SUSPENDED": "Hanzo O11y | Workspace Suspended",
|
|
"WORKSPACE_ACCESS_RESTRICTED": "Hanzo O11y | Workspace Access Restricted",
|
|
"SUPPORT": "Hanzo O11y | Support",
|
|
"LOGS_SAVE_VIEWS": "Hanzo O11y | Logs Saved Views",
|
|
"TRACES_SAVE_VIEWS": "Hanzo O11y | Traces Saved Views",
|
|
"TRACES_FUNNELS": "Hanzo O11y | Traces Funnels",
|
|
"DEFAULT": "Open source Observability Platform | Hanzo O11y",
|
|
"SHORTCUTS": "Hanzo O11y | Shortcuts",
|
|
"INTEGRATIONS": "Hanzo O11y | Integrations",
|
|
"ALERT_HISTORY": "Hanzo O11y | Alert Rule History",
|
|
"ALERT_OVERVIEW": "Hanzo O11y | Alert Rule Overview",
|
|
"MESSAGING_QUEUES_OVERVIEW": "Hanzo O11y | Messaging Queues",
|
|
"MESSAGING_QUEUES_KAFKA": "Hanzo O11y | Messaging Queues | Kafka",
|
|
"MESSAGING_QUEUES_KAFKA_DETAIL": "Hanzo O11y | Messaging Queues | Kafka",
|
|
"MESSAGING_QUEUES_CELERY_TASK": "Hanzo O11y | Messaging Queues | Celery",
|
|
"INFRASTRUCTURE_MONITORING_HOSTS": "Hanzo O11y | Infra Monitoring",
|
|
"INFRASTRUCTURE_MONITORING_KUBERNETES": "Hanzo O11y | Infra Monitoring",
|
|
"METRICS_EXPLORER": "Hanzo O11y | Metrics Explorer",
|
|
"METRICS_EXPLORER_EXPLORER": "Hanzo O11y | Metrics Explorer",
|
|
"METRICS_EXPLORER_VIEWS": "Hanzo O11y | Metrics Explorer",
|
|
"API_MONITORING": "Hanzo O11y | External APIs",
|
|
"METER_EXPLORER": "Hanzo O11y | Meter Explorer",
|
|
"METER_EXPLORER_VIEWS": "Hanzo O11y | Meter Explorer Views",
|
|
"METER": "Hanzo O11y | Meter",
|
|
"ROLES_SETTINGS": "Hanzo O11y | Roles",
|
|
"MEMBERS_SETTINGS": "Hanzo O11y | Members"
|
|
}
|