Skip to content

Conversation

@louismorgner
Copy link
Collaborator

@louismorgner louismorgner commented Dec 8, 2025

This PR adds a complete onboarding flow UI with 6 steps including organization setup, team creation, role definition, and metrics tracking.

Note: This is UI-only implementation for now - no data persistence or backend integration yet.

Key Changes

  • 6-step onboarding flow with split-screen layout (form + visualization)
  • Organization name step with optional website field
  • Member import step (Google Workspace/Slack - coming soon)
  • Team setup with name and description
  • Role creation with educational breakdown visualization
  • KPI/metrics step with data source dropdown and goal type toggle (absolute/relative)
  • Finish step with CTA to role canvas
  • Numeric input validation for goal fields
  • Progress indicator and smooth animations between steps

Summary by CodeRabbit

  • New Features
    • Complete 6-step onboarding wizard for setting up your organization, team members, roles, and KPIs.
    • Visual progress indicator throughout the onboarding flow.
    • Team member import integration with Google Workspace and Slack options.
    • Interactive KPI configuration with multiple goal types and data sources.
    • Animated visual guides accompanying each onboarding step.

✏️ Tip: You can customize this high-level summary in your review settings.

- Add 6-step onboarding flow with split-screen layout
- Implement organization name, member import, team setup, role creation, KPI/metrics, and finish steps
- Add data source dropdown and goal type toggle (absolute/relative) for metrics
- Add numeric input validation for goal fields
- Note: This is UI-only implementation, no data persistence yet
@vercel
Copy link

vercel bot commented Dec 8, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
org-os Error Error Dec 8, 2025 3:26pm

- Add quick-select buttons for common team names (growth, product, operations)
- Improve UX by allowing users to quickly select example team names
- Matches the pattern used in metrics step
@coderabbitai
Copy link

coderabbitai bot commented Dec 8, 2025

Walkthrough

Introduces a complete 6-step onboarding wizard with synchronized form and visual components. Each step collects configuration data (organization name, team members import, team setup, role creation, KPI configuration) with navigation controls. Uses Framer Motion for animations and state management to track progress through the flow.

Changes

Cohort / File(s) Summary
Step components
src/app/onboarding/_components/org-name-step.tsx, import-members-step.tsx, team-setup-step.tsx, role-creation-step.tsx, kpi-step.tsx, finish-step.tsx
Six step components implementing individual onboarding screens with form inputs (name, team members selection, team/role details, KPI config), state management, and onNext/onBack navigation callbacks; FinishStep renders summary with success state
Supporting components
src/app/onboarding/_components/progress-indicator.tsx, step-visuals.tsx
ProgressIndicator displays step progress as animated dots; step-visuals.tsx exports six visual components (OrgNameVisual, ImportMembersVisual, TeamSetupVisual, RoleCreationVisual, KpiVisual, FinishVisual) with Framer Motion animations and SVG/chart rendering for each step
Layout and page
src/app/onboarding/layout.tsx, page.tsx
Layout defines metadata and wraps onboarding routes with background styling; page.tsx implements 6-step wizard with currentStep state management, synchronized form and visual panes using AnimatePresence, and navigation bounds enforcement

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • page.tsx: Review step navigation logic, currentStep state management, and AnimatePresence coordination across dual panes (forms and visuals)
  • kpi-step.tsx: Verify conditional rendering for absolute vs. relative goal types and numeric input validation patterns
  • step-visuals.tsx: Examine SVG construction logic (ImportMembersVisual orbiting nodes and connection lines; KpiVisual inline gradient chart and line chart paths)
  • Framer Motion consistency: Validate animation patterns (containerVariants, staggered transitions) are applied consistently across all step components

Poem

🐰 Six steps through meadows green so bright,
Where forms and visions dance in light,
From org to teams, from roles to KPIs true,
A journey's path, all laid out new!
With progress dots to guide the way,
You'll onboard quick and seize the day! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: introducing a 6-step onboarding flow UI with metrics/KPI tracking capability, which aligns with the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/onboarding-ui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (12)
src/app/onboarding/_components/kpi-step.tsx (2)

23-45: Use explicit type imports for events and clarify numeric validation behavior

handleAbsoluteGoalChange / handleRelativeGoalChange use React.ChangeEvent without importing the type, relying on the global React namespace and mixing manual regex with a type="number" input. To align with typical consistent-type-imports setups and keep intent clear, consider importing the event type and tightening the validation story:

import { useState, type ChangeEvent } from "react";

