Skip to content

feat: apply the 2026 brand to the Phoenix docs - #15458

Open
jimbobbennett wants to merge 7 commits into
mainfrom
feat/new-brand-design-system
Open

feat: apply the 2026 brand to the Phoenix docs#15458
jimbobbennett wants to merge 7 commits into
mainfrom
feat/new-brand-design-system

Conversation

@jimbobbennett

Copy link
Copy Markdown
Contributor

Ports the 2026 design system already applied to the Arize AX docs (Arize-ai/docs#840), keeping Phoenix's own cyan identity. The layout does not change — this is colour, type, surfaces and icons.

Phoenix keeps its own palette

The brand token set carries a dedicated [data-mode="phoenix"] block: cyan accent, neutral near-black surfaces, but the same Geist type and 2/8px radii as AX. So the structure is shared and the hue is not — Phoenix does not become magenta.

before after source
colors.primary (light emphasis) #0384C3 #00769E derived, see below
colors.light (dark emphasis) #0384C3 #39C7FF token set accent-5
colors.dark (button fills) #0384C3 #009DD2 token set accent-1
background light / dark — / gradient #FFFFFF / #08090A token set page bg
surface (dark) #151616 token set container bg
fonts Roboto Geist + Geist Mono token set typography
icon library fontawesome lucide matches AX

Why #00769E and not the brand cyan. The token set defines Phoenix as dark-only, so light-mode values had to be derived. The brand cyan #009DD2 is only 3.1:1 on white — below AA. #00769E is the same hue darkened until it clears AA against both the white page (5.14:1) and the pale accent-soft pill it sits on in the active sidebar item (4.56:1). Solving for both was necessary; the first candidate passed on white but failed at 4.04:1 on the pill.

Heads up on the accent mapping. The docs.json JSON-schema says colors.dark is "used primary in light mode". That is wrong — measured from rendered output, primary is light-mode emphasis, light is dark-mode emphasis, and dark is button/hover fills in both. Getting it the schema's way puts the light accent on white at ~3:1.

docs/style.css

The highest-leverage change is replacing the --gray-* ramp: Mintlify derives it from colors.primary, so it was tinting every surface, hairline and muted text. The 400/900/950 stops are the token set's own Phoenix values (#A1A4AB, #151616, #08090A).

Then component styling for the navbar, sidebar, TOC, cards, code blocks, callouts, tables, the copy-page control and the changelog. Callout families are keyed off data-callout-type.

Changelog entries now stack at every width, so the date heads a full-width section instead of sitting in a 160px sticky column beside narrowed content.

Phoenix's existing rules (.sr-only, card-group image heights, table, .step-title, .invert-on-dark, .release-update-read-more) are carried over unchanged.

Two implementation notes carried over from the AX work, both of which cost real debugging there:

  • Surface selectors are doubled (.card.card). Mintlify styles these with dark: utilities that compile to .foo:is(.dark *) — specificity (0,2,0). A single class is (0,1,0) and silently loses in dark mode only.
  • The copy-page chevron is matched via aria-haspopup, not :last-child. Opening its menu injects sibling elements into the container, so a positional selector stops matching mid-interaction and the button visibly shrinks.

Icons

icons.library is a single global choice, and the two libraries behave differently:

  • Brand marks need no work — Mintlify resolves github, python, java, docker, aws, npm, google, golang, js, microsoft against fontawesome even under lucide. 572 references untouched.
  • Non-brand fontawesome names get no fallback — they resolve to a lucide URL that 404s and render blank. So 184 renames across 72 mdx files were mandatory, plus 19 in docs.json navigation (easy to miss — they are not in MDX).

Verified: all 1,175 icon references across 118 names resolve; zero blanks.

Judgement calls worth a look

Eleven mappings where lucide has no close equivalent — please sanity-check these:

was now note
dharmachakra ship-wheel Kubernetes helm; lucide has no dharmachakra
train train-front front elevation rather than side
signal-stream radio-tower
compress shrink
file-csv file-spreadsheet no csv-specific glyph
chart-simple chart-column
face-frown face-slightly-frowning lucide has no plain frown
sitemap network now identical to network-wired
comments messages-square now identical to messages
window-maximize app-window now identical to browser
warning triangle-alert now identical to triangle-exclamation

Also drops three hardcoded #3b82f6 callout colours so they inherit the theme accent.

Verification

Audited with a scripted in-page check across 11 pages × light and dark, asserting every ramp stop, accent var, surface, border, radius, and the structural selectors (navbar rule width, tab underline, copy-button halves equal height, changelog columns equal width), plus a sweep for icons painted as solid blocks.

Zero failures. Worst contrast anywhere in scope: 4.56:1. Coverage was checked too — every assertion ran and passed on at least one real page, so nothing was silently skipped.

check-card-links.js passes. mint broken-links reports 11 in 9 files — verified by exact path comparison as pre-existing, none of them in this diff.

Pre-existing issue found, not fixed here

docs/phoenix/settings/sandboxes.mdx contains a hand-authored diagram with hardcoded light-theme colours (#334155, #4C1D95, #F4DDFF). In dark mode that text sits at 1.8–1.9:1. It is not caused by this change and the file is not in this diff, but it has never worked in dark mode and is worth a separate fix.

Worth a reviewer's eye

  • Phoenix has no appearance.default, so it follows the system preference. Light mode is therefore as load-bearing as dark here — more so than on AX, which defaults to dark.
  • Type scale: only the H1 is matched to the design (46px). The rest keeps Mintlify's responsive scale; pinning body/h2 was tried on AX and reverted as too large.
  • Mintlify's CSS hooks are documented as subject to change with no version pinning, so this layer wants a visual check after CLI upgrades. Two bugs in the AX PR came from exactly that drift.

🤖 Generated with Claude Code

Ports the design system already applied to the Arize AX docs, keeping Phoenix's
own cyan identity. The layout does not change; this is colour, type, surfaces and
icons.

Phoenix keeps its own palette. The brand token set carries a dedicated
[data-mode="phoenix"] block — cyan accent, neutral near-black surfaces — with the
same Geist type and 2/8px radii as AX, so the structure is shared and the hue is
not.

docs.json
- Accents: primary #00769E (light-mode emphasis), light #39C7FF (dark-mode
  emphasis), dark #009DD2 (button fills). Note the docs.json JSON-schema
  describes this mapping incorrectly; these are what actually render.
- Backgrounds #FFFFFF / #08090A, gradient decoration dropped.
- Geist for heading and body; Geist Mono for code via CSS, as there is no
  docs.json slot for it.
- icons.library switched to lucide; brand marks pinned to fontawesome.

The token set defines Phoenix as dark-only, so light-mode values are derived. The
brand cyan #009DD2 is only 3.1:1 on white, so light-mode emphasis uses a darkened
#00769E — 5.1:1 on the page and 4.6:1 on the accent-soft pill.

docs/style.css
- Replaces the neutral ramp, which Mintlify otherwise derives from the primary
  colour and which therefore tinted every surface and hairline.
- Mode-scoped --px-* tokens, then component styling for the navbar, sidebar, TOC,
  cards, code blocks, callouts, tables, the copy-page control and the changelog.
  Callout families are keyed off data-callout-type.
- Changelog entries stack so the date heads a full-width section.
- Phoenix's existing rules are carried over unchanged.

Icons
- 184 fontawesome-only names remapped to lucide across 72 mdx files, plus 19 in
  docs.json navigation. Non-brand fontawesome names have no fallback under lucide
  and would render blank.
- Brand marks (github, python, java, docker, aws, npm, …) are untouched: Mintlify
  resolves those against fontawesome automatically.
- Eleven mappings are judgement calls where lucide has no close equivalent; they
  are listed in the PR description.

Also drops three hardcoded generic-blue callout colours so they inherit the theme.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@mintlify

mintlify Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
arize-phoenix 🟢 Ready View Preview Aug 16, 2026, 2:10 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Five of the six tabs wrapped their landing page in a group named " " —
Documentation, Integrations, Self-Hosting, Cookbooks and Release Notes. Mintlify
renders a group's name as an eyebrow above the page H1, so that single space
produced a blank line there plus an empty header in the sidebar.

A tab's `pages` array accepts nested group objects, so each wrapper's contents are
hoisted to tab level and the wrapper dropped. Tabs may carry either `pages` or
`groups` but not both, so the remaining real groups move into `pages` alongside
the hoisted items, preserving order.

Verified no page was added, dropped or reordered: 708 pages, byte-identical
flattened order per tab, no blank-named groups left, and no tab carrying both
keys. Pages that were inside a wrapper (self-hosting/architecture, license,
cookbook) now have no eyebrow rather than an empty one; grouped pages keep theirs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four of the six AX fixes apply here; the other two have no Phoenix counterpart
(there is no hero panel, and no coding-agent snippet).

- Prose links: these render as `<a class="link">`, and the rule here was
  `a:not(.card):not(.link)` — so it excluded exactly the links it was meant to
  style, leaving them on Mintlify's link colour. Now scoped correctly and set to
  the brand accent.
- Step number circles: shipped as a plain grey disc; now the design's
  accent-soft disc with a hairline accent ring and accent numeral.
- Code inside callouts: sits on the page background rather than the code
  surface, so a tinted callout does not carry a second tint.
- Table-of-contents active entry: marked by colour alone. Mintlify also bolds it,
  which the design does not.

Also fixes two callouts that asked for a warning and did not get one. `type` is
not a `<Callout>` prop, so `<Callout type="warning">` rendered as a neutral
generic callout. Replaced with `<Warning>` in the Claude Code and OpenCode
integration pages — same defect class as the AX callout fix, with the author's
intent explicit in the markup.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…-system

# Conflicts:
#	docs/phoenix/release-notes/08-2026/08-12-2026-session-filters-rest-api-and-endpoint-config.mdx
@jimbobbennett
jimbobbennett marked this pull request as ready for review August 17, 2026 22:45
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Aug 17, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mc2tUw43f5K7tNEk6nU5Fk

<CardGroup cols={2}>
<Card title="User Friction" icon="face-frown" href="/docs/phoenix/evaluation/pre-built-metrics/user-friction">
<Card title="User Friction" icon="face-slightly-frowning" href="/docs/phoenix/evaluation/pre-built-metrics/user-friction">

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.

face-slightly-frowning isn't a valid name in either library, so this icon will render blank.

Lucide has no face-* namespace — its emotion set is angry / annoyed / frown / laugh / meh / smile / smile-plus, so the plain frown the description says is missing does exist (it's inherited from Feather). FontAwesome has face-frown and face-frown-open but not face-slightly-frowning; that string is the Unicode/CLDR emoji name for 🙁, not an icon id in either set.

It's the only face--prefixed name left in the docs — every other renamed icon in this PR maps to a real lucide id. Note the same "User Friction" card in pre-built-metrics.mdx was mapped to messages-square instead:

</Card>
<Card title="User Friction" icon="messages-square" href="/docs/phoenix/evaluation/pre-built-metrics/user-friction">
Detects corrections, retries, frustration, and challenges expressed in a user's follow-up message.

Suggested change
<Card title="User Friction" icon="face-slightly-frowning" href="/docs/phoenix/evaluation/pre-built-metrics/user-friction">
<Card icon="frown" href="/docs/phoenix/evaluation/pre-built-metrics/user-friction">

(or messages-square for consistency with the other page)

<Card title="Document Relevance" icon="file-search" href="/docs/phoenix/evaluation/pre-built-metrics/document-relevance">
Assesses whether retrieved documents are relevant to the input query. Useful for RAG evaluation.
</Card>
<Card title="Tool Selection" icon="toolbox" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection">

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.

toolbox is a FontAwesome-only name that wasn't included in the rename sweep, so it's newly orphaned by the library flip and will render blank.

Lucide has no toolbox — the nearest equivalents are wrench, briefcase, or hammer. Per the PR description, non-brand FontAwesome names get no fallback under library: "lucide":

phoenix/docs.json

Lines 30 to 34 in 4e3cc26

},
"icons": {
"library": "lucide"
},
"styling": {

It's one of only three non-brand FontAwesome-shaped names left in the docs (toolbox, user-shield, list-check) — the other icons on this page are all valid lucide ids.

Suggested change
<Card title="Tool Selection" icon="toolbox" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection">
<Card icon="wrench" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection">

<Card title="Query for Documents" href="/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans#querying-for-retrieved-documents" icon="file-search" horizontal description="Document retrieval queries"/>
<Card title="Filter Expressions" href="/docs/phoenix/tracing/how-to-tracing/filter-expressions" icon="funnel" horizontal description="Filter spans and sessions with expressions"/>
<Card title="Extract Attributes" href="/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans#how-to-extract-attributes" icon="tags" horizontal description="Attribute extraction tips"/>
<Card title="Use Pre-defined Queries" href="/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans#pre-defined-queries" icon="list-check" horizontal description="Prebuilt query patterns"/>

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.

list-check (singular) is a FontAwesome name — lucide's is list-checks (plural). It was missed by the rename sweep, so under library: "lucide" this card renders blank while the four neighbours in this same <Columns> block were all correctly remapped.

phoenix/docs.json

Lines 30 to 34 in 4e3cc26

},
"icons": {
"library": "lucide"
},
"styling": {

Suggested change
<Card title="Use Pre-defined Queries" href="/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans#pre-defined-queries" icon="list-check" horizontal description="Prebuilt query patterns"/>
<Card href="/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans#pre-defined-queries" icon="list-checks" horizontal description="Prebuilt query patterns"/>

Comment thread docs.json
@@ -1245,12 +1250,14 @@
},

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.

(anchored here — the affected line is just above, outside the diff hunk)

user-shield is a FontAwesome-only name that the rename sweep missed. Lucide's equivalent reverses the word order: shield-user. Under library: "lucide" both of these render blank:

  • phoenix/docs.json

    Lines 1243 to 1245 in 4e3cc26

    "group": "Security",
    "icon": "user-shield",
    "pages": [
    — the "Security" nav group
  • </Card>
    <Card title="Access Controls" href="/docs/phoenix/settings/access-control-rbac" icon="user-shield">
    Role-based permissions
    — the "Access Controls" card

Every other shield/user icon left in the docs (shield, shield-check, user-lock, user-plus, users) is a valid lucide id, and the sweep applied exactly this pattern nearby (shield-halvedshield, user-robotbot, user-chefchef-hat), so this looks like an oversight rather than a deliberate keep. Both sites need icon: "shield-user".

Mintlify serves lucide v1.16.0 from its CDN. user-shield and
face-slightly-frowning are canonical ids in current lucide but postdate
v1.16.0, so both 403 and render blank:

  user-shield            -> shield-user  (docs.json Security nav, self-hosting.mdx)
  face-slightly-frowning -> frown        (07-22 release note)

Addresses two of the four review comments. The other two (toolbox,
list-check) were false positives — both return 200 from the v1.16.0 CDN
and render correctly, so they are left alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mc2tUw43f5K7tNEk6nU5Fk
@github-project-automation github-project-automation Bot moved this from 📘 Todo to 👍 Approved in phoenix Aug 18, 2026
Comment thread docs.json Outdated
}
},
"icons": {
"library": "lucide"

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.

Switching the default icon library to lucide orphans the FontAwesome brand icon names that are still used unqualified across the docs. Lucide deliberately excludes brand/logo marks, so these names no longer resolve and will render as blank space (they rendered fine before, under the implicit FontAwesome default).

Still bare strings in this file:

phoenix/docs.json

Lines 627 to 629 in 25c3c16

"group": "TypeScript",
"icon": "js",
"pages": [

plus "python" (L679, L938), "java" (L837), "js" (L948).

And in .mdx — including two files this PR does edit, where the generic icons on adjacent lines were migrated but the brand ones were skipped:

<Tabs>
<Tab title="Python" icon="python">
<CardGroup cols={4}>

</Card>
<Card title="Docker" href="/docs/phoenix/self-hosting/deployment-options/docker" icon="docker">
Docker or Compose

Repo-wide counts of unqualified names with no lucide equivalent: python ×211, js ×194, golang ×20, npm ×4, docker/aws/microsoft ×2 each, java/google ×1 each — ~437 .mdx usages plus the 5 in docs.json. (github ×130 does exist in lucide, so those render, just with a different mark.)

The footer socials were already handled correctly with the object form, which is the fix to apply here too:

phoenix/docs.json

Lines 1667 to 1673 in 25c3c16

"href": "https://x.com/ArizePhoenix",
"title": "X",
"icon": {
"name": "x-twitter",
"library": "fontawesome",
"style": "brands"
}

For docs.json nav entries, use "icon": { "name": "python", "library": "fontawesome", "style": "brands" }. For .mdx <Card>/<Tab> props (which take a plain string), either swap to a lucide-native equivalent or use <Icon icon="python" library="fontawesome" iconType="brands" /> where the brand mark matters. A grep -rnE 'icon="(python|js|java|golang|npm|docker|aws|microsoft|google)"' docs --include=*.mdx sweep will catch the rest.

<Card title="Document Relevance" icon="file-search" href="/docs/phoenix/evaluation/pre-built-metrics/document-relevance">
Assesses whether retrieved documents are relevant to the input query. Useful for RAG evaluation.
</Card>
<Card title="Tool Selection" icon="toolbox" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection">

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.

toolbox is a FontAwesome-only name — lucide has no such icon, so with icons.library: "lucide" now set globally this card renders with a blank icon.

This looks like a missed rename rather than a deliberate keep: every other FontAwesome-only name in this CardGroup was migrated in this same hunk (check-doublecheck-check, compressshrink, file-magnifying-glassfile-search, arrow-turn-downcorner-right-down, commentsmessages-square), and the names left untouched (ghost, circle-check, wrench, hand) are all valid lucide icons.

Note wrench is already taken by the "Tool Invocation" card just below, so it needs a distinct name:

Suggested change
<Card title="Tool Selection" icon="toolbox" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection">
<Card icon="briefcase" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection">

Mirrors the AX revert. FontAwesome's default style in Mintlify is already
'regular' — the lighter outline set — so removing icons.library restores light
icons without touching a single iconType prop.

Reverted at line level from the diff rather than by a global name map, and every
original name was checked against Mintlify's FontAwesome build first. Three nav
and card icons the line-level pass missed (their lines had other edits) were
restored by hand: chef-hat -> user-chef, settings -> gear, layers -> layer-group.

Verified: all 131 icon names now resolve — 121 via regular, 10 via brands, zero
blank.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mc2tUw43f5K7tNEk6nU5Fk
@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Aug 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Card links check

No broken Card links found. Checked external links in 20.2s

Comment thread docs.json
"group": "Upgrade",
"icon": "angles-up",
"pages": ["docs/phoenix/self-hosting/upgrade/migrations"]
"icon": "chevrons-up",

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.

chevrons-up is a lucide-only name, but this PR never actually switches the icon library — there is no icons key anywhere in docs.json (jq '.icons'null, and "lucide" appears nowhere in the diff). Mintlify therefore still resolves icons against its Font Awesome default.

Font Awesome names the double chevron angles-up and has no chevrons-* icons in Free or Pro. Because Mintlify renders these as CSS mask-image, the 404 paints nothing — the Self-Hosting → Upgrade group icon will render blank rather than showing a broken-image affordance.

The rest of the file confirms Font Awesome is still in force: gear-complex, user-robot, user-chef, rectangle-terminal, boxes-stacked, shield-halved, and wand-magic-sparkles are all FA-only names left untouched by this PR. The other renames here (rocket-launch, puzzle, gear, circle-check, wand-sparkles) all remain valid FA names — chevrons-up is the only outlier.

phoenix/docs.json

Lines 1232 to 1236 in 21c6b1e

{
"group": "Upgrade",
"icon": "chevrons-up",
"pages": [
"docs/phoenix/self-hosting/upgrade/migrations"

Suggested change
"icon": "chevrons-up",
"icon": "angles-up",

(Alternatively, land the "icons": { "library": "lucide" } switch and the full rename sweep the PR description describes — but as committed, the two halves disagree.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

Status: 👍 Approved

Development

Successfully merging this pull request may close these issues.

2 participants