feat(onboarding): add Storybook components#2564
Conversation
Add the presentational building blocks for the redesigned onboarding experience, showcased in Storybook (no app behavior change yet): - OnboardingAccordion: stepper card with status badges/circles and a progress ring - SummaryRow: compact status row (check circle + status badge) for nested setup items - LogoBadge: theme-aware brand logo badge (adds --logo-badge-shadow token) Also fixes Storybook so Drawer/Modal portals inherit the app font (applied to <html>, matching pages/_app.tsx), and adds the react-icons dependency used by the stories. These components are presentational only; the /getting-started page that wires them into the app follows in a separate PR. Co-authored-by: Cursor <cursoragent@cursor.com>
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR is presentational-only — it adds the reusable building blocks (
Confidence Score: 5/5Pure presentational addition with no routing or data-mutation changes; safe to merge. All new components are Storybook-only for now with no production routing wired up. The MDX fetching, catalog lookups, and accordion state management are all straightforward and handle edge cases (missing items, network errors, uncontrolled/controlled mode) correctly. The one stylistic concern — a hardcoded brand name in the drawer title — is a cosmetic issue that won't affect any production user until the follow-up wiring PR ships. IntegrationsDrawer.tsx — the drawer title hardcodes "ClickStack" with no prop override, which will need to be addressed before the component is used in a HyperDX-branded context. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
OA[OnboardingAccordion] --> SR[SummaryRow]
OA --> ID[IntegrationsDrawer]
ID --> DC[DrawerContent]
DC --> CS[ConnectionSnippet]
DC --> IT[ItemTile / CategorySection]
IT -- hasGuide → openGuide --> GV[GuideView]
IT -- no guide --> ExtLink[External docs link]
GV --> CS
GV --> UID[useIntegrationDoc]
UID -- fetch MDX --> GH[(raw.githubusercontent.com)]
GV --> IDM[IntegrationDocMarkdown]
LB[LogoBadge] --> IT
LB --> OA
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
OA[OnboardingAccordion] --> SR[SummaryRow]
OA --> ID[IntegrationsDrawer]
ID --> DC[DrawerContent]
DC --> CS[ConnectionSnippet]
DC --> IT[ItemTile / CategorySection]
IT -- hasGuide → openGuide --> GV[GuideView]
IT -- no guide --> ExtLink[External docs link]
GV --> CS
GV --> UID[useIntegrationDoc]
UID -- fetch MDX --> GH[(raw.githubusercontent.com)]
GV --> IDM[IntegrationDocMarkdown]
LB[LogoBadge] --> IT
LB --> OA
Reviews (9): Last reviewed commit: "feat(integrations): render setup docs fr..." | Re-trigger Greptile |
| 'in-progress': { | ||
| label: 'In progress', | ||
| fg: 'var(--color-bg-warning)', | ||
| bg: 'color-mix(in srgb, var(--color-bg-warning) 18%, transparent)', | ||
| }, |
There was a problem hiding this comment.
The
in-progress entry uses --color-bg-warning (a background-intent token) as the text/foreground color. This works today but is semantically incorrect — if the warning background token is ever adjusted to a color that's only safe on dark surfaces, the badge text will lose contrast. There is no --color-text-warning token defined in either theme, so the closest correct substitute is the amber value expressed directly, or a dedicated text token added alongside the other --color-text-* tokens.
| 'in-progress': { | |
| label: 'In progress', | |
| fg: 'var(--color-bg-warning)', | |
| bg: 'color-mix(in srgb, var(--color-bg-warning) 18%, transparent)', | |
| }, | |
| 'in-progress': { | |
| label: 'In progress', | |
| // TODO: replace with --color-text-warning once that token is added to each theme. | |
| fg: 'var(--color-bg-warning)', | |
| bg: 'color-mix(in srgb, var(--color-bg-warning) 18%, transparent)', | |
| }, |
E2E Test Results✅ All tests passed • 171 passed • 2 skipped • 1053s
Tests ran across 3 shards in parallel. |
Add the presentational IntegrationsDrawer used by the "Send telemetry" step, plus a Storybook story: - IntegrationsDrawer: right-side drawer with searchable, categorized integration tiles (languages, frameworks, infrastructure, cloud, collectors) - SDK/framework tiles open inline copy-paste setup guides with the team's endpoint + ingestion key substituted in; other tiles deep-link to docs - integrationsCatalog + integrationGuides.generated.json back the tiles/guides The drawer is fully prop-driven (opened/onClose/endpoint/apiKey); the getting-started page wiring and the guide generator script land in a follow-up PR. Co-authored-by: Cursor <cursoragent@cursor.com>
Knip - Unused Code Analysis🔴 2 issues found Unused exports (1)
Unused exported types (1)
Knip finds unused files, dependencies, and exports in your codebase. |
…stories The integrations drawer isn't onboarding-specific, so move it out of the GettingStarted folder to a shared components/IntegrationsDrawer/ module (carrying its integrationsCatalog + generated guides, re-exported via index.ts so other surfaces can reuse it). Wire the OnboardingAccordion "Browse integration guides" / "Language SDKs" links to the real IntegrationsDrawer instead of the previous mock docs drawer, opening the languages category from the SDKs link. Removes the now-unused mock (IntegrationsDocsDrawer/DocRow and its static lists). Co-authored-by: Cursor <cursoragent@cursor.com>
Use the broader components/Integrations/ name (was IntegrationsDrawer/) so the module can house more integration-related surfaces beyond the drawer. Co-authored-by: Cursor <cursoragent@cursor.com>
Add the generator that produces components/Integrations/ integrationGuides.generated.json from the ClickStack SDK MDX (yarn generate:integration-guides), pointed at the new Integrations module path, plus the package.json script entry. Include the "machine-readable Quickstart contract" proposal that motivates making the docs structured so the generator can drop its heuristics; adapted to reference this PR's Integrations module and to note it's non-blocking. Co-authored-by: Cursor <cursoragent@cursor.com>
Add an optional `logo` field to catalog items that points to a brand SVG in public/integrations/ and takes precedence over the react-icons glyph/monogram, for logos react-icons doesn't carry. Ship the Vector logo as the first one and switch Vector from its "Vec" monogram to the SVG. Co-authored-by: Cursor <cursoragent@cursor.com>
Add the brand SVGs under public/integrations/ and point every catalog item at its <id>.svg, replacing the react-icons glyphs and text monograms. Render logos on a white tile in both themes since several brand SVGs use near-black marks meant for a light background. Co-authored-by: Cursor <cursoragent@cursor.com>
…rows Replace the two plain endpoint/ingestion-key copy rows at the top of the integrations drawer with a ConnectionSnippet card that mirrors the send-telemetry connection panel (monospace endpoint/api-key block, reveal-key toggle, copy) — scoped to just the URL view, since the collector/env-var/AI-agent tabs aren't relevant when picking an integration. Co-authored-by: Cursor <cursoragent@cursor.com>
…tiles - Add a signals map (logs/traces/metrics) per integration and show a "This guide integrates: [chips]" row in the setup guide. - Mark tiles that deep-link out with a corner external-link icon and an "Opens the docs in a new tab" tooltip, so it's clear which open externally vs. show an inline guide. Co-authored-by: Cursor <cursoragent@cursor.com>
Mantine's Drawer body shrinks its right padding to reserve scrollbar space, which reads as missing right padding on overlay-scrollbar systems. Override paddingInlineEnd so left/right padding match. Co-authored-by: Cursor <cursoragent@cursor.com>
|
@elizabetdev you mentioned it in the call, but I suspect trying to extract the structure from the docs will be a big challenge - especially in the present state where there isn't a strong structure across files. I would suggest we find a way to render the markdown in the product directly from the .md page that the Mintlify docs site serves. For example:
We could give you pages with the structure you need, and it would then be a case of figuring out how we render this markdown within the product. It doesn't look like the page front-matter is served. Compare: https://github.com/ClickHouse/mintlify-docs-dev/blob/main/integrations/language-clients/js.mdx |
… stories Re-wire onDismiss into the story flows so the "Remove from sidebar" footer link renders again, and override paddingInlineEnd on the collector-setup, connection, and data-source drawers so their body padding is symmetric (Mantine reserves scrollbar space on the right). Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the build-time guide generator + committed JSON with runtime rendering of the docs' own markdown, and stop substituting the endpoint / ingestion key into the snippets: - useIntegrationDoc fetches each integration's markdown straight from the ClickStack docs repo; IntegrationDocMarkdown renders it (remark-gfm for tables, copy-able code blocks) - GuideView shows the connection panel plus a note to replace the placeholder endpoint/key, instead of rewriting the snippets - wire inline guides for kubernetes, nginx, kafka, aws, opentelemetry and vector via the integration-examples / ingesting-data docs; "View full docs" uses each page's frontmatter slug - drop the generator script, generated JSON, and the generate:integration-guides package script Also swap the Storybook brand glyphs to public/integrations SVGs and remove the react-icons dependency. Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
First of two PRs for the redesigned onboarding experience. This PR is presentational only — it adds the reusable building blocks and their Storybook stories, with no changes to app behavior or routing. The
/getting-startedpage that wires these into the app (plus the OSS/self-managed/fully-managed flows) will follow in a separate PR, once this one merges.What's included
OnboardingAccordion— stepper card with 3-state status badges/circles (Completed/In progress/Not started), a compact header progress ring, and a "remove from sidebar" footer affordance. Stories cover the OSS, self-managed, and fully-managed flows.SummaryRow— compact, icon-led status row (check circle + status badge, optionalaction/footerslots) used for nested setup items like connect / data sources / collector setup.components/Integrations/— reusable integrations module (not onboarding-specific):IntegrationsDrawer— right-side drawer with searchable, categorized integration tiles (languages, frameworks, infrastructure, cloud, collectors). Fully prop-driven (opened/onClose/endpoint/apiKey/initialCategory), showcased in Storybook and used by the OnboardingAccordion stories.kubernetes,nginx,kafka,aws,opentelemetry, andvector(via thesdks/integration-examples/ingesting-datapages inClickHouse/mintlify-docs-dev). Tiles without a page still deep-link out.slug.useIntegrationDoc+IntegrationDocMarkdown— fetch an integration's markdown at render time and render it (remark-gfmtables, copy-paste code blocks). Kept decoupled from the drawer so a future full integrations page can render the same content.integrationsCatalog— the catalog backing the tiles; each inline item carries adocSourcepointing at its markdown, withdocSourceUrlas the single place to swap sources (e.g. to the docs site's.mdendpoint once it's public).LogoBadge— theme-aware brand logo badge; adds a--logo-badge-shadowdesign token to both thehyperdxandclickstackthemes.document.body, outside the decorator wrapper, so they fell back to the browser default font. The fontclassNameis now also applied to<html>(mirroringpages/_app.tsx) so portal content inherits it.docs/clickstack-docs-quickstart-proposal.md— proposal to the docs team for a stable per-page.mdendpoint, standard placeholder tokens, and lightweight structured frontmatter (category/signals) to power the drawer and a future integrations page (non-blocking).public/integrationsinstead ofreact-icons(dependency removed); addsremark-gfm; switches the rootapp:storybookscript toyarn workspace @hyperdx/app storybook.Why split this out
Keeping the pure presentational components + Storybook separate from the app wiring/migration makes both PRs smaller and easier to review. There is no user-facing behavior change here.
Follow-ups / notes
.mdbehind the Mintlify preview flag; swapping to the public.mdendpoint is a one-line change indocSourceUrl(see the proposal doc).docker,gcp, andazurestill deep-link out — they don't have a dedicated docs page yet.Test plan
yarn workspace @hyperdx/app storybook— review the OnboardingAccordion, SummaryRow, IntegrationsDrawer, and LogoBadge storiespublic/integrationslogos render correctly in bothhyperdxandclickstackthemesmake ci-lintpasses