const handleAbsoluteGoalChange = (e: ChangeEvent<HTMLInputElement>) => {
  const value = e.target.value;
  // currently allows "", "123", "123.45", and also just "."
  if (value === "" || /^\d*\.?\d*$/.test(value)) {
    setAbsoluteGoal(value);
  }
};

Also double‑check that allowing a lone "." is intentional and that future parsing to a number accounts for this case to avoid NaN.


259-283: Consider gating “continue” on KPI completeness

Right now “continue” always calls onNext regardless of whether a metric name, data source, or goal has been entered, while “skip for now” is also available. To avoid accidental empty KPIs, consider disabling “continue” until a minimal set of fields (e.g., metric name and either absolute or relative goal) is present, and reserve “skip for now” for intentionally bypassing this step.

src/app/onboarding/_components/import-members-step.tsx (1)

84-121: Align Slack “COMING SOON” state with selection and continue behavior

Slack is labeled “COMING SOON” but is still fully selectable and enables the “continue” CTA, making it indistinguishable in behavior from Google Workspace. This can confuse users into thinking Slack import is available.

Consider either:

  • Disabling the Slack button (and not letting it satisfy selectedIntegration) while it’s “coming soon”, or
  • Handling Slack as a separate code path (e.g., toast / modal explaining it’s not yet available) and keeping continue gated only on supported integrations.

Also applies to: 139-146

src/app/onboarding/layout.tsx (1)

1-13: Prefer importing ReactNode as a type instead of using React.ReactNode

To keep type usage explicit and align with typical @typescript-eslint/consistent-type-imports setups, consider importing ReactNode rather than relying on the global React namespace:

import { type Metadata } from "next";
import type { ReactNode } from "react";

export default function OnboardingLayout({
  children,
}: {
  children: ReactNode;
}) {
  return <div className="bg-background min-h-screen">{children}</div>;
}

This keeps all external types coming from explicit imports and avoids depending on ambient React globals.

src/app/onboarding/_components/finish-step.tsx (1)

12-15: Avoid hard‑coding mockTeamId in the final CTA

mockTeamId is currently hard‑coded to "demo-team" and used in the final CTA link. That’s fine for a UI‑only prototype, but easy to forget once you wire up real data.

Before shipping beyond a demo context, consider:

  • Passing a real teamId (and possibly team name) via props or context, and
  • Falling back gracefully (e.g., disabling the CTA or routing to a safe default) if no team has been created yet.

This will prevent the “open role canvas” button from silently routing to an invalid or demo route in production.

Also applies to: 100-115

src/app/onboarding/_components/progress-indicator.tsx (1)

10-51: Optional: add ARIA semantics to improve progress accessibility

The animated dot indicator works visually, but it’s currently just a bare <div> for assistive tech. Consider wrapping it with appropriate ARIA semantics (e.g., role="group" / aria-label on the container, or a role="progressbar" with aria-valuenow/aria-valuemax) so screen readers can convey onboarding progress as well.

src/app/onboarding/page.tsx (1)

32-93: Well-structured layout with synchronized step transitions.

The split-screen layout and AnimatePresence integration work well together. The step synchronization between left and right panels is clean.

However, consider the following enhancements:

  1. Data persistence: While the PR scope is UI-only, user progress is lost on page refresh. Consider adding localStorage to persist step data and current step for better UX.

  2. Accessibility: The onboarding flow lacks keyboard navigation hints, ARIA labels, and focus management:

    • Add aria-label to the progress indicator
    • Add role="progressbar" with aria-valuenow, aria-valuemin, aria-valuemax attributes
    • Manage focus when transitioning between steps
    • Consider adding keyboard shortcuts (e.g., Ctrl+→ for next, Ctrl+← for back)
  3. Error boundaries: Wrap step components in an error boundary to gracefully handle rendering failures.

src/app/onboarding/_components/step-visuals.tsx (5)

12-73: Consider using theme colors instead of hardcoded RGB values.

Lines 28-29 use hardcoded rgb(60, 60, 55) for the grid background. This breaks theme consistency and won't adapt to theme changes.

Consider using Tailwind theme colors or CSS custom properties:

-            linear-gradient(rgb(60, 60, 55) 1px, transparent 1px),
-            linear-gradient(90deg, rgb(60, 60, 55) 1px, transparent 1px)
+            linear-gradient(rgb(var(--border)) 1px, transparent 1px),
+            linear-gradient(90deg, rgb(var(--border)) 1px, transparent 1px)

Or use a Tailwind utility class approach if the pattern is reused.


75-170: LGTM! Orbiting nodes visualization is mathematically sound.

The circular positioning using trigonometry is correctly implemented with 6 nodes at 60-degree intervals. The SVG connection lines animate nicely.

