Skip to content

Nest Request Body fields under their heading in OpenAPI docs#19009

Draft
djgrove wants to merge 3 commits into
masterfrom
dgrove/openapi-request-body-nesting
Draft

Nest Request Body fields under their heading in OpenAPI docs#19009
djgrove wants to merge 3 commits into
masterfrom
dgrove/openapi-request-body-nesting

Conversation

@djgrove
Copy link
Copy Markdown
Member

@djgrove djgrove commented May 14, 2026

Summary

  • Wrap each operation's Request Body subtree in a bordered card (.api-request-body) that mirrors how .api-response already presents response schemas, so body fields are visually nested under the Request Body heading instead of sitting flush-left with the section's Request Parameters list.
  • Request Parameters keep their existing flat layout: path and query parameters aren't fields of an enclosing object, so indentation there would imply false nesting.

Problem

On generated OpenAPI docs pages (/docs/reference/cloud-rest-api/...), each operation shows three field sections under the endpoint heading: Request Parameters, Request Body, and Responses. All three render fields via the same property-rows.html partial. The inconsistency was structural, not in the list rendering:

  • Responses wrap each status code in <div class=\"api-response\">, a bordered, padded card. The schema label and field list live inside, so every response field reads as nested under the Responses heading.
  • Request Body had no such wrapper. The <h4>Request Body</h4> was followed directly by the schema label and <ul class=\"api-params\">, all flush-left — at the same margin as the path/query parameters listed above.

Net effect: a body field like entity looked like just another peer parameter rather than a member of, say, CreateXRequest. Internal feedback flagged exactly this confusion.

Change

  • layouts/partials/openapi/endpoint.html: wrap the request body's schema label and property list in <div class=\"api-request-body\"> for both the $ref and inline-schema branches.
  • assets/fingerprinted/css/openapi.css: add .api-request-body styles (same border/padding/radius/background as .api-response) plus the matching .api-params first/last-child overrides so the field list reads cleanly inside the card.

Test plan

  • Confirm on the Netlify deploy preview that on an OpenAPI operation page (e.g. anything under /docs/reference/cloud-rest-api/) the Request Body section now renders as a bordered card, visually nesting its schema fields under the Request Body heading.
  • Confirm the Responses section still renders unchanged.
  • Confirm the Request Parameters section still renders flush-left and unchanged.
  • Spot-check an endpoint whose body is an inline (non-$ref) schema and one that uses $ref to a component schema to verify both branches.

Wrap each operation's Request Body subtree in a bordered card
(`.api-request-body`) so its fields are visually nested under the
Request Body heading, matching how the Responses section already
renders its status-coded `.api-response` cards. Without this, the
body's schema fields sat flush-left at the same margin as the
section's Request Parameters list, making nested fields look like
peer parameters.

Request Parameters keep their existing flat layout — they're path
and query inputs, not fields of an enclosing object, so indentation
would imply false nesting.
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 14, 2026

Docs review — PR #19009

Focused, low-risk change: a bordered .api-request-body card around the Request Body schema and field list, with CSS mirroring .api-response. The PR description does a great job explaining the structural inconsistency it fixes (body fields rendering flush-left with peer parameters). Code looks correct.

A few small notes — all minor / optional:

CSS — duplication and placement

assets/fingerprinted/css/openapi.css:344-368 is a near-clone of the existing .api-response block at lines 373-379 and 413-425. Five of the six rules are identical down to the values. A shared selector would cut ~15 lines and keep the two cards visually in lockstep if either is ever restyled:

/* Bordered card used for the Request Body and each Response. Both nest a
   field list (.api-params) under a section heading; sharing the selector
   keeps them visually in lockstep. */

.api-request-body,
.api-response {
    margin: 1rem 0 1.25rem;
    padding: 0.75rem 1rem;
    border: 1px solid #eaeaea;
    border-radius: 4px;
    background: #fff;
}

