Commit Graph
122 Commits
Author SHA1 Message Date
Raunak Bhagat 0fe91853b1 feat(opal): stored-secret password tag, tab keyboard nav, tertiary actions (#16275)
## Description

**1. Stored secrets in `InputPasswordTypeIn`**
- New prop `existingValue`: a stored value from the backend, already
masked.
- While `value === existingValue`:
- the field shows the value as a medium blue `Tag` with the key icon,
and the input itself stays empty;
  - the reveal toggle is disabled;
  - Backspace or Delete clears the value;
  - typing or pasting replaces the value with the new text.
- After the first edit, the field is a normal password field again.
- To keep the stored secret on submit, the caller compares the submitted
value with `existingValue`.
- The tag has no tooltip.
- An unchanged existing value does not block submission: the native
`required` check is off while the tag shows. A `readOnly` field keeps
its existing value, and the caller's `onKeyDown` runs first and can
cancel the deletion.
- The `mask` prop and its ✱ overlay are removed. Password fields always
use the browser's own dots.

**Callers that edit a stored secret now pass `existingValue`**
- LLM provider modals (`APIKeyField`, Bedrock, Ollama), SSO provider
modal, index settings, web search, voice, tracing, image generation
(OpenAI, Azure), OpenAPI OAuth client secret, MCP API token and OAuth
secret, MCP user credentials, Craft app user credentials, Slack bot
tokens.
- In each one, the stored masked string is the field's initial value. So
the untouched field keeps Formik's `dirty` false, and a Save gated on
`dirty` stays blocked. Submit logic does not change: an unchanged value
still counts as unchanged.
- SSO used `isNonRevealable` on edit only to protect the stored value.
It uses `existingValue` now.
- No change where the form starts empty for a stored secret: the hooks
modal (only a placeholder holds the masked key), the Discord bot config
and the custom-analytics key.

**Raw password inputs move to `InputPasswordTypeIn`**
- Slack bot tokens, reset password, impersonate (API key,
`autoComplete="new-password"`), custom analytics secret key, plugin
connection dialog.

**2. Keyboard and tab navigation (from the closed #16238)**
These are the Opal parts of the closed Plugins PR. The plugins-specific
parts are left out.
- `Tabs`:
- new `activationMode`. In `"manual"`, the default, arrows move focus
and Enter or Space selects.
  - a focus ring shows while the keyboard moves focus;
- Tab enters the list on the selected tab and the next Tab leaves it, as
the ARIA tabs pattern says;
- Escape leaves the tabs, but only from a tab: a control in
`rightChildren` keeps focus;
  - only a left click focuses a tab.
- `orientation` is omitted from the props: Opal tabs are horizontal
only.
- `Interactive` (stateless): keyboard focus shows the hover state in
place of the browser's ring.
- `useGridNavigation`: keyboard focus on a control inside a grid item
shows again.
- `InputTypeIn` clear button: it keeps focus in the field after it
clears the value, it has an `aria-label`, and it sends `onChange` a real
change event.

- Escape on a control beside a text field (the clear button, the reveal
toggle, a chevron, a chip) returns focus to the field, also when a
tooltip consumed the key. This covers `InputTypeIn` and every input
built on it, plus `TagField`. On `InputTime` and `InputDatePicker`,
which have no single input, it focuses the first segment.

**3. Input action buttons**
- The right-side icon buttons use `tertiary` prominence: the clear
buttons of `InputTypeIn`, `TagField`, `InputTime` and `InputDatePicker`,
and the date picker's calendar button.
- The `InputTypeIn` and `UploadControl` clear buttons have tooltips.
- The tooltip-only clear and calendar buttons of `TagField`, `InputTime`
and `InputDatePicker` get an `aria-label`, so they have an accessible
name.
- The clear button is always an input's last control. `InputDatePicker`
drew it before the calendar button, and `TagField` (`InputTypeInTag`,
the multi-select) drew it before the dropdown chevron.

- `TagField` (`InputTypeInTag`, the multi-select) uses `size="sm"` for
its clear button, as the other inputs do. It used `xs`.

## Additional Options

- [ ] [Optional] Please cherry-pick this PR to the latest release
version.
- [x] [Optional] Override Linear Check

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds an `existingValue` prop to `InputPasswordTypeIn` so forms that edit
backend secrets show the saved value as a key tag instead of editable
masked text, and polishes Opal tab keyboard navigation, focus handling,
and input action buttons.

**Stored secrets**
- `existingValue` marks a stored backend value: while the field's value
equals it, the value renders as a key tag, the input stays empty, and
the reveal toggle is disabled.
- Backspace or Delete clears it; typing or pasting replaces it whole. A
read-only field keeps the value, the caller's `onKeyDown` can cancel the
deletion, and an unchanged tag doesn't fail a native required check.
- Secret-editing forms (Slack tokens, SSO, MCP, language-model and
image-gen modals, tracing, voice, web search, and more) now pass
`existingValue`; a few raw password inputs move to
`InputPasswordTypeIn`. The `mask` prop and idle asterisk overlay are
removed.
- E2E specs for OpenAPI OAuth, index settings, and web search now verify
the stored value appears as a tag with an empty input.

**Keyboard and input actions**
- `Tabs` defaults to manual activation: arrows move focus, Enter or
Space selects, a focus ring tracks keyboard movement, and Escape leaves
the tabs. Only a plain left click focuses a tab; a caller's `onKeyDown`
can cancel the Escape.
- Keyboard focus on `Interactive` surfaces replaces the browser ring
with the hover state; `useGridNavigation` now shows focus on controls
inside grid items.
- `InputTypeIn`'s clear button sends a real change event, keeps focus in
the field after clearing, and gains an `aria-label`.
- Escape on an input's side controls (clear, reveal toggle, chevron,
chip) returns focus to the field, even when a tooltip consumed the key;
on `InputTime` and `InputDatePicker` it focuses the first segment.
- Input action buttons use `tertiary` prominence, the clear button is
always an input's last control, and `TagField`'s clear button is `sm`
like the other inputs'.

<sup>Written for commit 66ab5fd5b3.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/onyx-dot-app/onyx/pull/16275?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="View guided diff"
src="https://www.cubic.dev/buttons/review-in-cubic-light.svg"></picture></a>
<a
href="https://www.cubic.dev/action/auto-fix/pr/onyx-dot-app/onyx/16275?returnTo=https%3A%2F%2Fgithub.com%2Fonyx-dot-app%2Fonyx%2Fpull%2F16275&source=description"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"><img
alt="Turn on auto-fix"
src="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Password fields display saved credentials as masked, non-revealable
tags. Clear them with Backspace or Delete, or replace them by typing or
pasting.
* Tabs use manual activation: arrow keys move focus, while Enter or
Space selects.

* **Improvements**
* Credential fields preserve saved values while editing across
administrative and configuration forms.
* Clear controls provide localized labels and tooltips, and return focus
to the field.
  * Escape restores focus from date, time, tag, and input controls.
* Keyboard focus styling is more consistent across interactive controls
and grid navigation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-10-20 01:32:59 +00:00
Raunak BhagatandClaude Fable 5.1 a2325cf71d refactor(web): replace the legacy InputSelect with Opal's InputSingleSelect (#15104)
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 23:36:57 +00:00
Raunak Bhagat a66077b45a refactor(opal): input naming reorg and select-family grouping (#14664) 2026-09-11 22:02:35 +00:00
Raunak Bhagat f9e3de36c8 refactor(opal): Move the remaining raw inputs into Opal (#14618) 2026-09-10 01:44:35 +00:00
Raunak Bhagat 8a0e43b7ee refactor(opal): Move the dependency-free raw inputs into Opal (#14617) 2026-09-10 01:05:52 +00:00
Raunak Bhagat 3ccf566c65 refactor(web): Retire the refresh inputs that Opal already covers (#14616) 2026-09-10 00:37:28 +00:00
Nikolas Garza 676b36fa41 feat(i18n): format numbers and dates in the UI locale, with Arabic-Indic digits for Arabic (#14589) 2026-09-09 22:22:26 +00:00
Nikolas Garza b65d5cc583 feat(web): complete the i18n string extraction across the product (#14396) 2026-09-01 19:03:47 +00:00
Nikolas Garza 7268c219a8 feat(web): RTL layout support driven by the locale (#14394) 2026-09-01 18:04:59 +00:00
Jamison LahmanandClaude Fable 5 8115edc206 fix(web): use a pointer cursor across the whole InputSelect item (#14269)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 02:23:11 +00:00
Raunak Bhagat 9597046bee refactor(web): migrate every button onto opal and delete the old one (#14243) 2026-08-25 18:51:43 +00:00
Jamison LahmanandClaude Opus 5 f882a42e38 feat(web): enable the jsx-a11y oxlint plugin (#13962)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 16:46:26 +00:00
Raunak Bhagat 4be1a86eb9 refactor(opal): finish the padding migration and close the scales (#13919) 2026-08-12 23:26:38 +00:00
Raunak Bhagat 12c3c6a182 refactor(opal): move the card padding scale onto Spacing (#13916) 2026-08-12 20:14:56 +00:00
Raunak Bhagat f624117dce refactor(opal): give spacing a numeric scale (#13909) 2026-08-12 18:29:06 +00:00
Nikolas Garza 23dbf48fb8 fix(web): fix react-doctor error-class findings and enforce via oxlint plugin (#13850) 2026-08-11 18:45:27 +00:00
Evan LohnandCursor 8b6288931f feat(usage): add cost limits and enforcement UI (#13600)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-30 17:18:28 +00:00
Nikolas Garza 1816f15cf8 refactor(opal): rename action-link-* tokens to action-selection-* (#13529) 2026-07-28 23:58:41 +00:00
claude[bot]andClaude 4669938b1f fix(storybook): align @storybook/* addon versions with storybook 10.5.0 (#13482)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-27 21:00:13 +00:00
Nikolas Garza fa7cc69184 refactor(web): migrate PasswordInputTypeIn consumers to Opal (#12981) 2026-07-23 20:47:32 +00:00
Nikolas Garza 7ff14809a8 refactor(web): migrate InputTextArea consumers to Opal (#12989) 2026-07-20 22:30:47 +00:00
Nikolas Garza aa81dbfe56 fix(opal): keep password text size constant when masked (#13105) 2026-07-16 22:02:55 +00:00
greymothandgreymoth a43f264faf fix(web): ignore IME composition Enter in ListFieldInput (#12511)
Co-authored-by: greymoth <246701683+greymoth-jp@users.noreply.github.com>
2026-06-29 17:35:41 +00:00
Raunak Bhagat d511116416 feat(opal): add shadow prop to @opal/components.Card (#12451) 2026-06-25 23:19:26 +00:00
Nikolas Garza 1d4f36ff62 feat(agent-sharing): share UI foundation - 5/7 (#12025) 2026-06-18 17:01:11 +00:00
Jamison LahmanandClaude Opus 4.8 bc9b6e799e fix(web): don't shrink custom placeholders in PasswordInputTypeIn (#12041)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 22:37:22 +00:00
Jamison LahmanandClaude Opus 4.8 77cc753975 fix(auth): use a native type="password" field on login/signup (#11585)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 16:58:38 +00:00
Raunak Bhagat 925afd2177 refactor(opal): migrate Switch into Opal (#11474) 2026-05-28 19:42:05 +00:00
Raunak Bhagat e9a893d68f refactor(opal): migrate InputTypein into Opal (#11342) 2026-05-28 17:20:04 +00:00
Raunak Bhagat 82389dcc30 fix(opal/divider): fix vertical divider sizing, remove Separator component (#11427) 2026-05-27 18:45:48 +00:00
Jamison LahmanandClaude Opus 4.7 61272ba215 chore(devtools): migrate from prettier to oxfmt (#11040)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 02:32:49 +00:00
Jamison LahmanandClaude Opus 4.7 e356243d43 chore(deps): upgrade tailwindcss v3 → v4 (#11035)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 19:44:53 +00:00
Nikolas Garza 02b76edad6 refactor(opal): drop refresh-components shims, import directly from opal (#10945) 2026-05-08 20:52:19 +00:00
Raunak Bhagat 634cb0b07a refactor(opal): Hoverable variant rename + new variants (#10674) 2026-04-28 13:59:13 -07:00
Raunak Bhagat df332adbf4 fix(opal): separate Opal from @web/src shared utilities (#10598) 2026-04-24 20:04:43 +00:00
Raunak Bhagat 0e11b5a735 chore(opal): move Checkbox into Opal (#10595) 2026-04-24 19:08:21 +00:00
Raunak Bhagat 69fe8b8be5 feat: Admin page cleanup (#10454) 2026-04-22 08:54:45 -07:00
Raunak Bhagat 75ef2b014d refactor(opal): remove -Variant suffix from component props (#10348) 2026-04-18 00:16:51 +00:00
Raunak Bhagat fc0e8560bc feat: opalify Tooltip component, migrate all consumers (#10210) 2026-04-15 03:42:15 +00:00
Raunak Bhagat dee0b7867e refactor: opalify input layouts with trinary withLabel prop (#10144) 2026-04-14 01:28:37 +00:00
Jamison Lahman 3c5f77f5a4 fix: fetch Custom Models provider names (#10004) 2026-04-08 14:22:42 -07:00
Raunak Bhagat 0d3a6b255b chore: update custom LLM modal descriptions (#9946) 2026-04-06 21:55:31 +00:00
Raunak Bhagat 01748efe6a refactor: clean up KeyValueInput and EmptyMessageCard (#9947) 2026-04-06 21:18:45 +00:00
Raunak Bhagat 67c8df002e refactor: update Button to define its own internal disabled styling (#9851) 2026-04-02 16:42:35 +00:00
Jamison Lahman 9c5c42479c fix(a11y): migrate some buttons to Hoverable (#9778) 2026-04-01 15:35:07 +00:00
Justin Tahara 865c893a09 chore(agents): Match Mocks & Add Date Validation (#9632) 2026-03-25 21:57:31 +00:00
Bo-Onyx b20a5ebf69 feat(hook): Add frontend feature control and admin hook page (#9575) 2026-03-25 00:37:37 +00:00
Nikolas Garza 2425bd4d8d feat(groups): add shared resources and token limit sections (#9538) 2026-03-24 23:44:44 +00:00
Nikolas Garza ca6ba2cca9 fix(admin): users page UI/UX polish (#9366) 2026-03-16 15:27:03 +00:00
Raunak Bhagat a6815d1221 feat(llm-modal-consolidation): Update components (#9334) 2026-03-13 19:26:01 +00:00