One optional note: The SVG positioning (lines 125-128) uses magic numbers that could be extracted to constants if this pattern is reused elsewhere, but it's fine for a one-off visual.


346-466: Refactor hardcoded theme colors for consistency.

Lines 369, 420, 425, and 440 use hardcoded rgb(142, 157, 172) which breaks theme consistency and won't adapt to theme changes.

Extract the color to a CSS custom property or Tailwind theme color:

-            style={{ backgroundColor: "rgb(142, 157, 172)" }}
+            className="bg-chart-line"

And define in your Tailwind config or use an existing theme color.

Additionally, the SVG path generation (lines 431, 438) is complex and hard to maintain. Consider extracting it to a helper function:

const createChartPath = (dataPoints: number[], width: number, height: number) => {
  const xStep = width / (dataPoints.length - 1);
  const points = dataPoints.map((p, i) => `L${i * xStep},${height - p * 0.5}`).join(" ");
  return `M0,${height - dataPoints[0] * 0.5} ${points}`;
};

468-623: LGTM! Celebration visual effectively conveys completion.

The network diagram with animated connections and spring-animated checkmark provides a satisfying conclusion to the onboarding flow.

The positioning coordinates are hardcoded but acceptable for a static decorative visual. If this pattern is reused, consider extracting node positions to a configuration object.


12-623: Add accessibility attributes for decorative visuals.

All six visual components are purely decorative and should be hidden from assistive technologies to avoid confusing screen reader users.

Add aria-hidden="true" to the root motion.div of each visual component:

  <motion.div
+   aria-hidden="true"
    variants={containerVariants}
    initial="initial"
    animate="animate"

Apply this to all six visuals: OrgNameVisual, ImportMembersVisual, TeamSetupVisual, RoleCreationVisual, KpiVisual, and FinishVisual.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c04ae0 and 86a5432.

📒 Files selected for processing (10)
  • src/app/onboarding/_components/finish-step.tsx (1 hunks)
  • src/app/onboarding/_components/import-members-step.tsx (1 hunks)
  • src/app/onboarding/_components/kpi-step.tsx (1 hunks)
  • src/app/onboarding/_components/org-name-step.tsx (1 hunks)
  • src/app/onboarding/_components/progress-indicator.tsx (1 hunks)
  • src/app/onboarding/_components/role-creation-step.tsx (1 hunks)
  • src/app/onboarding/_components/step-visuals.tsx (1 hunks)
  • src/app/onboarding/_components/team-setup-step.tsx (1 hunks)
  • src/app/onboarding/layout.tsx (1 hunks)
  • src/app/onboarding/page.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: In TypeScript files, use @typescript-eslint/consistent-type-imports to enforce inline type imports and sort imports with @trivago/prettier-plugin-sort-imports
Use the tRPC server caller API from src/trpc/server.ts directly in Server Components for 10x faster performance instead of client-side hooks

Files:

  • src/app/onboarding/_components/import-members-step.tsx
  • src/app/onboarding/_components/progress-indicator.tsx
  • src/app/onboarding/_components/role-creation-step.tsx
  • src/app/onboarding/_components/finish-step.tsx
  • src/app/onboarding/_components/org-name-step.tsx
  • src/app/onboarding/layout.tsx
  • src/app/onboarding/page.tsx
  • src/app/onboarding/_components/step-visuals.tsx
  • src/app/onboarding/_components/team-setup-step.tsx
  • src/app/onboarding/_components/kpi-step.tsx