.api-request-body .api-params,
.api-response .api-params {
    margin-top: 0.5rem;
    border-top: none;
}

.api-request-body .api-param:first-child,
.api-response .api-param:first-child {
    padding-top: 0;
}

.api-request-body .api-param:last-child,
.api-response .api-param:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

.api-request-body .api-schema-label {
    margin-top: 0;
}

If you'd rather keep them separate to allow them to diverge later, then at least consider placing the new .api-request-body block next to .api-response (currently it sits at line 340, above the comment at line 370 that introduces the response styles). The order works because of selector specificity, but a reader scanning the file sees .api-request-body .api-schema-label { margin-top: 0 } before .api-schema-label itself is defined.

Visual asymmetry between the two card branches

In layouts/partials/openapi/endpoint.html:55-69 (the $ref branch) the card opens with a Schema: <link> label, then the field list. In the else branch at lines 74-84 (inline schema), there's no label, so the card opens directly with <ul class=\"api-params\">. That's defensible — there's no schema name to link to — but the resulting cards look subtly different. Worth a sanity check on the deploy preview that both read cleanly. If they don't, a generic "Schema:" or "Body:" label on the inline branch would symmetrize them; the .api-request-body .api-schema-label { margin-top: 0 } rule you already added is otherwise unused in that branch.

Pre-existing nit (not blocking, not yours to fix here)

endpoint.html:62 passes \"required\" $resolved.required directly, while the inline branch at line 78 passes \"required\" ($resolved.required | default slice). The asymmetry predates this PR — flagging only as a follow-up cleanup candidate if property-rows.html ever chokes on a nil required.

