Skip to content

fix(forms): stop placeholders reading as values a blank field doesn't submit - #1887

Draft
dawsontoth wants to merge 1 commit into
stagefrom
claude/1294-placeholder-usability
Draft

dawsontoth wants to merge 1 commit into
stagefrom
claude/1294-placeholder-usability

Conversation

@dawsontoth

@dawsontoth dawsontoth commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

A rabbit marking example text as an example on a stump form

⊙ Problem

Some Fabric placeholders show a real-looking value that a blank field does not submit (#1294). Users read the field as already filled and leave it blank, or retype the grey text by hand. The worst case is OAuth Scope: a blank Scope saved an empty string, and that empty string replaces the provider's preset scope, so sign-in ran with no scope at all.

❓ Your call: every row in the table below is a UX wording call. Each row is a one-line text change except Scope, so any of them can be reverted on its own.

💡 Solution

I went through all ~70 placeholders in src and sorted each one with a single rule. A placeholder that shows a value must either be what a blank field submits, or read as an example. Instructions ("Search…", "Choose Role") and placeholders that already match what a blank field submits are left alone (see Left unchanged below).

Where Field Before After Why
Org → Settings → OAuth (add + edit) Scope placeholder openid email profile, but a blank field sent '' placeholder unchanged; a blank field now sends openid email profile Makes the placeholder true. See the evidence below
Org → Settings → OAuth (add + edit) Domain company.okta.com e.g. company.okta.com Required field that looked filled in
New cluster (self-managed) Optional Cluster Load Balancer Host Name example.your-company.com e.g. cluster.your-company.com Optional field: a blank one sets no host name, but it looked set
Applications → Import, and Redeploy Install Command npm install Leave blank to install dependencies automatically A blank field already gets Harper's automatic install. Typing npm install is not the same thing: it opts out of the automatic install. Evidence below
Schema editor → field → Index options Index type HNSW e.g. HNSW A blank type means a standard index, not HNSW, so users thought they had a vector index
API explorer → Authorize → Bearer Token eyJhbGciOi… e.g. eyJhbGciOi… A cut-off JWT looks like a token that is already stored

❓ Your call: on edit, a provider saved with an empty scope gets openid email profile written the next time anyone saves it, even if the admin only changed the domain. Today that config signs in with an empty scope, so this repairs it, but it is a write the admin didn't type.

❓ Your call: HNSW is Harper's only custom index type, so e.g. slightly implies there are others. The fuller fix the issue mentions is a dropdown (Standard / HNSW). I didn't do that because the schema editor's text fields round-trip any directive argument as-is, and a dropdown would drop unknown values.

Evidence for the behavioral claims (traced, not assumed):

  • Scope. Studio sends '' for a blank Scope. Central manager passes the stored value to @harperfast/oauth unchanged. That library's buildProviderConfig spreads it over the preset: config.ts:79-82 @ v1.6.0, the version central manager pins. v2.9.0 still keeps an explicit '' (config.ts:548-552). The authorize request then sends scope: this.config.scope || '' (OAuthProvider.ts:76 @ v1.6.0).
  • Install Command. Harper runs a custom command only when one is set (Application.ts:4402). Otherwise it uses the package manager from package.json devEngines.packageManager (:4457), and falls back to npm with --omit=dev (:4540). A redeploy with a blank command writes no install block (operations.js:793). Harper 5.0.0 and 4.7 use the same order: custom command, then devEngines, then npm.
  • Index type. CUSTOM_INDEXES holds only HNSW (customIndexes.ts:4), and a blank type returns early as a standard index (databases.ts:3482). Distance left blank is cosine (HierarchicalNavigableSmallWorld.ts:543-548), so its cosine placeholder stays.

Left unchanged

  • Already what a blank field submits: new-org Name and Subdomain, cluster Host Name and Operations API Port, Create Table's Primary Key id and Database data, Import Data's Database data, the schema editor's Database data, table/endpoint name overrides and Distance cosine, and the new application's Name.
  • Instructions, not values: search and filter boxes, Choose … selects, Your password, Leave blank to keep existing, Okta Client ID/Secret, Optional, Page.
  • Already examples: e.g. us-east-1, e.g. 100OFF, e.g. example.com, *.example.com, e.g. https, operations, wss, e.g. 280ms, medium distribution.
  • Conventional, or deliberately value-shaped: you@company.com on the auth pages reads as a template. The secret editor's ******** deliberately signals a hidden existing value, next to Reveal. The cluster instance protocol select's https:// placeholder never shows, because secure is always set. In the admin-only notification composer, the link sample lists two alternatives joined by "or", and a blank message is rejected when you submit.

Skipped (would conflict)

🔧 Changes

✅ Verification

Closes #1294

🤖 Generated with Claude Code

Related PRs: none found
Complexity: easy

Review-Coverage: authored=claude; ran=gemini,codex; blocked=cursor-grok(no-receipt),cursor-composer(no-receipt),domain(auth); declined=cursor-kimi,cursor-muse; rounds=1; full=1 @ 53c9df4

Review-Attention: study ~11m (critical: FieldRow.tsx; raised: degraded review) @ 53c9df4

… submit

A placeholder that shows a real-looking value reads as already filled in, so
users either leave the field blank expecting that value or retype it by hand.
Each one now either is what a blank field submits, or reads as an example:

- OAuth Scope: a blank field now submits the default its placeholder shows.
  Central manager stores the scope verbatim and it overrides the provider
  preset, so a blank Scope signed in with an empty scope.
- Install Command (import + redeploy): the "npm install" placeholder said
  what to type, but a blank field already gets Harper's automatic install,
  and typing "npm install" opts out of it. The placeholder now says so.
- Okta domain, load balancer host name, HNSW index type and the API
  explorer bearer token read as examples ("e.g. ...").

Also gives the OAuth provider card's icon-only edit button an accessible
name ("Edit provider").

Closes #1294

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request improves user experience and form validation by updating several input placeholders for clarity, adding accessibility labels, and ensuring that empty or whitespace-only OAuth scope inputs default to a standard fallback value. Additionally, a new test suite has been added to verify the OAuth scope behavior under various conditions. There are no review comments, and the changes look correct and well-tested.

@github-actions

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 67.9% 10155 / 14954
🔵 Statements 68.04% 10833 / 15921
🔵 Functions 61.38% 2625 / 4276
🔵 Branches 62.79% 7719 / 12293
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/features/clusters/upsert/fields/ClusterFQDN.tsx 0% 100% 0% 0% 18-37
src/features/instance/apis/explorer/SettingsPanel.tsx 94.02% 82.19% 93.33% 93.93% 42, 206, 371-377, 394
src/features/instance/applications/components/NewApplication/ImportInstructions.tsx 62.5% 100% 50% 62.5% 33, 91-128
src/features/instance/applications/components/SchemaEditorView/FieldRow.tsx 42.55% 66.66% 22.85% 38.09% 58, 60, 62, 64, 84-91, 127-268
src/features/organization/settings/index.tsx 73.61% 69.76% 64.7% 75.71% 83, 121, 122, 134-138, 145-146, 151-152, 157-160, 199, 263-369, 404-405, 479-480
Generated in workflow #2100 for commit 53c9df4 by the Vitest Coverage Report Action

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.

Improve placeholder text usability in Fabric

1 participant