Skip to content
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

feat(ui): add Shadcn skeletons for dynamically loaded components #151

Merged
merged 1 commit into from
Feb 12, 2025

Conversation

Verifieddanny
Copy link
Collaborator

@Verifieddanny Verifieddanny commented Feb 12, 2025

πŸ“ Implement Shadcn Skeletons for Dynamically Loaded Components

πŸ› οΈ Issue

Closes #139

πŸ“– Description

This PR enhances the loading experience by replacing basic fallback components with visually appealing Skeleton components from Shadcn/UI. Each Skeleton component is designed to match the layout and structure of its respective section, ensuring a seamless transition before the actual content loads.

πŸ”„ Changes Implemented

  • Replaced basic fallbacks with Shadcn/UI Skeleton components for dynamically imported sections in home.tsx and other relevant components.

  • Created Skeleton components file for the dynamically loaded components on home.tsx

  • Created Skeleton components for Text placeholders with adjustable widths using <SkeletonText width={[100, 83, 74.6]} /> to simulate multiline text.

  • Ensured visual consistency by matching Skeleton layouts with actual components.

πŸ—οΈ New Structure

Skeleton components were added under:

apps/web/components/sections/home/skeletons.tsx
apps/web/components/base/skeleton-text.tsx

βœ… Acceptance Criteria

All dynamically imported components now have corresponding Shadcn Skeleton fallbacks.
The loading experience is improved without introducing visual or functional regressions.
Skeletons accurately reflect the final component layouts.

🎯 Benefits

  • Enhanced user experience during loading.

  • Improved visual consistency across components.

  • More modular and reusable fallback components.

πŸ”¬ Testing

Verified Skeleton components display correctly during loading.
Ensured no UI breakages or unexpected layout shifts.

Summary by CodeRabbit

  • New Features

    • Introduced enhanced loading placeholders across the home page, offering a more modern and visually appealing experience while content is being fetched.
    • Added dynamic skeleton loaders that adjust to various content widths and layouts.
  • Style

    • Implemented dynamic styling for loading elements that adapts seamlessly between light and dark themes for improved visual consistency.

Copy link

vercel bot commented Feb 12, 2025

The latest updates on your projects. Learn more about Vercel for Git β†—οΈŽ

Name Status Preview Comments Updated (UTC)
kindfi βœ… Ready (Inspect) Visit Preview πŸ’¬ Add feedback Feb 12, 2025 10:16pm

Copy link
Contributor

coderabbitai bot commented Feb 12, 2025

Walkthrough

This pull request introduces several updates to improve loading visuals. A new CSS variable, --skeleton-opacity, is defined for both light and dark themes. The Skeleton component is updated to use this variable for dynamic opacity. A new SkeletonText component is added to render multiple placeholder items, and the home page now replaces static loading indicators with various skeleton components. Additionally, a new file is introduced that exports a suite of skeleton components for different sections of the UI.

Changes

File(s) Change Summary
apps/web/app/css/globals.css, apps/web/components/base/skeleton.tsx Added the CSS custom property --skeleton-opacity (with 0.3 for light and 0.2 for dark themes) and updated the Skeleton component to use this dynamic opacity value.
apps/web/components/base/skeleton-text.tsx Introduced a new functional component SkeletonText that renders multiple Skeleton items with widths based on an input array and applies conditional class names via a utility function.
apps/web/components/pages/home.tsx Updated the home page to replace static loading indicators with dynamic skeleton components imported from a new skeletons module.
apps/web/components/sections/home/skeletons.tsx Added a new file exporting multiple skeleton components (including SkeletonGrid, SkeletonHero, SkeletonUserJourney, among others) for displaying placeholder UIs in different home page sections.

Sequence Diagram(s)

sequenceDiagram
    participant HP as Home Page
    participant DI as Dynamic Import System
    participant SK as Skeleton Component
    participant LC as Loaded Content
    HP->>DI: Request section component
    DI-->>HP: Return corresponding Skeleton (e.g., SkeletonHero)
    HP->>SK: Render Skeleton as placeholder (using dynamic opacity)
    Note right of SK: Display loading state
    HP->>DI: Fetch actual content
    DI-->>HP: Return loaded content
    HP->>SK: Replace skeleton with real content
Loading
sequenceDiagram
    participant ST as SkeletonText
    participant S as Skeleton
    ST->>S: Loop over width values to render Skeleton items
    S-->>ST: Render each Skeleton with dynamic width and opacity
Loading

Suggested labels

enhancement, webapp, documentation

Poem

In a realm where loading states arise,
CSS whispers secrets in light and dark skies.
Skeletons now gracefully hint at what's to come,
With dynamic widths and flows that hum.
A canvas of code, both playful and bright,
Sketching out content in a mesmerizing light.
CodeRabbit dances with each innovative byte!


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❀️ Share
πŸͺ§ Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai bot added documentation Improvements or additions to documentation enhancement New feature improvement or request webapp web app related labels Feb 12, 2025
Copy link
Contributor

@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 (5)
apps/web/components/base/skeleton-text.tsx (2)

6-8: Consider adding type constraints for width values.

The width array could benefit from type constraints to ensure valid percentage values.

 interface SkeletonTextProps {
-  width: number[]
+  width: Array<number & { readonly brand: unique symbol }>
   className?: string
 }