Things I checked and that look fine

  • Template brace balance after the restructure: 5 {{ end }} close 5 opens (with .details.requestBody, with $jsonContent, if $schema, if isset $schema \"$ref\"/else, if $resolved.properties). The diff also drops a stray trailing {{ end }} at indent 4 that looked like it didn't pair with anything in the surrounding block — good cleanup.
  • New CSS colors (#eaeaea, #fff) match the existing .api-response palette exactly, so the body and response cards will be visually consistent.
  • No accessibility regressions — purely a visual wrapper, no new interactive elements or headings.

Mention me (@claude) if you'd like another pass after applying changes, or if you'd prefer me to focus on a specific part of the review.

@pulumi-bot
Copy link
Copy Markdown
Collaborator

pulumi-bot commented May 14, 2026

@pulumi-bot
Copy link
Copy Markdown
Collaborator

pulumi-bot commented May 14, 2026

Lighthouse Performance Report

Commit: cd22b71 | Metric definitions

Page Device Score FCP LCP TBT CLS SI
Homepage Mobile 🔴 30 5.6s 11.9s 3259ms 0.000 6.9s
Homepage Desktop 🟡 62 0.8s 3.4s 282ms 0.028 3.0s
Install Pulumi Mobile 🔴 38 5.3s 7.7s 237ms 0.438 5.3s
Install Pulumi Desktop 🟡 87 1.3s 1.7s 22ms 0.021 1.8s
AWS Get Started Mobile 🟡 52 5.1s 7.5s 287ms 0.082 7.8s
AWS Get Started Desktop 🟡 88 1.3s 1.7s 22ms 0.024 1.7s

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the generated OpenAPI endpoint documentation layout by visually nesting request body fields under the Request Body heading, matching the existing “card” presentation used for response schemas.

Changes:

  • Wrap request body schema label + property list in a new .api-request-body container in the endpoint template.
  • Add .api-request-body CSS to present request bodies as bordered/padded cards with cleaned-up list borders/padding.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
layouts/partials/openapi/endpoint.html Wrapes the request body schema/fields in .api-request-body for both $ref and inline schema branches.
assets/fingerprinted/css/openapi.css Introduces .api-request-body styling to mirror response cards and adjust nested .api-params list presentation.

Comment thread layouts/partials/openapi/endpoint.html Outdated
Comment thread assets/fingerprinted/css/openapi.css Outdated
These cards are intentionally identical visually — the only reason
.api-request-body exists is to wrap the Request Body's schema list
the same way .api-response wraps each response. Sharing selectors
removes the 5 duplicated rules and keeps the two in lockstep if
either is ever restyled. Also fixes source order: the descendant
selector .api-request-body .api-schema-label no longer appears
before the base .api-schema-label rule that defines it.
@djgrove
Copy link
Copy Markdown
Member Author

djgrove commented May 15, 2026

Thanks @claude — went through each section:

CSS consolidation. Agreed and applied your suggested merge: 9418ca5. The two cards are meant to be identical and now share selectors; this also fixes the source-order issue you flagged (the descendant selector for .api-request-body .api-schema-label no longer appears before the base .api-schema-label rule).

Inline-schema branch asymmetry. Holding the current behavior. response-schema.html only renders the Schema: label when $resolved.schemaName is set, so inline-schema responses already render label-less — matching what the inline-schema request bodies now do. Adding a generic "Body:" label here would create a fresh asymmetry vs. responses. There are 7 inline-body operations in the spec (OAuth token, encrypt/decrypt/batch-decrypt, policygroups/.../batch); all render as a borderless card with a flat field list, which reads cleanly. The .api-request-body .api-schema-label { margin-top: 0 } rule is correctly inert when no label is present.

Pre-existing required nil-default asymmetry at endpoint.html:62 vs :78. Noted as a follow-up — not touching in this PR per your "not yours to fix here" note.

Brace balance / palette / a11y observations. Confirmed.

@pulumi-bot
Copy link
Copy Markdown
Collaborator

pulumi-bot commented May 15, 2026

Claude finished @djgrove's task in 1m 15s —— View job


Follow-up review — all three resolutions look good

Verified each point against the current branch.

CSS consolidation (9418ca5). Diff is clean: 5 duplicated rules collapsed to combined selectors, .api-request-body .api-schema-label { margin-top: 0 } kept as its own rule and moved after the base .api-schema-label definition — source-order issue resolved. Net –34/+13 in openapi.css.

Inline-schema branch — agreed, current behavior is correct. I went back and read layouts/partials/openapi/response-schema.html:4 to double-check, and you're right: the Schema: label there is gated on $resolved.schemaName, so inline responses already render label-less inside their card. Adding a "Body:" fallback on the inline request-body branch would break that cross-section symmetry. Your reasoning lines up with the actual response template; holding it is the right call. The .api-request-body .api-schema-label { margin-top: 0 } rule remains correctly inert when no label is rendered.

required nil-default at endpoint.html:62 vs :78. Agreed, follow-up only. Worth filing a tiny tracking issue if it's not already captured, since the inline branch's | default slice is the safer pattern and the $ref branch should probably match — but explicitly out of scope for this PR.

The Copilot reviewer's two notes also land in the same places — CSS dedup is now addressed by 9418ca5, and their suggestion about reusing response-schema.html for the request-body branch is a reasonable follow-up but a larger refactor than this PR's scope; the inline branch in particular passes ($resolved.required | default slice) which response-schema.html doesn't currently do, so a straight swap would need that nil-default question settled first.

No further changes from me — looks ready.

  • Verify CSS consolidation commit (9418ca5)
  • Verify inline-schema claim against response-schema.html
  • Acknowledge required follow-up and closure
    · Branch: dgrove/openapi-request-body-nesting

Collapses the parallel $ref / inline branches in the Request Body
template into a single call to openapi/response-schema.html — the
same partial Responses use to render their schema card. Drops ~30
lines of duplicated resolve/label/property-list logic from
endpoint.html and ensures request and response schemas can't drift
as response-schema.html evolves.

Incidentally fixes the pre-existing $resolved.required vs
($resolved.required | default slice) asymmetry between the two
branches; property-rows.html already defaults nil required slices
to an empty slice internally.
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.

3 participants