feat: implement dashboard story with analytics and job sections#258
feat: implement dashboard story with analytics and job sections#258
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughThis PR adds a comprehensive dashboard UI system with multiple new components for navigation, analytics/jobs content areas, user profile management, and mobile support. It also refines avatar styling and select component icons. Changes
Sequence DiagramsequenceDiagram
participant User
participant Dashboard as Dashboard Component
participant ScrollTracker as Scroll Tracker
participant AnimatedLogo
participant Topbar
participant TopMenu
participant ContentArea as Content (Analytics/<br/>Jobs)
User->>Dashboard: Render Dashboard
Dashboard->>ScrollTracker: Initialize useScroll hook
ScrollTracker-->>Dashboard: Initial scroll position
Dashboard->>Topbar: Render (hidelogo=false)
Dashboard->>ContentArea: Render active tab content
User->>User: Scroll down
ScrollTracker->>ScrollTracker: Compute scroll progress
ScrollTracker->>Dashboard: Trigger useMotionValueEvent
Dashboard->>AnimatedLogo: Update scrollProgress
AnimatedLogo->>AnimatedLogo: Compute eased progress & animate
AnimatedLogo-->>User: Fade in with translateY
Dashboard->>Topbar: Update hidelogo=true
Topbar->>Topbar: Reduce logo opacity
Dashboard->>TopMenu: Update padding (cubic easing)
TopMenu->>TopMenu: Apply dynamic spacing
User->>TopMenu: Click "Jobs" tab
TopMenu->>Dashboard: Trigger onTabChange callback
Dashboard->>Dashboard: Reset scroll position
Dashboard->>ScrollTracker: Reset scroll progress
Dashboard->>ContentArea: Switch to JobsContent
ContentArea-->>User: Render jobs table
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Areas requiring extra attention:
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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 |
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
There was a problem hiding this comment.
Pull request overview
This PR implements a comprehensive dashboard story for Storybook with analytics and jobs sections. The implementation includes animated scroll effects, organization/time selectors, and responsive layouts.
- Adds a new Dashboard component with tab navigation between Analytics and Jobs views
- Updates the Select component icon from "arrowDownSLine" to "expandUpDownLine"
- Adjusts Avatar rounded radius from rounded-6 to rounded-4
- Adds visual regression testing to Form story with Argos screenshot integration
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
libs/react/ui/src/components/select/select.tsx |
Updates dropdown icon to use expand/collapse iconography |
libs/react/ui/src/components/select/select.stories.tsx |
Adds TimeSelector and OrganizationSelector story examples |
libs/react/ui/src/components/form/form.stories.tsx |
Integrates Argos screenshot testing for visual regression |
libs/react/ui/src/components/dashboard/index.ts |
Exports Dashboard component |
libs/react/ui/src/components/dashboard/dashboard.tsx |
Main dashboard with scroll animations and tab switching |
libs/react/ui/src/components/dashboard/dashboard.stories.tsx |
Storybook story for Dashboard with fullscreen layout |
libs/react/ui/src/components/dashboard/components/user-profile.tsx |
User profile dropdown with usage gauge and upgrade CTA |
libs/react/ui/src/components/dashboard/components/topbar.tsx |
Top navigation bar with organization selector and utilities |
libs/react/ui/src/components/dashboard/components/topbar-button.tsx |
Reusable button component for topbar icons |
libs/react/ui/src/components/dashboard/components/top-menu.tsx |
Tab navigation between Analytics and Jobs sections |
libs/react/ui/src/components/dashboard/components/organization-selector.tsx |
Dropdown for switching between organizations |
libs/react/ui/src/components/dashboard/components/mobile-menu.tsx |
Mobile-responsive dropdown menu |
libs/react/ui/src/components/dashboard/components/jobs-content.tsx |
Jobs table view with search and filtering |
libs/react/ui/src/components/dashboard/components/complete-setup-button.tsx |
Animated setup completion button with loader |
libs/react/ui/src/components/dashboard/components/animated-logo.tsx |
Logo with scroll-based reveal animation |
libs/react/ui/src/components/dashboard/components/analytics-content.tsx |
Analytics dashboard with charts and empty states |
libs/react/ui/src/components/avatar/avatar.tsx |
Reduces border radius for rounded variant |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
libs/react/ui/src/components/dashboard/components/topbar-button.tsx
Outdated
Show resolved
Hide resolved
libs/react/ui/src/components/dashboard/components/mobile-menu.tsx
Outdated
Show resolved
Hide resolved
libs/react/ui/src/components/dashboard/components/organization-selector.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (13)
libs/react/ui/src/components/dashboard/components/jobs-content.tsx (2)
1-8: Imports from story files suggest prototype/demo code.The component imports
jobColumnsandjobsDatafromtable.stories.columnsandtable.stories.data, which are typically for Storybook demonstrations rather than production code. Consider moving these to a dedicated data layer or prop-drilling them if this component is intended for production use.
34-36: Button lacks an onClick handler.The button with the "Insert column left" icon has no
onClickhandler. If this is a placeholder for future functionality, consider adding a TODO comment or a no-op handler to make the intent explicit.libs/react/ui/src/components/dashboard/components/complete-setup-button.tsx (1)
7-29: Consider adding interaction handling.The button renders with proper styling and theme-aware loader but lacks an
onClickhandler orasChildpattern for composability. If this is intentional (e.g., the button is meant to be wrapped or will receive handlers later), consider documenting this or accepting an optionalonClickprop.💡 Suggested enhancement
-export function CompleteSetupButton({className}: {className?: string}) { +export function CompleteSetupButton({ + className, + onClick, +}: { + className?: string; + onClick?: () => void; +}) { const resolvedTheme = useResolvedTheme(); return ( <Button type="button" variant="transparent" + onClick={onClick} className={cn(libs/react/ui/src/components/dashboard/components/user-profile.tsx (2)
23-28: Static user data suggests demo/prototype implementation.The component uses hardcoded user data (name, email, credits). For production use, consider accepting these as props or fetching from a user context/hook.
💡 Suggested enhancement
-export function UserProfile() { - const userName = 'Thierry Abalea'; - const userEmail = 'thierryabalea@acme.com'; - const creditsUsed = 3213; - const creditsTotal = 6000; +export function UserProfile({ + userName, + userEmail, + creditsUsed, + creditsTotal, +}: { + userName: string; + userEmail: string; + creditsUsed: number; + creditsTotal: number; +}) {
52-53: Menu items lack interaction handlers.The "Getting started", "Profile settings", and "Log out" menu items don't have
onClickoronSelecthandlers. If this is placeholder functionality, consider adding TODO comments or accepting handlers as props.Also applies to: 86-86
libs/react/ui/src/components/dashboard/components/animated-logo.tsx (1)
6-25: Consider using framer-motion's animate prop for consistency.The component uses
motion.divbut applies animation styles manually via thestyleprop with template literals. While this works, using framer-motion'sanimateprop with motion values would be more idiomatic and potentially more performant, especially ifscrollProgressis a motion value fromuseScroll.💡 Alternative approach using animate prop
If
scrollProgressis already a motion value, you could use:const easedProgress = useTransform(scrollProgress, [0, 1], [0, 1], { ease: (v) => 1 - (1 - v) ** 3 }); return ( <motion.div className="..." style={{ opacity: easedProgress, y: useTransform(easedProgress, (v) => -LOGO_HEIGHT + v * LOGO_HEIGHT), }} /> );libs/react/ui/src/components/dashboard/components/organization-selector.tsx (1)
15-15: Consider making defaultValue configurable.The
defaultValueis hardcoded to "stripe". If this component will be reused, consider accepting it as a prop along with an optionalonChangehandler.libs/react/ui/src/components/dashboard/dashboard.stories.tsx (1)
4-13: Consider addingcomponentto meta for autodocs.The
autodocstag is included, but withoutcomponent: Dashboard, Storybook won't generate automatic documentation with prop tables. If you intend to document props, add the component reference.🔎 Proposed fix
+import type {Meta, StoryObj} from '@storybook/react'; +import {Dashboard} from './dashboard'; const meta = { title: 'Dashboard/Example', + component: Dashboard, tags: ['autodocs'], parameters: { layout: 'fullscreen', viewport: { defaultViewport: 'extraLarge', }, }, -} satisfies Meta; +} satisfies Meta<typeof Dashboard>;libs/react/ui/src/components/dashboard/components/top-menu.tsx (1)
3-9: Consider using a stricter type foractiveTab.Using
stringfor bothactiveTaband theonTabChangecallback parameter is flexible but loses type safety. A union type would catch typos at compile time.🔎 Proposed improvement
+type TabValue = 'analytics' | 'jobs'; + export function TopMenu({ activeTab, onTabChange, }: { - activeTab: string; - onTabChange: (tab: string) => void; + activeTab: TabValue; + onTabChange: (tab: TabValue) => void; }) {libs/react/ui/src/components/dashboard/dashboard.tsx (2)
14-14: Unused ref:topbarRefis assigned but never read.The
topbarRefis created and attached to a div but its value is never used. If it's intended for future functionality, consider adding a comment; otherwise, remove it to reduce clutter.🔎 If unused, remove the ref
export function Dashboard() { const containerRef = useRef<HTMLDivElement>(null); - const topbarRef = useRef<HTMLDivElement>(null); const [scrollProgress, setScrollProgress] = useState(0); const [activeTab, setActiveTab] = useState('analytics');And remove the ref assignment:
<div ref={containerRef} className="flex flex-col w-full h-full overflow-auto"> - <div ref={topbarRef}> + <div> <Topbar hidelogo={isTopbarHidden} /> </div>
9-10: Consider documenting magic numbers or co-locating with AnimatedLogo.
LOGO_HEIGHTis also used inanimated-logo.tsx. Consider extracting these constants to a shared location or adding brief comments explaining their relationship to the UI layout.libs/react/ui/src/components/dashboard/components/mobile-menu.tsx (1)
32-45: Consider extracting the shared "Complete setup" content into a reusable component.This ShipfoxLoader + ShinyText pattern is duplicated from
CompleteSetupButton(seecomplete-setup-button.tsxlines 17-24). If both need to stay in sync, consider extracting the inner content into a shared component to reduce duplication and ensure consistent styling.🔎 Example extraction
Create a shared component:
// complete-setup-content.tsx export function CompleteSetupContent({ className }: { className?: string }) { const resolvedTheme = useResolvedTheme(); return ( <div className={cn("flex items-center gap-8", className)}> <ShipfoxLoader size={13} animation="circular" color={resolvedTheme === 'dark' ? 'white' : 'orange'} background={resolvedTheme === 'dark' ? 'dark' : 'light'} /> <ShinyText text="Complete setup" className="flex-1 text-sm font-medium leading-20 text-foreground-neutral-base truncate text-left" /> </div> ); }Then use it in both
CompleteSetupButtonandMobileMenu.libs/react/ui/src/components/dashboard/components/topbar.tsx (1)
8-8: Prop name should use camelCase:hideLogoinstead ofhidelogo.React convention uses camelCase for prop names. This also improves consistency with standard React patterns and readability.
🔎 Proposed fix
-export function Topbar({hidelogo = false}: {hidelogo?: boolean}) { +export function Topbar({hideLogo = false}: {hideLogo?: boolean}) {And update line 13:
- <div className={cn('shrink-0', hidelogo ? 'opacity-0' : 'opacity-100')}> + <div className={cn('shrink-0', hideLogo ? 'opacity-0' : 'opacity-100')}>
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
libs/react/ui/src/components/avatar/avatar.tsxlibs/react/ui/src/components/dashboard/components/analytics-content.tsxlibs/react/ui/src/components/dashboard/components/animated-logo.tsxlibs/react/ui/src/components/dashboard/components/complete-setup-button.tsxlibs/react/ui/src/components/dashboard/components/jobs-content.tsxlibs/react/ui/src/components/dashboard/components/mobile-menu.tsxlibs/react/ui/src/components/dashboard/components/organization-selector.tsxlibs/react/ui/src/components/dashboard/components/top-menu.tsxlibs/react/ui/src/components/dashboard/components/topbar-button.tsxlibs/react/ui/src/components/dashboard/components/topbar.tsxlibs/react/ui/src/components/dashboard/components/user-profile.tsxlibs/react/ui/src/components/dashboard/dashboard.stories.tsxlibs/react/ui/src/components/dashboard/dashboard.tsxlibs/react/ui/src/components/dashboard/index.tslibs/react/ui/src/components/form/form.stories.tsxlibs/react/ui/src/components/select/select.stories.tsxlibs/react/ui/src/components/select/select.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*
⚙️ CodeRabbit configuration file
We handle errors at the edge of our applications in most cases. Do not recommend to add error handling around every single function. We prefer them to bubble up and be handled at upper layers.
Files:
libs/react/ui/src/components/dashboard/components/user-profile.tsxlibs/react/ui/src/components/dashboard/components/complete-setup-button.tsxlibs/react/ui/src/components/dashboard/components/top-menu.tsxlibs/react/ui/src/components/select/select.stories.tsxlibs/react/ui/src/components/dashboard/components/organization-selector.tsxlibs/react/ui/src/components/dashboard/dashboard.tsxlibs/react/ui/src/components/dashboard/components/animated-logo.tsxlibs/react/ui/src/components/dashboard/components/topbar-button.tsxlibs/react/ui/src/components/dashboard/components/mobile-menu.tsxlibs/react/ui/src/components/avatar/avatar.tsxlibs/react/ui/src/components/dashboard/index.tslibs/react/ui/src/components/dashboard/components/topbar.tsxlibs/react/ui/src/components/dashboard/components/analytics-content.tsxlibs/react/ui/src/components/form/form.stories.tsxlibs/react/ui/src/components/dashboard/components/jobs-content.tsxlibs/react/ui/src/components/dashboard/dashboard.stories.tsxlibs/react/ui/src/components/select/select.tsx
🧬 Code graph analysis (10)
libs/react/ui/src/components/dashboard/components/user-profile.tsx (5)
libs/react/ui/src/components/dropdown-menu/dropdown-menu.tsx (5)
DropdownMenu(388-388)DropdownMenuTrigger(389-389)DropdownMenuContent(391-391)DropdownMenuSeparator(398-398)DropdownMenuItem(394-394)libs/react/ui/src/components/avatar/avatar.tsx (1)
Avatar(117-217)libs/react/ui/src/components/badge/user-badge.tsx (1)
UserBadge(11-34)libs/react/ui/src/components/button/button.tsx (1)
Button(50-91)libs/react/ui/src/components/shiny-text/shiny-text.tsx (1)
ShinyText(20-20)
libs/react/ui/src/components/dashboard/components/top-menu.tsx (1)
libs/react/ui/src/components/tabs/tabs.tsx (3)
Tabs(368-368)TabsList(369-369)TabsTrigger(370-370)
libs/react/ui/src/components/dashboard/components/organization-selector.tsx (5)
libs/react/ui/src/components/select/select.stories.tsx (1)
OrganizationSelector(212-250)libs/react/ui/src/components/select/select.tsx (6)
Select(207-207)SelectTrigger(210-210)SelectValue(209-209)SelectContent(211-211)SelectItem(213-213)SelectSeparator(214-214)libs/react/ui/src/components/avatar/avatar.tsx (1)
Avatar(117-217)libs/react/ui/src/components/button/button.tsx (1)
Button(50-91)libs/react/ui/src/components/icon/icon.tsx (1)
Icon(86-90)
libs/react/ui/src/components/dashboard/dashboard.tsx (5)
libs/react/ui/src/components/dashboard/components/animated-logo.tsx (1)
AnimatedLogo(6-25)libs/react/ui/src/components/dashboard/components/topbar.tsx (1)
Topbar(8-40)libs/react/ui/src/components/dashboard/components/top-menu.tsx (1)
TopMenu(3-26)libs/react/ui/src/components/dashboard/components/analytics-content.tsx (1)
AnalyticsContent(5-102)libs/react/ui/src/components/dashboard/components/jobs-content.tsx (1)
JobsContent(10-51)
libs/react/ui/src/components/dashboard/components/animated-logo.tsx (1)
libs/react/ui/src/components/icon/icon.tsx (1)
Icon(86-90)
libs/react/ui/src/components/dashboard/components/topbar-button.tsx (2)
libs/react/ui/src/components/icon/icon.tsx (2)
IconName(77-77)Icon(86-90)libs/react/ui/src/components/button/button.tsx (1)
Button(50-91)
libs/react/ui/src/components/dashboard/components/topbar.tsx (6)
libs/react/ui/src/components/dashboard/components/topbar-button.tsx (1)
TopbarButton(5-30)libs/react/ui/src/components/dashboard/components/organization-selector.tsx (1)
OrganizationSelector(13-51)libs/react/ui/src/components/select/select.stories.tsx (1)
OrganizationSelector(212-250)libs/react/ui/src/components/dashboard/components/complete-setup-button.tsx (1)
CompleteSetupButton(7-30)libs/react/ui/src/components/dashboard/components/mobile-menu.tsx (1)
MobileMenu(14-53)libs/react/ui/src/components/dashboard/components/user-profile.tsx (1)
UserProfile(23-90)
libs/react/ui/src/components/dashboard/components/analytics-content.tsx (3)
libs/react/ui/src/components/skeleton/skeleton.tsx (1)
Skeleton(6-14)libs/react/ui/src/components/icon/icon.tsx (1)
Icon(86-90)libs/react/ui/src/components/typography/text.tsx (1)
Text(27-50)
libs/react/ui/src/components/dashboard/dashboard.stories.tsx (2)
libs/react/ui/src/components/select/select.stories.tsx (1)
Default(27-40)libs/react/ui/src/components/dashboard/dashboard.tsx (1)
Dashboard(12-61)
libs/react/ui/src/components/select/select.tsx (1)
libs/react/ui/src/components/icon/icon.tsx (1)
Icon(86-90)
⏰ 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). (3)
- GitHub Check: Upload results
- GitHub Check: Cursor Bugbot
- GitHub Check: Continuous integration
🔇 Additional comments (20)
libs/react/ui/src/components/form/form.stories.tsx (1)
1-1: Verify that the Argos CI package is correctly installed.The import pattern
import { argosScreenshot } from "@argos-ci/storybook/vitest"is correct and matches official Argos documentation for capturing screenshots in Storybook play functions. Ensure the@argos-ci/storybookpackage is listed in dependencies and compatible with the project's Storybook and Vitest versions.libs/react/ui/src/components/select/select.tsx (1)
60-60: LGTM! Icon change improves semantic clarity.The replacement of
arrowDownSLinewithexpandUpDownLinebetter represents the bidirectional nature of a select dropdown, where users can navigate both up and down through options.libs/react/ui/src/components/avatar/avatar.tsx (1)
14-14: LGTM! Styling refinement aligns with design system updates.The border radius reduction from
rounded-6torounded-4is consistent with the broader UI styling refinements in this PR.libs/react/ui/src/components/dashboard/components/user-profile.tsx (1)
13-21: LGTM! Safe percentage calculation with overflow protection.The
UsageGaugecomponent correctly usesMath.minto cap the percentage at 100%, preventing visual overflow issues.libs/react/ui/src/components/dashboard/index.ts (1)
1-1: LGTM! Standard barrel export pattern.The barrel export provides a clean public API for the dashboard module, allowing consumers to import from a single entry point.
libs/react/ui/src/components/dashboard/components/organization-selector.tsx (2)
16-16: Verify the specific breakpointmin-[321px]is intentional.The SelectTrigger uses a very specific responsive breakpoint of
321pxfor the right border. This is unusual compared to standard Tailwind breakpoints (sm: 640px, md: 768px, etc.). Ensure this precise value aligns with design requirements.
41-47: Verify Button behavior inside SelectContent.Placing a
ButtoninsideSelectContentis an unusual pattern. Ensure that:
- The Button's click handler doesn't conflict with Radix Select's item selection logic
- The select dropdown closes appropriately when the button is clicked
- Consider using
asChildon aSelectIteminstead if you need custom stylingYou may want to test this interaction or check Radix UI documentation for recommended patterns for action items in select dropdowns.
libs/react/ui/src/components/dashboard/components/jobs-content.tsx (1)
13-16: The code is type-safe. TheJobDatatype explicitly requiresnameas a non-nullablestring, so the filter operation cannot fail due to null/undefined values. No additional error handling is needed.Likely an incorrect or invalid review comment.
libs/react/ui/src/components/dashboard/dashboard.stories.tsx (1)
19-25: LGTM!The Default story is correctly structured with a full-height container appropriate for the fullscreen layout parameter.
libs/react/ui/src/components/select/select.stories.tsx (3)
2-5: LGTM!New imports are correctly added for the additional components used in the new stories.
168-210: LGTM!The TimeSelector story effectively demonstrates using
Kbdcomponents inside select items to show keyboard shortcuts, which is a useful pattern for documentation.
240-246: Verify Button accessibility within SelectContent.The Button is placed inside
SelectContentbut outside ofSelectItemelements. While this is a common pattern for "add new" actions, ensure it's keyboard-accessible and doesn't interfere with the Select's native keyboard navigation (arrow keys, enter selection).libs/react/ui/src/components/dashboard/components/top-menu.tsx (1)
10-25: LGTM!The Tabs implementation is clean, with proper controlled state management and responsive styling.
libs/react/ui/src/components/dashboard/dashboard.tsx (3)
18-25: LGTM!The scroll tracking implementation with framer-motion is well-structured. The progress is correctly clamped between 0 and 1.
27-33: LGTM!The
handleTabChangecallback is properly memoized withuseCallbackand correctly resets both scroll position and progress state when switching tabs.
37-60: LGTM!The overall component structure is clean with proper separation of concerns. The dynamic padding calculation using cubic easing provides smooth animation, and conditional rendering of tab content is straightforward.
libs/react/ui/src/components/dashboard/components/mobile-menu.tsx (1)
14-53: LGTM!The component is well-structured, follows existing patterns (theme-aware loader, dropdown composition), and correctly handles responsive display via the
md:hiddenclass on the trigger button.libs/react/ui/src/components/dashboard/components/topbar.tsx (1)
9-39: LGTM!The Topbar composition is clean with good responsive handling. The use of
opacity-0for hiding the logo (rather than conditional rendering) correctly preserves layout space, which appears intentional for the dashboard structure.libs/react/ui/src/components/dashboard/components/analytics-content.tsx (2)
5-102: LGTM!The skeleton-based placeholder UI is well-structured with:
- Proper responsive design using
md:breakpoints- Consistent styling patterns
- Clean iteration for repeated elements (metrics cards, extra blocks)
- Good use of semantic Text component with size variants
This provides a solid foundation for replacing with real data.
69-74: This usage is correct. Thecolorprop is explicitly supported by theShipfoxLogocomponent, which the Icon component renders whenname="shipfox". The Icon wrapper passes all additional props through to the underlying icon component via spread operator, allowing thecolorprop to flow through properly and be applied to the SVG's fill attribute. No changes needed.Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
This is the final PR Bugbot will review for you during this billing cycle
Your free Bugbot reviews will reset on January 19
Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
libs/react/ui/src/components/dashboard/components/user-profile.tsx
Outdated
Show resolved
Hide resolved
…ndling and UI consistency
Note
Introduces a Storybook dashboard with Analytics/Jobs tabs, animated topbar, org/user menus, plus minor UI tweaks and tests.
Dashboardwith stickyTopMenutabs (analytics,jobs), scroll-awareAnimatedLogo, andTopbar(org selector, setup button, search/help/notifications, mobile menu, user profile) undercomponents/dashboard/*; exports viacomponents/dashboard/index.tsand Storybookdashboard.stories.tsx(fullscreen).AnalyticsContentwith metric cards/placeholders;JobsContentwith searchable/paginatedDataTable.OrganizationSelector,MobileMenu,CompleteSetupButton,UserProfile(usage gauge),TopbarButton.avatarrounded radius set torounded-4;SelectTriggericon switched toexpandUpDownLine; newSelectstoryTimeSelector.form.stories.tsxadds Argos screenshotplaystep forBasicstory.@shipfox/react-ui.Written by Cursor Bugbot for commit d1f4aaa. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
New Features
Style
✏️ Tip: You can customize this high-level summary in your review settings.