src/app/**/*.{tsx,ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Use React Server Components and server-side data fetching patterns instead of client-side fetching for better performance and security

Files:

  • src/app/onboarding/_components/import-members-step.tsx
  • src/app/onboarding/_components/progress-indicator.tsx
  • src/app/onboarding/_components/role-creation-step.tsx
  • src/app/onboarding/_components/finish-step.tsx
  • src/app/onboarding/_components/org-name-step.tsx
  • src/app/onboarding/layout.tsx
  • src/app/onboarding/page.tsx
  • src/app/onboarding/_components/step-visuals.tsx
  • src/app/onboarding/_components/team-setup-step.tsx
  • src/app/onboarding/_components/kpi-step.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TanStack Query (via tRPC hooks) for server state management, client-side data fetching, and automatic cache invalidation

Files:

  • src/app/onboarding/_components/import-members-step.tsx
  • src/app/onboarding/_components/progress-indicator.tsx
  • src/app/onboarding/_components/role-creation-step.tsx
  • src/app/onboarding/_components/finish-step.tsx
  • src/app/onboarding/_components/org-name-step.tsx
  • src/app/onboarding/layout.tsx
  • src/app/onboarding/page.tsx
  • src/app/onboarding/_components/step-visuals.tsx
  • src/app/onboarding/_components/team-setup-step.tsx
  • src/app/onboarding/_components/kpi-step.tsx
src/app/**/page.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Use the shared canvas library from src/lib/canvas/ when building new React Flow canvas features (BaseNode, SaveStatus, EdgeActionButtons, create-canvas-store)

Files:

  • src/app/onboarding/page.tsx
🧠 Learnings (2)
📚 Learning: 2025-12-02T13:36:55.215Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-02T13:36:55.215Z
Learning: Applies to src/components/ui/**/*.tsx : Use shadcn/ui CLI from `components.json` configuration to add new UI components instead of manual copying

Applied to files:

  • src/app/onboarding/_components/import-members-step.tsx
  • src/app/onboarding/_components/step-visuals.tsx
📚 Learning: 2025-12-02T13:36:55.215Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-02T13:36:55.215Z
Learning: Applies to src/app/**/components/**/*.tsx : Define custom React Flow nodes in a `_components/` folder within the feature directory and style them with the `BaseNode` component from the shared library

Applied to files:

  • src/app/onboarding/_components/finish-step.tsx
  • src/app/onboarding/_components/step-visuals.tsx
🧬 Code graph analysis (2)
src/app/onboarding/page.tsx (8)
src/app/onboarding/_components/progress-indicator.tsx (1)
  • ProgressIndicator (10-53)
src/app/onboarding/_components/org-name-step.tsx (1)
  • OrgNameStep (11-99)
src/app/onboarding/_components/import-members-step.tsx (1)
  • ImportMembersStep (12-151)
src/app/onboarding/_components/team-setup-step.tsx (1)
  • TeamSetupStep (12-121)
src/app/onboarding/_components/role-creation-step.tsx (1)
  • RoleCreationStep (12-136)
src/app/onboarding/_components/kpi-step.tsx (1)
  • KpiStep (23-286)
src/app/onboarding/_components/finish-step.tsx (1)
  • FinishStep (12-127)
src/app/onboarding/_components/step-visuals.tsx (6)
  • OrgNameVisual (13-73)
  • ImportMembersVisual (76-170)
  • TeamSetupVisual (173-230)
  • RoleCreationVisual (233-344)
  • KpiVisual (347-466)
  • FinishVisual (469-623)
src/app/onboarding/_components/kpi-step.tsx (2)
src/components/ui/select.tsx (5)
  • Select (178-178)
  • SelectTrigger (186-186)
  • SelectValue (187-187)
  • SelectContent (179-179)
  • SelectItem (181-181)
src/components/ui/toggle-group.tsx (2)
  • ToggleGroup (84-84)
  • ToggleGroupItem (84-84)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test
🔇 Additional comments (8)
src/app/onboarding/_components/org-name-step.tsx (1)

11-96: Solid minimal validation and keyboard UX for org name

The canContinue check using orgName.trim().length > 0 plus disabling the button and handling Enter keypress provides a clear, minimal guard against empty org names with good keyboard UX. This step looks good as a self‑contained client component.

src/app/onboarding/_components/role-creation-step.tsx (1)

12-132: Role creation step state and validation look consistent

Requiring both title and purpose via canContinue before enabling the continue button fits the guidance text and keeps the flow from advancing on empty roles. The structure and local state management here look solid.

src/app/onboarding/_components/team-setup-step.tsx (1)

12-117: Team setup step is coherent and consistent with the rest of the flow

Using canContinue based on a trimmed teamName, plus example chips and Enter‑to‑continue behavior, keeps this step consistent with OrgNameStep and provides a smooth UX. The component looks good as implemented.

src/app/onboarding/page.tsx (2)

1-23: LGTM! Clean setup and imports.

The component is correctly marked as a client component for state management and animations. Imports are well-organized and the TOTAL_STEPS constant follows good practices.


25-30: LGTM! Navigation logic is sound.

The state management and boundary checks are correctly implemented. Using the functional form of setState is good practice.

src/app/onboarding/_components/step-visuals.tsx (3)

1-10: LGTM! Good use of shared animation variants.

The containerVariants provide a consistent fade transition across all visual components, following DRY principles.


172-230: LGTM! Clean and straightforward team visualization.

The staggered animation and highlighting of the first team card effectively demonstrates the team organization concept.


232-344: LGTM! Effective educational breakdown.

The staggered reveal of role components (title, purpose, accountabilities) with examples provides clear guidance to users. Proper quote escaping and clean structure.

@drifter089 drifter089 marked this pull request as draft December 10, 2025 16:30
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.

2 participants