-
Notifications
You must be signed in to change notification settings - Fork 455
feat: interactive board onboarding wizard #422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Added a new onboarding wizard to guide users through the board features. - Integrated sample feature generation for quick start onboarding. - Enhanced BoardView component to manage onboarding state and actions. - Updated BoardControls and BoardHeader to include tour functionality. - Introduced utility functions for sample feature management in constants. - Improved user experience with toast notifications for onboarding actions.
- Introduced a new onboarding wizard for guiding users through the board features. - Added shared onboarding components including OnboardingWizard, useOnboardingWizard, and related types and constants. - Implemented onboarding logic in the BoardView, integrating sample feature generation for a quick start. - Updated UI components to support onboarding interactions and improve user experience. - Enhanced onboarding state management with localStorage persistence for user progress tracking.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the 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. Comment |
Summary of ChangesHello @Shironex, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a comprehensive interactive onboarding wizard for the board view, designed to help new users quickly understand and utilize the Kanban workflow. It establishes a robust, reusable foundation for future onboarding experiences across the application, complete with dynamic UI highlighting, keyboard navigation, and a 'Quick Start' option to populate the board with illustrative sample tasks. The wizard is intentionally triggered manually to avoid conflicts with existing user flows. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
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 introduces a well-structured and reusable onboarding wizard, which is a great addition for improving user experience. The implementation is solid, with good separation between the generic wizard infrastructure and the board-specific integration. My review includes a few suggestions to improve efficiency and robustness, such as parallelizing API calls for a quicker 'Quick Start' experience, making the step navigation more direct, and strengthening the logic for identifying sample data.
| const handleStepClick = useCallback( | ||
| (stepIndex: number) => { | ||
| if (stepIndex === currentStep) return; | ||
|
|
||
| if (stepIndex > currentStep) { | ||
| for (let i = currentStep; i < stepIndex; i++) { | ||
| onNext(); | ||
| } | ||
| } else { | ||
| for (let i = currentStep; i > stepIndex; i--) { | ||
| onPrevious(); | ||
| } | ||
| } | ||
| }, | ||
| [currentStep, onNext, onPrevious] | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The handleStepClick function simulates jumping to a step by repeatedly calling onNext or onPrevious in a loop. This is inefficient and makes assumptions about the implementation of these handlers (e.g., that they are synchronous and have no side effects per call).
The useOnboardingWizard hook already provides a more direct and efficient goToStep function. This should be passed down to the OnboardingWizard component and used here.
To fix this, you should:
- Add
onGoToStep: (step: number) => void;to theOnboardingWizardPropsinterface inapps/ui/src/components/shared/onboarding/types.ts. - Pass
onGoToStepto this component's props. - Update this
handleStepClickfunction to callonGoToStepdirectly:
const handleStepClick = useCallback(
(stepIndex: number) => {
if (stepIndex === currentStep) return;
onGoToStep(stepIndex);
},
[currentStep, onGoToStep]
);- Pass the
goToStepfunction from theuseBoardOnboardinghook throughBoardOnboardingWizardto this component.
| // Create each sample feature | ||
| for (const featureData of sampleFeatures) { | ||
| const result = await api.features.create(currentProject.path, featureData); | ||
| if (result.success && result.feature) { | ||
| useAppStore.getState().addFeature(result.feature); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating sample features sequentially with await inside a for loop can be slow, as each API call waits for the previous one to complete. To improve performance and provide a faster user experience, these API calls should be made in parallel using Promise.all.
| // Create each sample feature | |
| for (const featureData of sampleFeatures) { | |
| const result = await api.features.create(currentProject.path, featureData); | |
| if (result.success && result.feature) { | |
| useAppStore.getState().addFeature(result.feature); | |
| } | |
| } | |
| // Create each sample feature in parallel | |
| const createPromises = sampleFeatures.map((featureData) => | |
| api.features.create(currentProject.path, featureData) | |
| ); | |
| const results = await Promise.all(createPromises); | |
| // Add successfully created features to the store | |
| for (const result of results) { | |
| if (result.success && result.feature) { | |
| useAppStore.getState().addFeature(result.feature); | |
| } | |
| } |
| export function isSampleFeature(feature: Partial<Feature>): boolean { | ||
| // Check title prefix - this is the reliable marker that persists through the database | ||
| return feature.title?.startsWith(SAMPLE_FEATURE_PREFIX) ?? false; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a title prefix [DEMO] to identify sample features is fragile. A user could inadvertently create a feature with this prefix, causing it to be treated as sample data. A more robust approach is to use a dedicated property on the feature object.
The SampleFeatureTemplate interface already includes an isSampleData: true marker. This should be passed through to the feature object in generateSampleFeatures and used for identification.
- Update
generateSampleFeaturesto include theisSampleDataproperty:
// in generateSampleFeatures()
return SAMPLE_FEATURES.map((template) => ({
// ... other properties
isSampleData: template.isSampleData,
// ... other properties
}));- Update this function to check for that property instead of the title prefix.
| export function isSampleFeature(feature: Partial<Feature>): boolean { | |
| // Check title prefix - this is the reliable marker that persists through the database | |
| return feature.title?.startsWith(SAMPLE_FEATURE_PREFIX) ?? false; | |
| } | |
| export function isSampleFeature(feature: Partial<Feature & { isSampleData?: boolean }>): boolean { | |
| // Check for a dedicated property instead of a title prefix for robustness. | |
| return feature.isSampleData === true; | |
| } |
Summary
Changes
New Shared Onboarding Infrastructure
Created
apps/ui/src/components/shared/onboarding/with:data-onboarding-targetBoard View Integration
data-onboarding-targetfor spotlight targetingFeatures
Test plan
🤖 Generated with Claude Code