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

Add option to display color filters as swatches #230

Merged
merged 4 commits into from
Dec 10, 2024
Merged

Add option to display color filters as swatches #230

merged 4 commits into from
Dec 10, 2024

Conversation

hta218
Copy link
Member

@hta218 hta218 commented Dec 10, 2024

Summary by CodeRabbit

  • New Features

    • Enhanced Checkbox component to support flexible label content.
    • Added custom styling options to the TooltipContent component.
    • Introduced color swatch support in the Filters component.
    • New properties for customizable filter options in CollectionFilters.
  • Bug Fixes

    • Improved rendering logic for filter labels and color swatches.
  • Chores

    • Updated Tailwind CSS configuration with new animation keyframes.

Copy link
Contributor

coderabbitai bot commented Dec 10, 2024

Walkthrough

This pull request introduces several modifications across various components in the application. The Checkbox component now accepts more flexible label types and has updated export semantics. The TooltipContent component gains a new style prop for custom styling. The variants variable in the product form is now exported for broader accessibility. The Filters component enhances filter rendering with color swatches and modifies related logic. The CollectionFilters component adds new properties for customizable filter options. Lastly, the Tailwind CSS configuration is updated with a new animation keyframe and configuration.

Changes

File Change Summary
app/components/checkbox.tsx - Changed label prop type from string to React.ReactNode.
- Exported as let Checkbox.
- Updated class names and simplified checkbox styles.
- Replaced IconCheck with Check component.
- Modified label rendering logic.
app/components/tooltip.tsx - Added style prop to TooltipContent for custom styles.
- Utilized style for animation duration.
- Removed opacity-0 class from Content.
app/modules/product-form/options.tsx - Changed variants from local to exported variable.
app/sections/collection-filters/filters.tsx - Expanded parentData destructuring.
- Integrated filter rendering logic directly into map function.
- Added asColorSwatch prop to ListItemFilter.
- Modified checked state handling.
app/sections/collection-filters/index.tsx - Updated CollectionFiltersData interface to include enableColorSwatch and displayAsButtonFor.
- Modified CollectionFilters component to accept new props.
- Updated schema with new inputs.
tailwind.config.js - Added new animation keyframe and configuration for "slide-down-and-fade".

Possibly related PRs

  • Add support for animations #220: The changes in the main PR regarding the Checkbox component's rendering logic and class names may relate to the animation support introduced in this PR, as both involve UI components and their visual presentation.

Poem

🐰 In the meadow where the checkboxes play,
New colors and swatches brighten the day.
Tooltips dance with a fade and a slide,
Filters now flourish, with joy they abide.
With styles that are custom, oh what a delight,
Our components are hopping, all set for flight! 🌼


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. (Experiment)
  • @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.

@hta218 hta218 merged commit 42fc2d5 into main Dec 10, 2024
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: 2

🧹 Outside diff range and nitpick comments (3)
app/sections/collection-filters/index.tsx (1)

187-187: Consider enhancing the help text for displayAsButtonFor.

While the help text is informative, it could be more specific about the expected format and provide examples.

-          helpText: "Comma-separated list of filters to display as buttons",
+          helpText: "Comma-separated list of filters to display as buttons (e.g., 'Size, Color, Material')",
app/sections/collection-filters/filters.tsx (2)

57-58: Consider making color filter detection more flexible.

The current implementation uses exact matches for color filter labels. Consider using case-insensitive comparison or allowing custom color filter labels through configuration.

-const COLORS_FILTERS = ["Color", "Colors", "Colour", "Colours"];
+const COLORS_FILTERS = ["color", "colors", "colour", "colours"];
-          enableColorSwatch && COLORS_FILTERS.includes(filter.label);
+          enableColorSwatch && COLORS_FILTERS.includes(filter.label.toLowerCase());

Also applies to: 88-90


153-162: Consider debouncing filter changes.

The filter change handler might trigger frequent navigation updates. Consider implementing debouncing for better performance.