+
+type Percentage = number & { readonly brand: unique symbol }
+const asPercentage = (n: number): Percentage => {
+  if (n < 0 || n > 100) throw new Error('Percentage must be between 0 and 100')
+  return n as Percentage
+}

13-20: Consider memoizing the skeleton elements.

For better performance when rendering multiple skeletons, consider using useMemo.

+import { useMemo } from 'react'
+
 export const SkeletonText: FC<SkeletonTextProps> = ({ width, className }) => {
+  const skeletons = useMemo(
+    () => width.map((w) => (
+      <Skeleton
+        key={w}
+        className={cn('h-4', className)}
+        style={{ width: `${w}%` }}
+      />
+    )),
+    [width, className]
+  )
+
   return (
     <div className="space-y-2">
-      {width.map((w) => (
-        <Skeleton
-          key={w}
-          className={cn('h-4', className)}
-          style={{ width: `${w}%` }}
-        />
-      ))}
+      {skeletons}
     </div>
   )
 }
apps/web/components/sections/home/skeletons.tsx (2)

45-48: Consider optimizing array generation.

The current array generation could be more performant using Array.from with a mapping function.

-      {Array.from({ length: count }).map((_, index) => {
-        const key = `skeleton-${index}`
-        return <div key={key}>{renderItem(index)}</div>
-      })}
+      {Array.from(
+        { length: count },
+        (_, index) => (
+          <div key={`skeleton-${index}`}>{renderItem(index)}</div>
+        )
+      )}

6-12: Consider using a const enum for columns and gap values.

Using const enums would provide better type safety and maintainability.

+const enum GridColumns {
+  Two = 2,
+  Three = 3,
+  Four = 4,
+  Five = 5
+}
+
+const enum GridGap {
+  Small = 3,
+  Medium = 4,
+  Large = 6,
+  XLarge = 8,
+  XXLarge = 12
+}
+
 interface SkeletonGridProps {
   count: number
-  columns?: 1 | 2 | 3 | 4 | 5
-  gap?: 3 | 4 | 6 | 8 | 12
+  columns?: GridColumns
+  gap?: GridGap
   className?: string
   renderItem: (index: number) => React.ReactNode
 }
apps/web/app/css/globals.css (1)

52-52: Consider grouping skeleton variables with related theme properties.

We could enhance the organization by moving the skeleton opacity variables near related opacity or component variables within each theme section. This would make it easier to maintain related theme properties together.

Consider this organization:

 		--ring: 99 57.1% 56.1%;
+		/* Component-specific opacities */
+		--skeleton-opacity: 0.3;
 		--radius: 0.75rem;
-		--skeleton-opacity: 0.3;

And similarly in the dark theme:

 		--ring: 99 57.1% 46.1%;
+		/* Component-specific opacities */
+		--skeleton-opacity: 0.2;
 		--radius: 0.75rem;
-		--skeleton-opacity: 0.2;

Also applies to: 81-81

πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 19fd0b5 and 86e170f.

πŸ“’ Files selected for processing (5)
  • apps/web/app/css/globals.css (2 hunks)
  • apps/web/components/base/skeleton-text.tsx (1 hunks)
  • apps/web/components/base/skeleton.tsx (1 hunks)
  • apps/web/components/pages/home.tsx (6 hunks)
  • apps/web/components/sections/home/skeletons.tsx (1 hunks)
🧰 Additional context used
πŸ““ Path-based instructions (1)
`**/*.css`: Review style files for consistent Tailwind utili...

**/*.css: Review style files for consistent Tailwind utility usage. Verify responsive design patterns and theme consistency. Check proper modularization and style reuse.

  • apps/web/app/css/globals.css
πŸ”‡ Additional comments (4)
apps/web/components/base/skeleton.tsx (1)

9-12: Great use of CSS custom properties!

The transition to using CSS variables for opacity control is an excellent improvement. This approach provides better theme support and maintainability.

apps/web/components/pages/home.tsx (1)

17-18: Excellent optimization with SSR enabled for Hero!

Enabling SSR for the Hero component is a great optimization that will improve the initial page load experience.

apps/web/app/css/globals.css (2)

52-52: Well-structured theme integration for skeleton components!

The skeleton opacity values are thoughtfully chosen for both themes, with a higher opacity (0.3) in light mode for better visibility and a lower opacity (0.2) in dark mode to maintain comfortable contrast levels.

Also applies to: 81-81


52-52: Excellent Tailwind integration for skeleton components!

The new CSS variables align perfectly with Tailwind's utility-first approach, enabling dynamic opacity control through utilities like bg-primary/[var(--skeleton-opacity)]. This implementation maintains consistency with the existing design system while providing flexible skeleton loading states.

Also applies to: 81-81

@Bran18 Bran18 self-requested a review February 12, 2025 22:18
Copy link
Contributor

@Bran18 Bran18 left a comment

Choose a reason for hiding this comment

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

Great work on these changes and tks for taking into consideration the changes from andler! Everything looks solidβ€”merging now. Kudos for the effort

@Bran18 Bran18 merged commit 04e263e into develop Feb 12, 2025
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature improvement or request webapp web app related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enhance Suspense Fallbacks with Skeleton Components Across All Sections
2 participants