+import { useDebounce } from '~/hooks/use-debounce';
+
 function ListItemFilter({ ... }) {
+  const debouncedNavigate = useDebounce(navigate, 300);
+
   function handleCheckedChange(checked: boolean) {
     setChecked(checked);
     if (checked) {
       let link = getFilterLink(option.input as string, params, location);
-      navigate(link, { preventScrollReset: true });
+      debouncedNavigate(link, { preventScrollReset: true });
     } else if (filter) {
       let link = getAppliedFilterLink(filter, params, location);
-      navigate(link, { preventScrollReset: true });
+      debouncedNavigate(link, { preventScrollReset: true });
     }
   }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 61fc0da and 2a92ecf.

📒 Files selected for processing (6)
  • app/components/checkbox.tsx (1 hunks)
  • app/components/tooltip.tsx (1 hunks)
  • app/modules/product-form/options.tsx (1 hunks)
  • app/sections/collection-filters/filters.tsx (2 hunks)
  • app/sections/collection-filters/index.tsx (3 hunks)
  • tailwind.config.js (2 hunks)
🔇 Additional comments (11)
app/components/checkbox.tsx (3)

8-8: LGTM: Label type change enables color swatch rendering

The change from string to React.ReactNode aligns with the PR objective of supporting color swatches in filters.


15-15: LGTM: UI refinements

Good improvements:

  • Using gap instead of space-x is more modern
  • Simplified checkbox styles while maintaining functionality
  • Updated to Phosphor icons maintains consistency

Also applies to: 18-18, 21-22


25-25: LGTM: Flexible label rendering

The conditional rendering handles both string labels and component labels (like color swatches) appropriately.

app/components/tooltip.tsx (2)

27-27: LGTM: Flexible animation customization

Good practices:

  • Added style prop for custom animation timing
  • Default duration fallback in Tailwind config
  • Proper spreading of additional styles

Also applies to: 40-45


33-33: LGTM: Clean tooltip styling

The tooltip styling provides good contrast with background/text colors and appropriate spacing.

tailwind.config.js (2)

34-40: LGTM: Well-structured animation keyframe

Good implementation:

  • Uses CSS variable for customizable distance
  • Handles both opacity and transform
  • Matches existing animation patterns

85-86: LGTM: Flexible animation configuration

Well implemented:

  • Customizable duration via CSS variable
  • Smooth easing with cubic-bezier
  • Consistent with other animation configurations
app/sections/collection-filters/index.tsx (2)

18-19: LGTM! Interface updates are well-defined.

The new properties enableColorSwatch and displayAsButtonFor are clearly typed and appropriately placed in the interface.


37-38: LGTM! Props destructuring is correctly implemented.

The new props are properly destructured from the parent data object.

app/modules/product-form/options.tsx (1)

9-43: Verify the usage of exported variants across components.

The variants configuration is now exported, which is good for reusability. However, we should ensure this doesn't lead to unexpected styling conflicts in other components.

✅ Verification successful

No styling conflicts found with the exported variants

The exported variants from product-form/options.tsx is only imported once in collection-filters/filters.tsx where it's renamed to productOptionsVariants to avoid naming conflicts. The other occurrences of variants in the codebase are either:

  1. Different variant configurations defined locally in their respective components
  2. GraphQL query references related to product variants

The current implementation follows good practices by:

  • Using a descriptive alias when importing to avoid naming collisions
  • Keeping variant configurations scoped to their respective components
  • Having clear separation between styling variants and product variants
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for imports of variants from this file
rg "import.*variants.*from.*product-form/options" -A 2

# Search for direct usage of the variants
rg "variants\({.*}\)" -A 2

Length of output: 478


Script:

#!/bin/bash
# Search for imports using a more flexible pattern
rg "from.*product-form/options"

# Search for variant usage with a corrected pattern
rg "variants\(" -A 2

# Search for className usage that might reference variants
rg "className.*variants" -A 2

Length of output: 32343

app/sections/collection-filters/filters.tsx (1)

25-29: LGTM! Dependencies and constants are well-organized.

The new imports and COLORS_FILTERS constant are appropriately defined. The constant helps standardize color filter detection.

}

const Checkbox = React.forwardRef<
export let Checkbox = React.forwardRef<
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider keeping the export as const

Using let for component exports is unusual and suggests potential mutation, which could lead to unexpected behavior. React components should generally be immutable.

-export let Checkbox = React.forwardRef<
+export const Checkbox = React.forwardRef<
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export let Checkbox = React.forwardRef<
export const Checkbox = React.forwardRef<

Comment on lines +164 to +209
if (asColorSwatch) {
let swatchColor = swatches.colors.find(({ name }) => name === option.label);
let optionConf = options.find(({ name }) => {
return name.toLowerCase() === option.label.toLowerCase();
});

let { shape = "square", size = "md" } = optionConf || {};
return (
<Tooltip>
<TooltipTrigger>
<button
type="button"
className={cn(
productOptionsVariants({
colorSize: size,
shape,
}),
checked ? "p-1 border-line" : "border-line-subtle",
)}
onClick={() => handleCheckedChange(!checked)}
>
<span
className={cn(
"w-full h-full inline-block border-none hover:border-none",
productOptionsVariants({ shape }),
)}
style={{
backgroundColor:
swatchColor?.value || option.label.toLowerCase(),
}}
/>
</button>
</TooltipTrigger>
<TooltipContent>
{showFiltersCount ? (
<span>
{option.label}{" "}
<span className="text-gray-100">({option.count})</span>
</span>
) : (
option.label
)}
</TooltipContent>
</Tooltip>
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance color swatch accessibility.

The color swatch implementation should include ARIA attributes for better accessibility. Also, consider adding a fallback color for invalid color values.

           <button
             type="button"
+            aria-label={`${option.label} (${option.count} items)`}
             className={cn(
               productOptionsVariants({
                 colorSize: size,
                 shape,
               }),
               checked ? "p-1 border-line" : "border-line-subtle",
             )}
             onClick={() => handleCheckedChange(!checked)}
           >
             <span
               className={cn(
                 "w-full h-full inline-block border-none hover:border-none",
                 productOptionsVariants({ shape }),
               )}
               style={{
                 backgroundColor:
-                  swatchColor?.value || option.label.toLowerCase(),
+                  swatchColor?.value || option.label.toLowerCase() || '#cccccc',
               }}
             />
           </button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (asColorSwatch) {
let swatchColor = swatches.colors.find(({ name }) => name === option.label);
let optionConf = options.find(({ name }) => {
return name.toLowerCase() === option.label.toLowerCase();
});
let { shape = "square", size = "md" } = optionConf || {};
return (
<Tooltip>
<TooltipTrigger>
<button
type="button"
className={cn(
productOptionsVariants({
colorSize: size,
shape,
}),
checked ? "p-1 border-line" : "border-line-subtle",
)}
onClick={() => handleCheckedChange(!checked)}
>
<span
className={cn(
"w-full h-full inline-block border-none hover:border-none",
productOptionsVariants({ shape }),
)}
style={{
backgroundColor:
swatchColor?.value || option.label.toLowerCase(),
}}
/>
</button>
</TooltipTrigger>
<TooltipContent>
{showFiltersCount ? (
<span>
{option.label}{" "}
<span className="text-gray-100">({option.count})</span>
</span>
) : (
option.label
)}
</TooltipContent>
</Tooltip>
);
}
if (asColorSwatch) {
let swatchColor = swatches.colors.find(({ name }) => name === option.label);
let optionConf = options.find(({ name }) => {
return name.toLowerCase() === option.label.toLowerCase();
});
let { shape = "square", size = "md" } = optionConf || {};
return (
<Tooltip>
<TooltipTrigger>
<button
type="button"
aria-label={`${option.label} (${option.count} items)`}
className={cn(
productOptionsVariants({
colorSize: size,
shape,
}),
checked ? "p-1 border-line" : "border-line-subtle",
)}
onClick={() => handleCheckedChange(!checked)}
>
<span
className={cn(
"w-full h-full inline-block border-none hover:border-none",
productOptionsVariants({ shape }),
)}
style={{
backgroundColor:
swatchColor?.value || option.label.toLowerCase() || '#cccccc',
}}
/>
</button>
</TooltipTrigger>
<TooltipContent>
{showFiltersCount ? (
<span>
{option.label}{" "}
<span className="text-gray-100">({option.count})</span>
</span>
) : (
option.label
)}
</TooltipContent>
</Tooltip>
);
}

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.

1 participant