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

[WEB-4025] Add useTheming hook, reduce generated TW classes #510

Merged
merged 1 commit into from
Oct 16, 2024

Conversation

jamiehenson
Copy link
Member

@jamiehenson jamiehenson commented Oct 14, 2024

Jira Ticket Link / Motivation

There's been a few swings at getting dynamic theming right across our components, but so far things haven't been quite right in terms of optimisation and the usage of the functionality in the code - this PR aims to address things on both those fronts.

Summary of changes

Currently, the approach to generating extra Tailwind classes necessitated by dynamic theming has embedded a misunderstanding about Tailwind itself. Turns out, very large lookup tables are ingested by Tailwind wholesale, and result in very large build sizes.

This PR flips the approach by scanning the repo for uses of the themeColor helper (previously t), and keeping a record of the thematic variants of those classes only, meaning we only generate the classes we actually need instead of every possible combination.

This is supported by the restructuring of the dynamic theming logic into a hook called useTheming. The advantages of this are twofold:

  • it standardises what the theming helper is called. Previously, t was a convention but this wasn't reinforced anywhere, which is messy, particularly when you need some consistency when scanning for theme-oriented class names in the code. useTheming only gives you themeColor back.
  • it paves the way for global theming in future, as we can integrate this hook in with an repo-wide context which holds the state for theming across a whole app

How do you manually test this?

It's a background change so hard to test directly. Look at Storybook and see all the colours work on theme-flipped components (i.e. PricingCards) I guess.

Reviewer Tasks (optional)

Merge/Deploy Checklist

  • Written automated tests for implemented features/fixed bugs
  • Rebased and squashed commits
  • Commits have clear descriptions of their changes
  • Checked for any performance regressions

Frontend Checklist

  • No frontend changes in this PR
  • Added before/after screenshots for changes
  • Tested on different platforms/browsers with Browserstack
  • Compared with the initial design / our brand guidelines
  • Checked the code for accessibility issues (VoiceOver User Guide)?

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced a new theming hook (useTheming) to manage theme colors dynamically across components.
    • Enhanced color management with new definitions and structures for color types.
  • Bug Fixes

    • Removed deprecated determineThemeColor function to streamline theme color management.
  • Documentation

    • Updated documentation for DynamicTheming to reflect new usage patterns with the useTheming hook.
  • Chores

    • Incremented version number in package.json to indicate a shift to a development version.
    • Modified .gitignore to adjust tracking behavior for specific color files.

Copy link
Contributor

coderabbitai bot commented Oct 14, 2024

Walkthrough

The pull request introduces changes to the .gitignore file to manage the tracking of specific JSON files, updates the package.json version number, and modifies multiple components to implement a new theming hook (useTheming). The determineThemeColor utility function has been removed and replaced with the useTheming hook across various components for dynamic theming. Additionally, a new utility function, invertTailwindClassVariant, is introduced for color inversion logic.

Changes

File Path Change Summary
.gitignore Added computed-colors.json to tracking; excluded computed-colors-*.json from being tracked.
package.json Updated version from 14.6.8 to 14.7.0.
src/core/Icon/EncapsulatedIcon.tsx Removed determineThemeColor, added useTheming hook, and updated JSX to use themeColor.
src/core/Pricing/PricingCards.tsx Removed determineThemeColor, added useTheming hook, and updated JSX to use themeColor.
src/core/ProductTile.tsx Removed determineThemeColor, added useTheming hook, and updated JSX to use themeColor.
src/core/Tooltip.tsx Removed determineThemeColor, added useTheming hook, and updated JSX to use themeColor.
src/core/hooks/useTheming.tsx Introduced useTheming hook with themeColor function for theming logic.
src/core/styles/colors/Colors.stories.tsx Replaced determineThemeColor with useTheming in DynamicTheming component; updated render logic.
src/core/styles/colors/utils.ts Removed determineThemeColor, added invertTailwindClassVariant function, and updated imports.
scripts/compute-colors.ts Removed computeColors function; added findStringInFiles function for reading files and processing colors.
src/core/styles/colors/types.ts Added colors constant, renamed colorNames to colorRoles, removed numericalColors, and added colorGroupLengths.

Possibly related PRs

Suggested labels

review

Suggested reviewers

  • aralovelace
  • kennethkalmer
  • denissellu

Poem

🐇 In the meadow where colors play,
A new theme hops in, brightening the day.
With hooks and styles, we dance and twirl,
Ignoring old paths, watch new ones unfurl.
So let’s celebrate with joy and cheer,
For vibrant themes are finally here! 🌈


🪧 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 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.

@jamiehenson jamiehenson force-pushed the reduce-tw-class-generation branch 2 times, most recently from f943999 to 19c0991 Compare October 14, 2024 14:12
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: 9

🧹 Outside diff range and nitpick comments (10)
src/core/hooks/useTheming.tsx (1)

10-13: Consider differentiating default values for baseTheme and theme.

While providing default values is good practice, having the same default value ("dark") for both baseTheme and theme might lead to unexpected behavior if only one is provided. Consider setting different defaults or documenting the intended behavior clearly.

src/core/Tooltip.tsx (1)

190-193: Approve changes with a suggestion for improved readability.

The updates to the tooltip's className correctly implement the new theming approach and maintain the existing functionality. However, the line is quite long and could be split for better readability.

Consider refactoring the className assignment for improved readability:

className={`
  ${themeColor("bg-neutral-1000")} 
  ${themeColor("text-neutral-200")} 
  ui-text-p3 font-medium p-16 
  ${interactive ? "" : "pointer-events-none"} 
  rounded-lg absolute 
  ${tooltipProps?.className ?? ""} 
  ${fadeOut ? "animate-[tooltipExit_0.25s_ease-in-out]" : "animate-[tooltipEntry_0.25s_ease-in-out]"}
`}

This format improves readability without changing the functionality.

src/core/styles/colors/utils.ts (1)

1-10: Ensure all imported color arrays are necessary.

The imports of various color arrays (blueColors, greenColors, neutralColors, orangeColors, pinkColors, violetColors, yellowColors) from ./types should be verified to confirm they are all required. Unused imports may lead to unnecessary code bloat.

scripts/compute-colors.ts (1)

64-66: Update the Console Message to Reflect Single Output File

The console message states that "Tailwind theme classes have been computed and written to JSON files," but only one file (computed-colors.json) is being written. Update the message to accurately reflect this.

Apply this diff to correct the message:

-      `🎨 Tailwind theme classes have been computed and written to JSON files.`,
+      `🎨 Tailwind theme classes have been computed and written to computed-colors.json.`,
src/core/ProductTile.tsx (1)

22-25: Confirm the necessity of specifying baseTheme: "dark".

If "dark" is the default baseTheme in useTheming, you might not need to specify it explicitly. Consider omitting baseTheme if it's unnecessary.

src/core/Pricing/PricingCards.tsx (5)

95-95: Simplify complex className for better readability

The className on line 95 is quite complex due to multiple inline conditionals and template literals. Consider extracting parts of this string into variables or using a utility like clsx or classnames to enhance readability and maintainability.

For example, you could refactor as:

const borderClass = themeColor(borderClasses(border?.color)?.border ?? "border-neutral-1100");
const styleClass = border?.style ?? "";
const responsiveClass = delimiter ? "@[520px]:flex-row @[920px]:flex-col" : "";

className={`relative border ${borderClass} ${styleClass} flex-1 px-24 py-32 flex flex-col gap-24 rounded-2xl group ${responsiveClass} min-w-[272px] backdrop-blur`}

152-152: Simplify additionalCSS in FeaturedLink component

The additionalCSS prop on line 152 is quite extensive. Consider breaking it into variables or using a utility function to enhance readability.

For example:

const ctaClasses = `text-center ui-btn ${themeColor("bg-neutral-000")} ${themeColor("text-neutral-1300")} hover:text-neutral-000 px-24 !py-12 ${cta.className ?? ""} cursor-pointer`;

<FeaturedLink
  additionalCSS={ctaClasses}
  url={cta.url}
  onClick={cta.onClick}
  disabled={cta.disabled}
>
  {cta.text}
</FeaturedLink>

181-181: Review complex className for list items

The className for list items on line 181 is complex due to multiple conditional expressions. Refactoring this into variables may improve readability.

Example:

const paddingClass = index === 0 ? "py-8" : "py-4";
const backgroundClass = index > 0 && index % 2 === 0 ? `${themeColor("bg-blue-900")} rounded-md` : "";

className={`flex justify-between gap-16 px-8 -mx-8 ${paddingClass} ${backgroundClass}`}

218-220: Manage long additionalCSS strings

The additionalCSS prop on lines 218-220 is quite lengthy. Consider refactoring it into variables for clarity.

Example:

const featuredLinkClasses = `absolute sm:-translate-x-120 sm:opacity-0 sm:group-hover:translate-x-24 duration-300 delay-0 sm:group-hover:delay-100 sm:group-hover:opacity-100 transition-[transform,opacity] font-medium ui-text-p3 ${themeColor("text-neutral-500")} hover:${themeColor("text-neutral-000")} cursor-pointer`;

<FeaturedLink
  url={cta.url}
  additionalCSS={featuredLinkClasses}
  onClick={cta.onClick}
  iconColor={themeColor(listItemColors?.foreground ?? "text-white")}
>
  {cta.text}
</FeaturedLink>

227-227: Simplify complex className for transition effects

The className on line 227 includes multiple transition classes. Extracting these into variables can enhance readability.

Example:

const transitionClasses = "absolute sm:translate-x-24 sm:opacity-100 sm:group-hover:translate-x-120 sm:group-hover:opacity-0 duration-200 delay-100 sm:group-hover:delay-0 transition-[transform,opacity]";
const textClasses = `leading-6 tracking-widen-0.15 font-light text-p3 ${themeColor("text-neutral-800")}`;

className={`${transitionClasses} ${textClasses}`}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between d3ece16 and b49dd8c.

📒 Files selected for processing (10)
  • .gitignore (1 hunks)
  • package.json (1 hunks)
  • scripts/compute-colors.ts (1 hunks)
  • src/core/Icon/EncapsulatedIcon.tsx (2 hunks)
  • src/core/Pricing/PricingCards.tsx (11 hunks)
  • src/core/ProductTile.tsx (4 hunks)
  • src/core/Tooltip.tsx (4 hunks)
  • src/core/hooks/useTheming.tsx (1 hunks)
  • src/core/styles/colors/Colors.stories.tsx (2 hunks)
  • src/core/styles/colors/utils.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • .gitignore
  • package.json
🧰 Additional context used
🔇 Additional comments (30)
src/core/hooks/useTheming.tsx (3)

1-8: LGTM: Imports and type definition are well-structured.

The imports are appropriate for the hook's functionality, and the UseThemingProps type is well-defined with optional properties, allowing flexibility in usage.


14-18: LGTM: themeColor function is well-implemented.

The themeColor function is efficiently memoized using useCallback. The logic for determining the color is concise and clear, and the dependency array is correctly specified.


1-25: Overall, the useTheming hook is well-implemented.

The hook is well-structured, follows React best practices, and provides a clear API for theme-based color management. The use of TypeScript for type definitions and useCallback for performance optimization are commendable. Consider the suggestions for default values and return structure to enhance future maintainability and extensibility.

src/core/Icon/EncapsulatedIcon.tsx (4)

3-4: LGTM: Import changes align with PR objectives

The introduction of the useTheming hook and the removal of ColorClass and determineThemeColor imports are consistent with the PR's goal of reducing generated Tailwind classes and improving theming. These changes suggest a more centralized approach to managing theme-related functionality.


21-24: LGTM: Proper implementation of useTheming hook

The useTheming hook is correctly implemented with the appropriate parameters. The destructured themeColor function effectively replaces the previous determineThemeColor utility, aligning with the PR's objective of introducing the new hook. This change should contribute to reducing generated Tailwind classes and improving theming consistency.


32-32: LGTM: Consistent application of new theming approach in JSX

The changes in the JSX return statement correctly implement the new theming approach using the themeColor function. The existing functionality, including conditional class application based on the theme prop, is preserved. These modifications align with the PR's goal of reducing generated Tailwind classes while maintaining the component's behavior.

Also applies to: 36-36


Line range hint 1-46: Overall assessment: Successful implementation of useTheming hook

The changes in this file successfully implement the new useTheming hook, replacing the previous determineThemeColor utility. This modification aligns well with the PR objectives of introducing the useTheming hook and reducing generated Tailwind classes. The new approach should lead to improved theming consistency across the application while maintaining the existing functionality of the EncapsulatedIcon component.

Key improvements:

  1. Centralized theming logic through the useTheming hook.
  2. Reduced reliance on generated Tailwind classes.
  3. Maintained component functionality and conditional theming.

These changes contribute positively to the codebase's maintainability and consistency.

src/core/Tooltip.tsx (4)

14-14: LGTM: New hook import added correctly.

The import statement for the useTheming hook is properly added and follows the correct relative path convention.


169-169: LGTM: Icon color updated to use new theming approach.

The Icon component's color prop has been correctly updated to use the themeColor function from the new theming hook. This change maintains consistency with the new theming strategy.


Line range hint 1-203: Overall assessment: Changes successfully implement new theming approach.

The modifications to the Tooltip component effectively integrate the new useTheming hook and consistently apply the updated theming strategy throughout the component. The core functionality of the Tooltip remains intact, with improvements to the theming system.

A few minor suggestions have been made for verification and readability, but overall, the changes appear to be well-implemented and maintain the component's intended behavior.


41-44: Verify the baseTheme setting in useTheming hook.

The implementation of the useTheming hook looks good and correctly replaces the previous determineThemeColor utility. However, please confirm that setting baseTheme: "light" is the intended behavior for this component.

To ensure consistency across the codebase, let's check how baseTheme is set in other components:

src/core/styles/colors/utils.ts (2)

25-36: Consider edge cases for color variants outside the defined ranges.

The function may not handle cases where the className includes colors or variants not defined in the extents object, potentially leading to NaN or incorrect calculations.

Please ensure that input validation is added to handle unexpected className values gracefully.


25-36: Verify that the extents object covers all possible colors.

The invertTailwindClassVariant function relies on the extents object to determine the flipping logic. It's crucial to ensure that all colors used in the application are included in extents. Missing colors could lead to undefined values and runtime errors.

Run the following script to check for any color classes used in the codebase that are not covered by extents:

Expected Result:

  • The script should output an empty list, indicating that all used colors are covered.
  • If any colors are listed, they are missing from extents and should be added.
src/core/ProductTile.tsx (1)

46-46: 🛠️ Refactor suggestion

Avoid using negative margins with arbitrary values.

The negative margin mt-[-3px] might lead to maintenance issues and inconsistencies. Consider using standard spacing utilities provided by Tailwind CSS or adjusting the layout to eliminate the need for negative margins.

Apply this diff to remove the negative margin:

-              className={`ui-text-p2 ${themeColor("text-neutral-000")} font-bold ${unavailable ? "" : "mt-[-3px]"}`}
+              className={`ui-text-p2 ${themeColor("text-neutral-000")} font-bold`}

Ensure that removing the negative margin does not adversely affect the visual layout. If spacing adjustments are needed, consider using predefined margin classes from Tailwind CSS.

src/core/Pricing/PricingCards.tsx (13)

9-9: Import useTheming hook correctly

The useTheming hook is imported properly, ensuring theming capabilities are available in the component.


48-51: Verify hardcoding of baseTheme to "dark"

In the useTheming hook, baseTheme is set to "dark". If the component is intended to support multiple base themes, consider making baseTheme dynamic or deriving it from props for greater flexibility.


62-62: Proper use of themeColor for additionalCSS

Applying themeColor("text-neutral-500") to the additionalCSS prop of the Icon component ensures consistent theming.


105-105: Ensure background theming with themeColor

The use of themeColor("bg-neutral-1300") correctly applies theme-based background coloring.


113-113: Consistent theming for title text

Applying themeColor to the title ensures that text color adheres to the selected theme.


127-127: Themed styling for description text

Using themeColor(description.color ?? "text-neutral-000") appropriately applies theming to the description text.


139-139: Proper use of themeColor for price amount

The price amount text uses themeColor("text-neutral-000"), maintaining consistency in theming.


143-145: Correct theming for price content

The ui-text-p3 class combined with themeColor("text-neutral-000") ensures the price content is styled according to the theme.


162-164: Themed styling for horizontal rule

The <hr> element correctly uses themeColor("border-neutral-800") for theming the border color.


172-172: Appropriate theming for section titles

Applying themeColor("text-neutral-500") to section titles ensures they align with the overall theme.


186-186: Consistent text styling in list items

The usage of ui-text-p3 and conditional font weights aligns with design standards.


197-200: Ensure listItemColors are defined before use

When using listItemColors to set color and secondaryColor, ensure that listItemColors is defined to prevent potential runtime errors.

As listItemColors is conditionally rendered, this check might already be in place, but double-checking can prevent issues.


206-206: Themed text styling for item descriptions

Applying conditional classes based on listItemColors and using themeColor("text-neutral-300") ensures consistent theming.

src/core/styles/colors/Colors.stories.tsx (3)

4-4: Importing useTheming hook

The useTheming hook is correctly imported from "../../hooks/useTheming".


109-112: Verify the baseTheme and theme parameter values

In the useTheming hook, baseTheme is set to "dark" and theme is set to "light". Please verify if this is intentional. Typically, baseTheme represents the default or current theme, and theme represents the target or new theme.


116-121: Ensure consistent color mapping in theming

In line 116, you use {colorSet(["orange-300"], "bg-orange-300")}, displaying orange-300 with its background color. In line 120, you use {colorSet(["orange-900"], themeColor("bg-orange-300"))}. Please verify whether ["orange-900"] should correspond with themeColor("bg-orange-900") instead of themeColor("bg-orange-300"), to maintain consistency between the color name and the themed background class.

src/core/hooks/useTheming.tsx Show resolved Hide resolved
src/core/styles/colors/utils.ts Outdated Show resolved Hide resolved
src/core/styles/colors/utils.ts Outdated Show resolved Hide resolved
scripts/compute-colors.ts Show resolved Hide resolved
scripts/compute-colors.ts Outdated Show resolved Hide resolved
scripts/compute-colors.ts Outdated Show resolved Hide resolved
scripts/compute-colors.ts Show resolved Hide resolved
src/core/ProductTile.tsx Show resolved Hide resolved
src/core/ProductTile.tsx Show resolved Hide resolved
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: 9

🧹 Outside diff range and nitpick comments (6)
src/core/hooks/useTheming.tsx (1)

10-23: LGTM: Hook implementation is efficient and clear.

The useTheming hook is well-implemented, using useCallback for performance optimization and providing a clear, focused API. The logic for determining theme color is concise and effective.

Consider adding a type annotation for the return value of the hook for improved type safety and documentation:

const useTheming = ({
  baseTheme = "dark",
  theme = "dark",
}: UseThemingProps): { themeColor: (color: ColorClass) => ColorClass } => {
  // ... existing implementation ...
};
src/core/Icon/EncapsulatedIcon.tsx (2)

21-24: LGTM with a suggestion: Consider making baseTheme configurable.

The implementation of useTheming hook looks good and aligns with the PR objectives. However, consider making the baseTheme configurable instead of hardcoding it to "dark". This would increase the component's flexibility for different use cases.

- baseTheme: "dark",
+ baseTheme: theme === "light" ? "light" : "dark",

This change would allow the component to adapt to both light and dark base themes more dynamically.


32-32: LGTM with a readability suggestion.

The use of themeColor function and conditional gradient direction look good. These changes align with the PR objectives of reducing generated Tailwind classes and enhancing theming capabilities.

To improve readability, consider extracting the className into a separate variable:

const outerClassName = `p-1 rounded-lg ${
  theme === "light" ? "bg-gradient-to-t" : "bg-gradient-to-b"
} ${themeColor("from-neutral-900")} ${className ?? ""}`;

return (
  <div
    className={outerClassName}
    style={{ width: numericalSize, height: numericalSize }}
  >
    {/* ... */}
  </div>
);

This change would make the JSX more readable and easier to maintain.

src/core/Tooltip.tsx (2)

169-169: LGTM: Icon color prop updated to use new theming approach.

The Icon color prop has been correctly updated to use the themeColor function from the useTheming hook. This change is consistent with the new theming approach introduced in this PR.

Minor suggestion: The template literal might be unnecessary for a single expression. Consider simplifying it to:

color={themeColor("text-neutral-800")}

190-193: LGTM: Tooltip className updated to use new theming approach. Consider improving readability.

The tooltip's className has been correctly updated to use the themeColor function for background and text colors, which is consistent with the new theming approach.

However, the current implementation might be hard to read due to the long line and multiple embedded expressions. Consider refactoring for improved readability:

className={`
  ${themeColor("bg-neutral-1000")}
  ${themeColor("text-neutral-200")}
  ui-text-p3 font-medium p-16
  ${interactive ? "" : "pointer-events-none"}
  rounded-lg absolute
  ${tooltipProps?.className ?? ""}
  ${fadeOut
    ? "animate-[tooltipExit_0.25s_ease-in-out]"
    : "animate-[tooltipEntry_0.25s_ease-in-out]"
  }
`}

This approach separates each class or condition onto its own line, making it easier to read and maintain.

scripts/compute-colors.ts (1)

62-69: Include Error Object in Catch Block for Detailed Logging

In the catch block, the error object is not captured, which limits the usefulness of the error message. By including the error parameter, you provide more context, making it easier to debug issues when they occur.

Apply this diff to include the error object:

try {
  fs.writeFileSync(outputPath, JSON.stringify(flippedMatches));
  console.log(
    `🎨 Tailwind theme classes have been computed and written to JSON files.`,
  );
- } catch {
-   console.error(`Error persisting computed colors.`);
+ } catch (error) {
+   console.error(`Error persisting computed colors:`, error);
  }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between d3ece16 and b49dd8c.

📒 Files selected for processing (10)
  • .gitignore (1 hunks)
  • package.json (1 hunks)
  • scripts/compute-colors.ts (1 hunks)
  • src/core/Icon/EncapsulatedIcon.tsx (2 hunks)
  • src/core/Pricing/PricingCards.tsx (11 hunks)
  • src/core/ProductTile.tsx (4 hunks)
  • src/core/Tooltip.tsx (4 hunks)
  • src/core/hooks/useTheming.tsx (1 hunks)
  • src/core/styles/colors/Colors.stories.tsx (2 hunks)
  • src/core/styles/colors/utils.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • .gitignore
  • package.json
🧰 Additional context used
🔇 Additional comments (33)
src/core/hooks/useTheming.tsx (4)

1-3: LGTM: Imports are appropriate and well-organized.

The imports are relevant to the hook's functionality, utilizing React's useCallback for optimization and local type definitions and utility functions for better code organization.


5-8: LGTM: Type definition is clear and flexible.

The UseThemingProps type is well-defined, with optional properties allowing for flexible usage of the hook. The use of the custom Theme type promotes type safety.


25-25: LGTM: Export statement is appropriate.

The default export of the useTheming hook follows common practices and is suitable for a single hook in the file.


1-25: Great implementation of the useTheming hook!

This new file introduces a well-structured and efficient useTheming hook that aligns perfectly with the PR objectives. The implementation is clean, well-typed, and follows React best practices. By centralizing theme-based color logic, this hook should effectively help reduce generated Tailwind classes across the application.

The hook provides a simple and flexible API for theme-based color manipulation, which should make it easy to integrate into existing components. Great job on improving the theming capabilities of the application!

src/core/Icon/EncapsulatedIcon.tsx (3)

3-3: LGTM: Import changes align with PR objectives.

The addition of the useTheming hook import and removal of determineThemeColor are consistent with the PR's goal of enhancing theming capabilities.


36-36: LGTM: Consistent use of themeColor function.

The update to use the themeColor function in the inner div's className is consistent with the new theming approach and aligns with the PR objectives of reducing generated Tailwind classes.


Line range hint 1-46: Overall assessment: Changes successfully implement new theming approach.

The modifications to EncapsulatedIcon.tsx effectively implement the new theming approach using the useTheming hook. These changes align well with the PR objectives of adding the useTheming hook and reducing generated Tailwind classes.

Key points:

  1. Successful integration of the useTheming hook.
  2. Consistent use of the themeColor function throughout the component.
  3. Reduction in hardcoded color classes, potentially optimizing Tailwind class generation.

The suggestions provided for making the baseTheme configurable and improving readability are minor and optional improvements. Overall, the implementation achieves its goals and enhances the component's theming capabilities.

src/core/Tooltip.tsx (3)

14-14: LGTM: Importing useTheming hook aligns with PR objectives.

The addition of the useTheming hook and removal of the determineThemeColor utility function aligns well with the PR objective of adding a new theming hook and reducing generated Tailwind classes. This change centralizes the theming logic, potentially making it easier to manage and update theme-related functionality across the application.


Line range hint 1-203: Overall, great job on implementing the useTheming hook!

The changes in this file effectively implement the new useTheming hook, replacing the previous determineThemeColor function. This aligns well with the PR objectives of adding a new theming hook and potentially reducing generated Tailwind classes.

The theming logic is now more centralized and consistently applied throughout the component, which should improve maintainability and flexibility in theme management. The minor suggestions provided in the review comments can further enhance code readability and optimization.

Great work on improving the theming system in the Tooltip component!


41-44: LGTM: useTheming hook implementation looks good.

The implementation of the useTheming hook is correct and aligns with the PR objectives. It replaces the previous determineThemeColor function, potentially providing more flexibility in theme management.

However, please verify if setting the baseTheme to "light" is intentional, as it might affect the default appearance of the tooltip.

To ensure consistency across the codebase, let's check if "light" is used as the baseTheme in other components:

✅ Verification successful

LGTM: useTheming hook implementation looks good.

The implementation of the useTheming hook is correct and aligns with the PR objectives. It replaces the previous determineThemeColor function, potentially providing more flexibility in theme management.

No other components are using baseTheme set to "light", ensuring that this configuration is specific to the tooltip component and maintains the intended default appearance.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for useTheming hook usage with baseTheme set to "light"
rg --type typescript --type tsx 'useTheming.*baseTheme:\s*"light"'

Length of output: 103


Script:

#!/bin/bash
# Search for useTheming hook usage with baseTheme set to "light"
rg --type ts --type tsx 'useTheming.*baseTheme:\s*"light"'

Length of output: 88


Script:

#!/bin/bash
# Search for useTheming hook usage with baseTheme set to "light" using glob patterns
rg 'useTheming.*baseTheme:\s*"light"' --glob '*.ts' --glob '*.tsx'

Length of output: 68

src/core/styles/colors/utils.ts (2)

1-10: Imports are correct and necessary

All imported color arrays and the ColorClass type are appropriately used in the code.


15-23: Extents mapping is accurately defined

The extents constant correctly maps each color to the length of its corresponding color array.

src/core/ProductTile.tsx (2)

5-5: Import of useTheming is appropriate

The useTheming hook is correctly imported from ./hooks/useTheming.


22-25: Proper implementation of useTheming hook

The usage of useTheming to obtain themeColor with the specified baseTheme and dynamic theme based on the selected prop is appropriate and enhances theming capabilities.

src/core/styles/colors/Colors.stories.tsx (1)

116-121: Verify color consistency in theming examples.

In the theming examples, you are using `"orange-300"` in the first `colorSet` and `"orange-900"` in the second. Given that you're applying `themeColor("bg-orange-300")` to the second one, please verify if both should be using the same color to demonstrate the theming effect on the same base color.

src/core/Pricing/PricingCards.tsx (18)

9-9: Import useTheming Hook

The useTheming hook is correctly imported from "../hooks/useTheming".


48-51: Initialize themeColor with useTheming

The useTheming hook is properly used to initialize themeColor, with baseTheme set to "dark" and theme passed as a prop.


62-62: Update Icon Component with themeColor

The themeColor function is correctly used to apply the text-neutral-500 color to the additionalCSS prop of the Icon component.


95-95: Apply themeColor to Card Container

The themeColor function is appropriately used to determine the border color class based on the border prop in the card container's className.


105-105: Set Background Color with themeColor

The themeColor function is correctly applied to set background color classes in the className, enhancing theming consistency.


113-113: Apply themeColor to Title Text

The themeColor function is properly used to set the text color of the title, ensuring it adapts to the current theme.


127-127: Apply themeColor to Description Text

The themeColor function is correctly applied to set the text color of the description, maintaining theming consistency.


139-139: Set Price Amount Text Color with themeColor

The themeColor function is appropriately used to apply the text-neutral-000 color to the price amount text.


143-145: Apply themeColor to Price Content

The themeColor function is correctly used to set the text color of the price content within the <div> element.


152-152: Update FeaturedLink Styling with themeColor

The themeColor function is properly applied to set the background and text colors in the additionalCSS prop of the FeaturedLink component.


162-164: Apply themeColor to Horizontal Rule

The themeColor function is correctly used to set the border color of the <hr> element, ensuring theme consistency.


172-172: Set Section Title Color with themeColor

The themeColor function is appropriately applied to set the text color of section titles, enhancing theming.


181-181: Apply themeColor to Item Container Background

The themeColor function is correctly used to set the background color for alternating items in the item container.


186-186: Set Item Text Color with themeColor

The themeColor function is properly applied to the item text, ensuring consistent theming across items.


206-206: Apply themeColor to Item Description Text

The themeColor function is correctly used to set the text color of the item descriptions, maintaining consistency with the theme.


218-218: Update FeaturedLink Styling with themeColor

The themeColor function is appropriately applied in the additionalCSS prop to set text colors for the FeaturedLink component.


220-220: Safely Access listItemColors.foreground with Optional Chaining

The use of optional chaining listItemColors?.foreground ensures that if listItemColors is undefined, it defaults to "text-white", preventing potential errors.


227-227: Set Placeholder Text Color with themeColor

The themeColor function is correctly applied to set the text color of the placeholder text, ensuring it aligns with the current theme.

src/core/styles/colors/utils.ts Outdated Show resolved Hide resolved
scripts/compute-colors.ts Outdated Show resolved Hide resolved
scripts/compute-colors.ts Outdated Show resolved Hide resolved
src/core/ProductTile.tsx Show resolved Hide resolved
src/core/ProductTile.tsx Show resolved Hide resolved
src/core/ProductTile.tsx Show resolved Hide resolved
src/core/styles/colors/Colors.stories.tsx Outdated Show resolved Hide resolved
src/core/Pricing/PricingCards.tsx Show resolved Hide resolved
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: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b49dd8c and 87df035.

📒 Files selected for processing (1)
  • scripts/compute-colors.ts (1 hunks)
🧰 Additional context used
📓 Learnings (1)
scripts/compute-colors.ts (2)
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: scripts/compute-colors.ts:40-42
Timestamp: 2024-10-14T14:51:08.699Z
Learning: In `scripts/compute-colors.ts`, when constructing the regex pattern to match `themeColor` usages, the missing separators between `joinedVariants` and `joinedPrefixes` are intentional.
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: scripts/compute-colors.ts:37-37
Timestamp: 2024-10-14T14:50:06.863Z
Learning: In `scripts/compute-colors.ts`, when searching for `themeColor` usages, only `.tsx` files need to be processed; there is no need to include other file types such as `.ts`, `.jsx`, or `.js`.
🔇 Additional comments (5)
scripts/compute-colors.ts (5)

1-14: LGTM: Import statements and constant declarations

The import statements and constant declarations look good. The introduction of invertTailwindClassVariant and the definition of directory and output paths are appropriate for the script's purpose.


56-60: LGTM: Main script execution

The main script execution looks good. It correctly calls findStringInFiles with the directory path and applies invertTailwindClassVariant to each match, which aligns with the script's purpose of computing and inverting theme color classes.


62-72: LGTM: File writing logic with proper error handling

The file writing logic looks good. It includes appropriate error handling for the file writing operation and creates the output directory if it doesn't exist. The inclusion of the error object in the catch block's console.error message is a good practice for debugging.


1-72: Overall assessment: Significant refactor with good improvements

The script has undergone a substantial refactor, shifting its focus to finding and processing theme color strings in .tsx files. The new implementation introduces useful utility functions and leverages existing color utilities effectively. Key improvements include:

  1. Introduction of the findStringInFiles function for recursive file searching.
  2. Use of invertTailwindClassVariant for color processing.
  3. Improved error handling in the file writing logic.

While the overall structure and purpose of the script have changed, the implementation is logical and aligned with the new requirements. To further enhance the script, consider:

  1. Centralizing color definitions for better maintainability.
  2. Adding more comprehensive error handling, especially in file system operations.

These suggestions aside, the refactored script appears to be a solid improvement that should effectively serve its new purpose.


15-23: 🛠️ Refactor suggestion

Consider importing colors from a central configuration

The colors array is currently hardcoded within the script. To enhance maintainability and ensure consistency across the codebase, consider importing color definitions from a central configuration or constants file.

scripts/compute-colors.ts Outdated Show resolved Hide resolved
@jamiehenson jamiehenson force-pushed the reduce-tw-class-generation branch from 87df035 to a105c03 Compare October 14, 2024 15:17
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: 3

🧹 Outside diff range and nitpick comments (8)
src/core/styles/colors/utils.ts (1)

8-10: Enhance input validation for robustness.

While the current check ensures the class name has at least 3 parts, consider adding more comprehensive validation:

  1. Check if color exists in ColorClassColorGroups.
  2. Validate that variant is a valid number followed by "00".

Example:

if (splitMatch.length < 3 || !(color in colorGroupLengths) || !/^\d+00$/.test(variant)) {
  throw new Error(`Invalid className format: ${className}`);
}

This will catch more potential errors early and provide more informative error messages.

src/core/Icon/EncapsulatedIcon.tsx (1)

32-32: LGTM: Updated class names with themeColor function.

The class names have been successfully updated to use the themeColor function, which aligns with the PR objective of reducing generated Tailwind classes and implementing the new theming approach.

Suggestion for improvement:
Consider extracting the complex class name logic into a separate function to enhance readability. For example:

const getOuterDivClassName = (theme: Theme, themeColor: Function, className?: string) => {
  return `p-1 rounded-lg ${theme === "light" ? "bg-gradient-to-t" : "bg-gradient-to-b"} ${themeColor("from-neutral-900")} ${className ?? ""}`;
};

const getInnerDivClassName = (themeColor: Function, innerClassName?: string) => {
  return `flex items-center justify-center rounded-lg ${themeColor("bg-neutral-1100")} ${innerClassName ?? ""}`;
};

Then use these functions in your JSX:

<div
  className={getOuterDivClassName(theme, themeColor, className)}
  style={{ width: numericalSize, height: numericalSize }}
>
  <div
    className={getInnerDivClassName(themeColor, innerClassName)}
    style={{ height: numericalSize - 2 }}
  >
    {/* ... */}
  </div>
</div>

This approach would make the component more readable and easier to maintain.

Also applies to: 36-36

src/core/ProductTile.tsx (5)

22-25: LGTM: Proper usage of useTheming hook.

The implementation of the useTheming hook is correct and aligns well with the component's theming needs. The dynamic theme selection based on the selected prop is a good approach for conditional theming.

Consider destructuring the selected prop in the component parameters for improved readability:

const ProductTile = ({
  name,
  selected,
  currentPage,
  className,
  onClick,
}: ProductTileProps) => {
  const { themeColor } = useTheming({
    baseTheme: "dark",
    theme: selected ? "light" : "dark",
  });
  // ...
};

This minor change would make the code slightly more concise and easier to follow.


30-30: Consider refactoring the className for improved readability.

The update to use themeColor is correct and aligns with the new theming approach. However, the className string is becoming complex. Consider refactoring it for improved readability:

const containerClasses = [
  'rounded-lg p-12 flex flex-col gap-8 transition-colors',
  themeColor("bg-neutral-1200"),
  selected ? '' : 'hover:bg-neutral-1100',
  className
].filter(Boolean).join(' ');

return (
  <div
    className={containerClasses}
    onClick={onClick}
  >
    {/* ... */}
  </div>
);

This approach separates the class logic from the JSX, making it easier to read and maintain.


41-41: Consider refactoring the className for improved readability.

The update to use themeColor is correct and aligns with the new theming approach. However, the className string is becoming complex. Consider refactoring it for improved readability:

const paragraphClasses = [
  unavailable ? 'ui-text-p2' : 'ui-text-p3',
  themeColor("text-neutral-300"),
  'font-medium'
].join(' ');

return (
  <p className={paragraphClasses}>
    Ably{" "}
  </p>
);

This approach separates the class logic from the JSX, making it easier to read and maintain.


46-46: Consider refactoring the className for improved readability.

The update to use themeColor is correct and aligns with the new theming approach. However, the className string is becoming complex. Consider refactoring it for improved readability:

const labelClasses = [
  'ui-text-p2',
  themeColor("text-neutral-000"),
  'font-bold',
  unavailable ? '' : 'mt-[-3px]'
].filter(Boolean).join(' ');

return (
  <p className={labelClasses}>
    {label}
  </p>
);

This approach separates the class logic from the JSX, making it easier to read and maintain.


66-66: Consider refactoring the additionalCSS prop for improved readability.

The update to use themeColor is correct and aligns with the new theming approach. However, the additionalCSS string is quite long. Consider refactoring it for improved readability:

const featuredLinkClasses = [
  'ui-btn-secondary bg-transparent hover:bg-transparent',
  'w-full hover:text-neutral-1300 mt-8 text-center inline-block',
  themeColor("text-neutral-000")
].join(' ');

return (
  <FeaturedLink
    additionalCSS={featuredLinkClasses}
    iconColor="text-orange-600"
    url={link}
  >
    {currentPage ? "View docs" : "Explore"}
  </FeaturedLink>
);

This approach separates the class logic from the JSX, making it easier to read and maintain.

src/core/styles/colors/types.ts (1)

Line range hint 1-194: Overall feedback: Improved color management with minor adjustments needed.

The changes in this file generally improve the color management system by introducing more structured and type-safe approaches. The new colors constant, ColorClassColorGroups type, and colorGroupLengths object enhance the organization and usability of color-related code.

However, there are a few points that need attention:

  1. Clarify the rationale behind removing secondary and aliased colors from colorRoles.
  2. Address the potential inconsistency in how color group lengths are derived for different color groups.

Once these points are addressed, the changes will significantly enhance the color management system in the codebase.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 87df035 and a105c03.

📒 Files selected for processing (11)
  • .gitignore (1 hunks)
  • package.json (1 hunks)
  • scripts/compute-colors.ts (1 hunks)
  • src/core/Icon/EncapsulatedIcon.tsx (2 hunks)
  • src/core/Pricing/PricingCards.tsx (11 hunks)
  • src/core/ProductTile.tsx (4 hunks)
  • src/core/Tooltip.tsx (4 hunks)
  • src/core/hooks/useTheming.tsx (1 hunks)
  • src/core/styles/colors/Colors.stories.tsx (6 hunks)
  • src/core/styles/colors/types.ts (2 hunks)
  • src/core/styles/colors/utils.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • .gitignore
  • package.json
  • src/core/Pricing/PricingCards.tsx
  • src/core/Tooltip.tsx
  • src/core/hooks/useTheming.tsx
🧰 Additional context used
📓 Learnings (3)
scripts/compute-colors.ts (2)
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: scripts/compute-colors.ts:37-37
Timestamp: 2024-10-14T14:50:06.863Z
Learning: In `scripts/compute-colors.ts`, when searching for `themeColor` usages, only `.tsx` files need to be processed; there is no need to include other file types such as `.ts`, `.jsx`, or `.js`.
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: scripts/compute-colors.ts:40-42
Timestamp: 2024-10-14T14:51:08.699Z
Learning: In `scripts/compute-colors.ts`, when constructing the regex pattern to match `themeColor` usages, the missing separators between `joinedVariants` and `joinedPrefixes` are intentional.
src/core/ProductTile.tsx (1)
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: src/core/ProductTile.tsx:30-30
Timestamp: 2024-10-14T15:13:43.163Z
Learning: In `src/core/ProductTile.tsx`, prefer not to use utility libraries like `clsx` for conditional class names.
src/core/styles/colors/types.ts (2)
Learnt from: jamiehenson
PR: ably/ably-ui#486
File: src/core/styles/colors/types.ts:8-15
Timestamp: 2024-09-18T14:08:15.229Z
Learning: When updating `ColorClassVariants` and `ColorClassPrefixes`, only include variants and prefixes that relate to colour classes.
Learnt from: jamiehenson
PR: ably/ably-ui#486
File: src/core/styles/colors/types.ts:8-15
Timestamp: 2024-10-08T15:37:26.766Z
Learning: When updating `ColorClassVariants` and `ColorClassPrefixes`, only include variants and prefixes that relate to colour classes.
🔇 Additional comments (23)
src/core/styles/colors/utils.ts (3)

1-1: LGTM: Import changes align with function modifications.

The updated imports correctly reflect the changes in the file's functionality, removing unused imports and adding necessary types and constants for the new invertTailwindClassVariant function.


16-19: Please clarify the neutral color adjustment.

The calculation of flippedVariant includes a special case for the "neutral" color:

(color === "neutral" ? 1 : -1)

Could you provide a comment explaining why this adjustment is necessary for neutral colors? This would improve the code's maintainability and help future developers understand the logic behind this special case.


6-22: LGTM: Well-implemented function with minor suggestions.

The invertTailwindClassVariant function is well-structured and correctly implements the inversion of Tailwind CSS color variants. It handles the parsing of class names, calculates the flipped variant, and constructs the new class name effectively.

Consider the following minor improvements:

  1. Add more comprehensive input validation as suggested earlier.
  2. Use a more robust approach for parsing the variant number.
  3. Add a comment explaining the neutral color adjustment.
  4. Consider adding unit tests to verify the function's behavior with various inputs.

Overall, good job on implementing this new functionality!

src/core/Icon/EncapsulatedIcon.tsx (3)

3-3: LGTM: Import statement for useTheming hook.

The import statement for the useTheming hook is correctly implemented. This change aligns with the PR objective of adding the useTheming hook and reducing generated Tailwind classes.


Line range hint 1-46: Summary: Successful implementation of useTheming hook with minor suggestions for improvement

The changes in this file successfully implement the useTheming hook and update the class names to use the new theming approach. This aligns well with the PR objectives of adding the useTheming hook and reducing generated Tailwind classes.

Key points:

  1. The useTheming hook is correctly imported and implemented.
  2. Class names are updated to use the themeColor function from the hook.
  3. The changes contribute to more dynamic and efficient theming.

Suggestions for further improvement:

  1. Consider the implications of setting baseTheme: "dark" in the useTheming hook call.
  2. Extract complex class name logic into separate functions for better readability and maintainability.

Overall, the changes are approved with minor suggestions for refinement.


21-24: LGTM: useTheming hook implementation with a minor consideration.

The useTheming hook is correctly implemented and used. It aligns with the PR objective of adding the hook for theming purposes.

However, consider the implications of setting baseTheme: "dark":

  • This might affect the default behavior of the component.
  • Ensure this aligns with the intended design system and doesn't introduce unexpected behavior for light themes.

To verify the impact of this change, let's check for other usages of useTheming in the codebase:

✅ Verification successful

Action Required: Corrected command to locate other useTheming usages.

To accurately identify all instances of the useTheming hook within TypeScript files, please run the following script:


LGTM: useTheming hook implementation confirmed as consistent.

The useTheming hook is correctly implemented and consistently used across the codebase. Setting baseTheme: "dark" aligns with other components, ensuring uniform theming behavior.

  • Verified that useTheming is utilized appropriately in multiple files with both dark and light base themes.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for other usages of useTheming hook
rg --type typescript 'useTheming\(' -C 3

Length of output: 77


Script:

#!/bin/bash
# Description: Check for other usages of useTheming hook in TypeScript files
rg 'useTheming\(' --glob '*.ts' --glob '*.tsx' -C 3

Length of output: 1951

src/core/ProductTile.tsx (2)

5-5: LGTM: Import changes align with the new theming approach.

The addition of the useTheming hook import and removal of the ColorClass and determineThemeColor imports reflect the shift towards using a custom hook for theming. This change aligns well with the PR objective of adding a useTheming hook and reducing generated TW classes.


Line range hint 1-79: Overall assessment: Good implementation of the new theming approach.

The changes in this file successfully implement the new useTheming hook and consistently apply the new theming approach throughout the ProductTile component. This aligns well with the PR objectives of adding a useTheming hook and reducing generated TW classes.

Key points:

  1. The import statements have been updated correctly.
  2. The useTheming hook is properly implemented and used.
  3. All instances of theme-related class names now use the themeColor function.

While the changes are functionally correct, there are opportunities to improve code readability, particularly in the construction of class name strings. Consider implementing the suggested refactors to enhance maintainability.

Great job on implementing the new theming system!

scripts/compute-colors.ts (6)

3-4: LGTM: Import statements are correct

The new import for invertTailwindClassVariant is appropriate for the changes in the file's functionality. The existing import for prefixes and variants is maintained.


6-11: LGTM: Path definitions are well-structured

The directoryPath and outputPath are correctly defined using path.join, ensuring cross-platform compatibility. The output path is appropriately set within the project structure.


25-71: LGTM: Well-structured function with proper error handling

The findStringInFiles function is well-implemented with:

  • Recursive directory traversal
  • Proper error handling for file system operations
  • Correct file type filtering (.tsx files only)

The overall structure and error handling approach are commendable.


74-77: LGTM: Efficient processing of matches

The code efficiently processes the matches found by findStringInFiles:

  1. It calls the function with the correct directoryPath.
  2. It then maps the results using invertTailwindClassVariant, which aligns with the purpose of this script.

This approach is concise and effective.


80-88: LGTM: Robust file writing with proper checks

This section demonstrates good practices:

  1. It checks and creates the output directory if it doesn't exist.
  2. It writes the processed matches to the JSON file.
  3. It provides an informative success message.

The implementation ensures that the file writing process is robust and user-friendly.


89-91: LGTM: Appropriate error handling

The error handling for the file writing process is well-implemented:

  • It catches any potential errors during the operation.
  • It logs the error with details, which is crucial for debugging.

This approach is consistent with the error handling used throughout the file and provides valuable information in case of failures.

src/core/styles/colors/types.ts (2)

22-32: LGTM! Improved color group management.

The introduction of the colors constant and the ColorClassColorGroups type is a positive change. It centralizes the definition of color group names and provides type safety for their usage throughout the codebase. This addition aligns well with the existing color definitions and enhances the overall type system for colors.


179-185: Approve renaming, but clarify color removals.

The renaming of colorNames to colorRoles is a good change that better reflects the purpose of these color groups in the UI. However, the removal of secondary and aliased colors from colorRoles requires clarification:

  1. What is the rationale behind removing these color groups?
  2. Are there any potential impacts on existing code that might rely on these color groups?
  3. If these colors are still needed, where are they being managed now?

Please provide some context on these changes to ensure they align with the overall color management strategy.

src/core/styles/colors/Colors.stories.tsx (7)

2-4: Updated imports to reflect new theming system

The import statements correctly include colorRoles and useTheming, aligning with the updated theming approach.


50-50: Updated 'NeutralColors' to use 'colorRoles.neutral'

The NeutralColors component now utilizes colorRoles.neutral to render the color set, ensuring consistency with the new color roles structure.


65-65: Updated 'OrangeColors' to use 'colorRoles.orange'

The OrangeColors component now utilizes colorRoles.orange for rendering, reflecting the updated color role definitions.


80-80: Updated 'SecondaryColors' to use 'colorRoles.secondary'

The SecondaryColors component correctly uses colorRoles.secondary, maintaining consistency with the updated theming system.


94-94: Updated 'GUIColors' to use 'colorRoles.gui'

The GUIColors component now references colorRoles.gui, aligning with the new color roles configuration.


107-124: Implemented theming in 'DynamicTheming' component using useTheming

The DynamicTheming component correctly implements the useTheming hook and utilizes the themeColor function to dynamically adjust color classes based on the theme context.


129-129: Updated documentation to reflect new theming approach

The story description accurately explains the usage of the useTheming hook and themeColor function for generating alternative colors based on theme differences.

src/core/styles/colors/utils.ts Show resolved Hide resolved
scripts/compute-colors.ts Outdated Show resolved Hide resolved
src/core/styles/colors/types.ts Show resolved Hide resolved
@jamiehenson jamiehenson force-pushed the reduce-tw-class-generation branch from a105c03 to 1133a22 Compare October 14, 2024 15:26
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: 1

🧹 Outside diff range and nitpick comments (11)
src/core/styles/colors/utils.ts (2)

6-11: Enhance error message for invalid class format.

The error handling for invalid class format is a good practice. However, consider making the error message more descriptive to aid in debugging.

Suggest updating the error message as follows:

- throw new Error("Invalid TW class format");
+ throw new Error(`Invalid Tailwind class format: ${className}`);

This change will provide more context about which class caused the error.


12-27: Approve implementation with suggestions for improvement.

The overall implementation of invertTailwindClassVariant is well-structured and includes good error handling. Here are some suggestions for further improvement:

  1. The function assumes all variants end with "00", which might not always be true in Tailwind CSS (e.g., "50" variants). Consider making this more robust:
const numericalVariant = parseInt(variant.replace(/00$/, ''), 10);
  1. Enhance the error message for invalid variant values:
- throw new Error(`Invalid variant value in TW class: ${className}`);
+ throw new Error(`Invalid variant value '${variant}' in Tailwind class: ${className}`);
  1. Consider adding a check to ensure the color exists in colorGroupLengths:
if (!(color in colorGroupLengths)) {
  throw new Error(`Unknown color '${color}' in Tailwind class: ${className}`);
}

These changes will make the function more robust and provide more helpful error messages.

🧰 Tools
🪛 Biome

[error] 17-17: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.

(lint/suspicious/noGlobalIsNan)

src/core/ProductTile.tsx (4)

22-25: Approved: Dynamic theming with useTheming hook

The implementation of the useTheming hook provides a more flexible and centralized approach to theme management. It correctly uses the selected prop to determine the appropriate theme.

Consider destructuring the selected prop at the top of the component for improved readability:

const ProductTile = ({
  name,
  selected,
  currentPage,
  className,
  onClick,
}: ProductTileProps) => {
+  const { selected } = props;
  const { themeColor } = useTheming({
    baseTheme: "dark",
    theme: selected ? "light" : "dark",
  });
  // ...

30-30: Improve className structure while maintaining new theming approach

The use of themeColor function for applying the background color is correct and aligns with the new theming approach. However, the string concatenation for className could be improved for better readability and maintainability.

Consider using template literals for better readability:

-      className={`rounded-lg p-12 flex flex-col gap-8 transition-colors ${themeColor("bg-neutral-1200")} ${selected ? "" : "hover:bg-neutral-1100"} ${className ?? ""}`}
+      className={`
+        rounded-lg p-12 flex flex-col gap-8 transition-colors
+        ${themeColor("bg-neutral-1200")}
+        ${selected ? "" : "hover:bg-neutral-1100"}
+        ${className ?? ""}
+      `}

This change improves readability while maintaining the functionality.


41-41: Improve className structure in paragraph elements

The use of themeColor function in both paragraph elements is correct and consistent with the new theming approach. However, the string concatenation for classNames could be improved for better readability and maintainability.

Consider using template literals for better readability in both paragraph elements:

For the first paragraph (line 41):

-            className={`${unavailable ? "ui-text-p2" : "ui-text-p3"} ${themeColor("text-neutral-300")} font-medium`}
+            className={`
+              ${unavailable ? "ui-text-p2" : "ui-text-p3"}
+              ${themeColor("text-neutral-300")}
+              font-medium
+            `}

For the second paragraph (line 46):

-            className={`ui-text-p2 ${themeColor("text-neutral-000")} font-bold ${unavailable ? "" : "mt-[-3px]"}`}
+            className={`
+              ui-text-p2
+              ${themeColor("text-neutral-000")}
+              font-bold
+              ${unavailable ? "" : "mt-[-3px]"}
+            `}

These changes improve readability while maintaining the functionality.

Also applies to: 46-46


66-66: Improve additionalCSS structure in FeaturedLink component

The use of themeColor function in the additionalCSS prop is correct and consistent with the new theming approach. However, the string concatenation could be improved for better readability and maintainability.

Consider using template literals for better readability:

-          additionalCSS={`ui-btn-secondary bg-transparent hover:bg-transparent w-full hover:text-neutral-1300 mt-8 text-center inline-block ${themeColor("text-neutral-000")}`}
+          additionalCSS={`
+            ui-btn-secondary bg-transparent hover:bg-transparent
+            w-full hover:text-neutral-1300 mt-8 text-center inline-block
+            ${themeColor("text-neutral-000")}
+          `}

This change improves readability while maintaining the functionality.

scripts/compute-colors.ts (1)

66-70: LGTM: Clear execution logic with a minor suggestion

The main execution logic is clear and concise. It correctly uses the findStringInFiles function and processes the results with invertTailwindClassVariant.

Consider adding a brief comment explaining the purpose of invertTailwindClassVariant for better code documentation. For example:

// Invert theme colors for dark/light mode compatibility
const flippedMatches = matches.map((match) =>
  invertTailwindClassVariant(match)
);
src/core/styles/colors/types.ts (1)

Line range hint 1-194: Reminder: Maintain color-related consistency

While the current changes don't directly modify ColorClassVariants or ColorClassPrefixes, it's important to keep in mind the previous learning:

When updating ColorClassVariants and ColorClassPrefixes, only include variants and prefixes that relate to colour classes.

This principle should be applied in future updates to this file to maintain consistency in color-related type definitions.

src/core/Pricing/PricingCards.tsx (3)

95-95: LGTM with a minor suggestion: Theming applied to border

The themeColor function is correctly used to apply the theme-based color to the border, and the nullish coalescing operator provides a good fallback. However, this line is quite long and might benefit from being split for better readability.

Consider refactoring like this for improved readability:

className={`
  relative border 
  ${themeColor(borderClasses(border?.color)?.border ?? "border-neutral-1100")} 
  ${border?.style ?? ""} 
  flex-1 px-24 py-32 flex flex-col gap-24 rounded-2xl group 
  ${delimiter ? "@[520px]:flex-row @[920px]:flex-col" : ""} 
  min-w-[272px] backdrop-blur
`}

This change would make the code easier to read and maintain without changing its functionality.


105-105: LGTM with a minor suggestion: Theming applied to background

The themeColor function is correctly used to apply the theme-based color to the background, and the conditional hover effects are maintained. However, this line is quite long and might benefit from being split for better readability.

Consider refactoring like this:

className={`
  absolute z-0 top-0 left-0 w-full h-full rounded-2xl 
  ${themeColor("bg-neutral-1300")} 
  ${!delimiter 
    ? `${themeColor("group-hover:bg-neutral-1200")} group-hover:opacity-100` 
    : ""
  } 
  transition-[colors,opacity] opacity-25
`}

This change would make the code easier to read and maintain without changing its functionality.


152-152: Theming applied to FeaturedLink, but improvements needed

The themeColor function is correctly used to apply theme-based colors to the background and text of the FeaturedLink. However, there are a few points to consider:

  1. The line is very long, making it hard to read and maintain.
  2. The hover state text color is hardcoded and not using themeColor.

Consider refactoring like this for improved readability and consistency:

additionalCSS={`
  text-center ui-btn 
  ${themeColor("bg-neutral-000")} 
  ${themeColor("text-neutral-1300")} 
  ${themeColor("hover:text-neutral-000")}
  px-24 !py-12 
  ${cta.className ?? ""} 
  cursor-pointer
`}

This change would make the code easier to read and maintain, and ensure consistent use of theming throughout, including in the hover state.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a105c03 and 1133a22.

📒 Files selected for processing (11)
  • .gitignore (1 hunks)
  • package.json (1 hunks)
  • scripts/compute-colors.ts (1 hunks)
  • src/core/Icon/EncapsulatedIcon.tsx (2 hunks)
  • src/core/Pricing/PricingCards.tsx (11 hunks)
  • src/core/ProductTile.tsx (4 hunks)
  • src/core/Tooltip.tsx (4 hunks)
  • src/core/hooks/useTheming.tsx (1 hunks)
  • src/core/styles/colors/Colors.stories.tsx (6 hunks)
  • src/core/styles/colors/types.ts (2 hunks)
  • src/core/styles/colors/utils.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • .gitignore
  • package.json
  • src/core/Icon/EncapsulatedIcon.tsx
  • src/core/Tooltip.tsx
  • src/core/hooks/useTheming.tsx
🧰 Additional context used
📓 Learnings (3)
scripts/compute-colors.ts (2)
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: scripts/compute-colors.ts:37-37
Timestamp: 2024-10-14T14:50:06.863Z
Learning: In `scripts/compute-colors.ts`, when searching for `themeColor` usages, only `.tsx` files need to be processed; there is no need to include other file types such as `.ts`, `.jsx`, or `.js`.
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: scripts/compute-colors.ts:40-42
Timestamp: 2024-10-14T14:51:08.699Z
Learning: In `scripts/compute-colors.ts`, when constructing the regex pattern to match `themeColor` usages, the missing separators between `joinedVariants` and `joinedPrefixes` are intentional.
src/core/ProductTile.tsx (1)
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: src/core/ProductTile.tsx:30-30
Timestamp: 2024-10-14T15:13:43.163Z
Learning: In `src/core/ProductTile.tsx`, prefer not to use utility libraries like `clsx` for conditional class names.
src/core/styles/colors/types.ts (2)
Learnt from: jamiehenson
PR: ably/ably-ui#486
File: src/core/styles/colors/types.ts:8-15
Timestamp: 2024-09-18T14:08:15.229Z
Learning: When updating `ColorClassVariants` and `ColorClassPrefixes`, only include variants and prefixes that relate to colour classes.
Learnt from: jamiehenson
PR: ably/ably-ui#486
File: src/core/styles/colors/types.ts:8-15
Timestamp: 2024-10-08T15:37:26.766Z
Learning: When updating `ColorClassVariants` and `ColorClassPrefixes`, only include variants and prefixes that relate to colour classes.
🪛 Biome
src/core/styles/colors/utils.ts

[error] 17-17: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.

(lint/suspicious/noGlobalIsNan)

🔇 Additional comments (24)
src/core/styles/colors/utils.ts (2)

1-5: LGTM: Import changes and existing function.

The updated imports reflect the changes in how color-related data is managed. The convertTailwindClassToVar function remains unchanged and continues to serve its purpose.


1-27: Summary: Alignment with PR objectives and overall improvements.

The changes in this file align well with the PR objectives of "[WEB-4025] Add useTheming hook, reduce generated TW classes". The removal of determineThemeColor and the addition of invertTailwindClassVariant contribute to the goal of dynamic theming and potentially reducing generated Tailwind classes.

The new invertTailwindClassVariant function provides a mechanism for inverting Tailwind color variants, which can be useful in implementing dynamic theming. The function includes error handling and complex logic to handle various Tailwind class formats.

While the implementation is generally solid, consider the suggested improvements to make the function more robust and error messages more informative. These enhancements will contribute to better maintainability and easier debugging in the future.

🧰 Tools
🪛 Biome

[error] 17-17: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.

(lint/suspicious/noGlobalIsNan)

src/core/ProductTile.tsx (2)

5-5: Approved: Shift to useTheming hook

The import of useTheming hook replaces the previous imports of ColorClass and determineThemeColor. This change aligns with the PR objective of adding a useTheming hook and potentially optimizing the theming approach.


Line range hint 1-78: Summary: Successful implementation of new theming approach

The changes in this file successfully implement the new theming approach using the useTheming hook. This aligns well with the PR objectives and provides more flexibility in theme management. The themeColor function is consistently used throughout the component, replacing the previous determineThemeColor utility.

Key improvements:

  1. Centralized theme management with useTheming hook
  2. Consistent application of themeColor function across the component
  3. Potential for reduced generated Tailwind classes (though this would need to be verified)

While the functionality is correct, there's room for improving the readability of className and additionalCSS structures, as suggested in the previous comments.

Overall, these changes represent a positive step towards more efficient and flexible theming in the component.

scripts/compute-colors.ts (4)

3-14: LGTM: Imports and constants are well-defined

The imports and constants are appropriately set up for the task. The use of path.join for directory paths ensures cross-platform compatibility, and joining arrays to create regex patterns is an efficient approach.


17-63: LGTM: Well-structured function with proper error handling

The findStringInFiles function is well-implemented with appropriate error handling for file system operations. It correctly processes only .tsx files as per the project requirements. The regex pattern construction aligns with the intentional design mentioned in the previous feedback.

I've taken into account the following learnings:

  1. Only .tsx files need to be processed when searching for themeColor usages.
  2. The missing separators in the regex pattern between joinedVariants and joinedPrefixes are intentional.

72-82: LGTM: Robust file writing logic with proper error handling

The file writing logic is well-implemented:

  • It ensures the output directory exists before writing the file, preventing potential errors.
  • Proper error handling is in place for the file writing operation.
  • A clear success message is logged upon completion, providing good feedback.

These improvements make the script more robust and user-friendly.


1-82: Overall: Significant improvement in robustness and maintainability

This rewrite of compute-colors.ts brings several notable improvements:

  1. Clear focus on finding and processing theme color strings in .tsx files.
  2. Robust error handling throughout the script, especially for file system operations.
  3. Improved maintainability with well-structured functions and constants.
  4. Better cross-platform compatibility using path.join for file paths.
  5. Efficient regex pattern construction for finding theme colors.

These changes result in a more reliable and maintainable script for computing theme colors. Great job on the refactoring!

src/core/styles/colors/types.ts (2)

22-32: LGTM: Improved color group management

The addition of the colors constant and ColorClassColorGroups type enhances the organization of color-related code. This change provides a centralized list of color group names and ensures type safety when referring to these groups throughout the codebase.


186-194: LGTM: Useful addition of colorGroupLengths

The colorGroupLengths constant is a valuable addition, providing easy access to the number of colors in each group. This can be beneficial for various color-related operations in the codebase.

The implementation is now consistent with the newly added colors constant, addressing the concern raised in the previous review comment. Each color group's length is derived from its respective color array, ensuring consistency across the color system.

src/core/styles/colors/Colors.stories.tsx (6)

2-2: LGTM: Import changes align with PR objectives.

The replacement of colorNames with colorRoles and the addition of the useTheming hook are consistent with the PR's goal of enhancing theming capabilities.

Also applies to: 4-4


50-50: LGTM: Consistent use of colorRoles.

The update to use colorRoles.neutral is consistent with the import changes and likely reflects a broader restructuring of color definitions.


65-65: LGTM: Consistent updates to color role usage.

The changes in OrangeColors and SecondaryColors stories to use colorRoles instead of colorNames are consistent with the previous modifications and import changes.

Also applies to: 80-80


94-94: LGTM: Consistent update to GUI colors.

The change in the GUIColors story to use colorRoles.gui is consistent with the previous modifications and maintains the overall pattern of updates in this file.


107-124: LGTM: Successful implementation of dynamic theming.

The changes in the DynamicTheming story effectively demonstrate the new theming approach:

  1. The useTheming hook is correctly implemented with baseTheme and theme parameters.
  2. The render method now uses the themeColor function to showcase dynamic color generation.
  3. The JSX structure has been updated to reflect these changes.

The documentation string has been updated to accurately describe the new approach, and the previously reported issue with the missing backtick has been resolved.

Also applies to: 129-129


Line range hint 1-129: Overall: Excellent implementation of new theming approach.

The changes in this file successfully achieve the PR objectives:

  1. Consistent replacement of colorNames with colorRoles across all color stories.
  2. Introduction and demonstration of the useTheming hook in the DynamicTheming story.
  3. Updated documentation to reflect the new theming approach.

These changes enhance the theming capabilities of the components while maintaining consistency throughout the file.

src/core/Pricing/PricingCards.tsx (8)

9-9: LGTM: New useTheming hook imported

The import of the useTheming hook is correctly placed and follows good practices for code organization.


Line range hint 19-19: LGTM: Default theme set to "dark"

Setting a default theme to "dark" is a good practice. It ensures that the component always has a valid theme, even if one is not explicitly provided.


48-51: LGTM: useTheming hook implemented correctly

The useTheming hook is well-implemented:

  • It's called with the correct parameters (baseTheme and theme).
  • The destructuring of themeColor from the hook's return value is clean and follows React best practices.
  • The "dark" baseTheme aligns with the default theme prop value.

This implementation provides a consistent way to manage theming throughout the component.


62-62: LGTM: Theming applied to delimiter icon

The themeColor function is correctly used to apply the theme-based color to the delimiter icon. This change ensures consistency with the new theming approach.


113-113: LGTM: Theming applied to title text

The themeColor function is correctly used to apply the theme-based color to the title text. The use of the nullish coalescing operator provides a good fallback, ensuring that a color is always applied. This change maintains consistency with the new theming approach.


127-127: LGTM: Theming applied to description text

The themeColor function is correctly used to apply the theme-based color to the description text. The use of the nullish coalescing operator provides a good fallback, ensuring that a color is always applied. This change maintains consistency with the new theming approach and preserves the existing styling classes.


139-139: LGTM: Theming applied to price amount

The themeColor function is correctly used to apply the theme-based color to the price amount text. This change ensures consistency with the new theming approach while maintaining the existing typography classes.


143-145: LGTM: Improved structure for price content with theming

The changes to the price content styling are well-implemented:

  1. The themeColor function is correctly used to apply the theme-based color.
  2. Moving the styling to a separate div element improves the structure and readability of the code.

These changes enhance the consistency of the theming approach and the overall code organization.

src/core/styles/colors/types.ts Show resolved Hide resolved
@jamiehenson jamiehenson force-pushed the reduce-tw-class-generation branch from 4a95c2b to 9aa44f5 Compare October 16, 2024 09:23
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: 1

🧹 Outside diff range and nitpick comments (4)
src/core/styles/colors/utils.ts (1)

8-10: Enhance error message for invalid class format.

The current error message could be more informative to aid in debugging.

Consider updating the error message to include the invalid class name:

-    throw new Error("Invalid TW class format");
+    throw new Error(`Invalid Tailwind class format: ${className}`);
src/core/Pricing/PricingCards.tsx (3)

100-100: Consider improving readability of long className

The usage of themeColor for the border class is correct and includes a good fallback. However, this line is quite long and might be hard to read. Consider splitting it into multiple lines for better readability.

Example:

className={`
  relative border
  ${themeColor(borderClasses(border?.color)?.border ?? "border-neutral-1100")}
  ${border?.style ?? ""}
  flex-1 px-24 py-32 flex flex-col gap-24 rounded-2xl group
  ${delimiter ? "@[520px]:flex-row @[920px]:flex-col" : ""}
  min-w-[272px] backdrop-blur
`}

147-147: Consider adding a fallback color for consistency

The themeColor function is correctly used to apply theming to the price text color. However, unlike previous usages, there's no fallback color provided here. Consider adding a fallback color for consistency with other themed elements.

Example:

className={`ui-text-title font-medium tracking-tight leading-none ${themeColor("text-neutral-000" ?? "text-neutral-000")}`}

151-153: Consider adding a fallback color for consistency

The themeColor function is correctly used to apply theming to the price content text color. However, similar to the previous instance, there's no fallback color provided. Consider adding a fallback color for consistency with other themed elements.

Example:

className={`ui-text-p3 ${themeColor("text-neutral-000" ?? "text-neutral-000")}`}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 4a95c2b and 9aa44f5.

📒 Files selected for processing (11)
  • .gitignore (1 hunks)
  • package.json (1 hunks)
  • scripts/compute-colors.ts (1 hunks)
  • src/core/Icon/EncapsulatedIcon.tsx (2 hunks)
  • src/core/Pricing/PricingCards.tsx (11 hunks)
  • src/core/ProductTile.tsx (4 hunks)
  • src/core/Tooltip.tsx (4 hunks)
  • src/core/hooks/useTheming.tsx (1 hunks)
  • src/core/styles/colors/Colors.stories.tsx (6 hunks)
  • src/core/styles/colors/types.ts (2 hunks)
  • src/core/styles/colors/utils.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • .gitignore
  • package.json
  • src/core/Icon/EncapsulatedIcon.tsx
  • src/core/ProductTile.tsx
  • src/core/Tooltip.tsx
  • src/core/hooks/useTheming.tsx
  • src/core/styles/colors/Colors.stories.tsx
  • src/core/styles/colors/types.ts
🧰 Additional context used
📓 Learnings (1)
scripts/compute-colors.ts (2)
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: scripts/compute-colors.ts:37-37
Timestamp: 2024-10-14T14:50:06.863Z
Learning: In `scripts/compute-colors.ts`, when searching for `themeColor` usages, only `.tsx` files need to be processed; there is no need to include other file types such as `.ts`, `.jsx`, or `.js`.
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: scripts/compute-colors.ts:40-42
Timestamp: 2024-10-14T14:51:08.699Z
Learning: In `scripts/compute-colors.ts`, when constructing the regex pattern to match `themeColor` usages, the missing separators between `joinedVariants` and `joinedPrefixes` are intentional.
🪛 Biome
src/core/styles/colors/utils.ts

[error] 17-17: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.

(lint/suspicious/noGlobalIsNan)

🔇 Additional comments (20)
src/core/styles/colors/utils.ts (3)

1-1: LGTM: Import changes align with PR objectives.

The updated imports reflect the shift from using computed colors to color group lengths, which aligns with the PR's goal of reducing generated Tailwind classes.


21-27: LGTM: Flipped variant calculation and class construction.

The logic for calculating the flipped variant and constructing the new class name looks correct and aligns with the PR objectives.


1-27: Summary: Changes align with PR objectives, with minor suggestions for improvement.

The modifications in this file, particularly the introduction of the invertTailwindClassVariant function, align well with the PR objectives of improving theming capabilities and reducing generated Tailwind classes. The function provides a standardized approach to inverting color variants, which should contribute to more efficient dynamic theming.

A few minor improvements have been suggested:

  1. Enhancing error messages for better debugging.
  2. Improving the robustness of variant parsing.
  3. Using safer NaN checking as per static analysis recommendations.

These changes, once implemented, will further improve the reliability and maintainability of the theming utilities.

To ensure that the new invertTailwindClassVariant function is being used correctly throughout the codebase, consider running the following verification script:

This script will help identify:

  1. Where the new function is being used.
  2. If there are any lingering uses of the old determineThemeColor function.
  3. Potential spots where invertTailwindClassVariant might be needed but not yet implemented.
✅ Verification successful

All concerns from the review have been successfully addressed:

  • The invertTailwindClassVariant function is actively used in scripts/compute-colors.ts and src/core/hooks/useTheming.tsx, ensuring it aligns with the PR objectives.
  • There are no remaining usages of the old determineThemeColor function, confirming its successful removal.

No issues were found in the codebase regarding the integration and usage of these functions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of invertTailwindClassVariant function

# Search for usage of invertTailwindClassVariant
echo "Searching for usage of invertTailwindClassVariant:"
rg --type typescript --type javascript "invertTailwindClassVariant\(" -C 3

# Check for any remaining usage of the old determineThemeColor function
echo "\nChecking for any remaining usage of determineThemeColor:"
rg --type typescript --type javascript "determineThemeColor\(" -C 3

# Look for potential places where invertTailwindClassVariant might be needed
echo "\nSearching for potential places where invertTailwindClassVariant might be needed:"
rg --type typescript --type javascript "(bg|text|from|to)-\w+-\d{3}" -C 3

Length of output: 740


Script:

#!/bin/bash
# Description: Verify the usage of invertTailwindClassVariant and determineThemeColor functions

# Search for usage of invertTailwindClassVariant in TypeScript and JavaScript files
echo "Searching for usage of invertTailwindClassVariant:"
rg "invertTailwindClassVariant\(" --glob "*.ts" --glob "*.tsx" -C 3

# Check for any remaining usage of the old determineThemeColor function in TypeScript and JavaScript files
echo "\nChecking for any remaining usage of determineThemeColor:"
rg "determineThemeColor\(" --glob "*.ts" --glob "*.tsx" -C 3

# Look for potential places where invertTailwindClassVariant might be needed by searching for Tailwind classes
echo "\nSearching for potential places where invertTailwindClassVariant might be needed:"
rg "(bg|text|from|to)-\w+-\d{3}" --glob "*.ts" --glob "*.tsx" -C 3

Length of output: 44331

🧰 Tools
🪛 Biome

[error] 17-17: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.

(lint/suspicious/noGlobalIsNan)

scripts/compute-colors.ts (8)

3-4: LGTM: Imports are appropriate for the script's functionality

The imports look good. The invertTailwindClassVariant function is imported from the utils file, which aligns with the new functionality. The color-related constants are imported from a centralized types file, promoting consistency across the codebase.


6-11: LGTM: Path definitions are clear and cross-platform compatible

The directoryPath and outputPath are well-defined using path.join, ensuring cross-platform compatibility. The output path correctly points to the computed-colors.json file in the appropriate directory.


13-15: LGTM: Joined constants improve maintainability

The joined constants for variants, prefixes, and colors are well-prepared for use in the regex pattern. This approach promotes maintainability by centralizing these values and making them easy to update if needed.


17-63: LGTM: findStringInFiles function is well-implemented

The findStringInFiles function is well-structured and effectively achieves its purpose:

  • It recursively searches for theme color strings in .tsx files, aligning with the provided learning.
  • Appropriate error handling is implemented for file system operations.
  • The regex pattern construction looks correct, including the intentional lack of separators between joinedVariants and joinedPrefixes.

The overall implementation is robust and should reliably find the required theme color strings.


66-69: LGTM: Match processing is concise and effective

The processing of matches is well-implemented:

  • It calls findStringInFiles to get the initial matches.
  • It then uses invertTailwindClassVariant to flip each match, which aligns with the new functionality of the script.

This approach effectively prepares the data for output.


72-80: LGTM: File writing logic is robust and includes necessary checks

The file writing logic is well-implemented:

  • It checks if the output directory exists and creates it if necessary, addressing a potential issue raised in a previous review.
  • The flipped matches are written to the JSON file using fs.writeFileSync.
  • A success message is logged upon completion.

This implementation ensures that the output file is created reliably.


81-82: LGTM: Error handling is concise and informative

The error handling for the file writing operation is well-implemented:

  • It catches any errors that might occur during the file writing process.
  • The error message includes the error object, which will provide detailed information for debugging if an issue occurs.

This implementation addresses a suggestion from a previous review and improves the script's robustness.


1-82: LGTM: Excellent refactoring of the compute-colors script

This refactoring of the compute-colors.ts script is well-executed and aligns perfectly with the PR objectives:

  1. It implements a new approach for finding and processing theme color strings, which should help reduce generated Tailwind classes.
  2. The script is well-structured, with clear separation of concerns between finding color strings, processing them, and writing the output.
  3. Robust error handling has been implemented throughout, addressing previous review comments.
  4. The use of centralized color-related constants and the invertTailwindClassVariant function promotes consistency and maintainability.

Overall, this implementation should effectively support the new dynamic theming approach while optimizing the build process.

src/core/Pricing/PricingCards.tsx (9)

9-9: LGTM: New useTheming hook imported

The import of the new useTheming hook aligns with the PR objective of introducing standardized theming functionality.


48-51: Verify baseTheme setting in useTheming

The usage of the useTheming hook looks good and aligns with the PR objectives. However, please confirm if setting baseTheme: "dark" is the intended default for all cases.

Can you confirm if "dark" should always be the baseTheme, or if this should be configurable?


62-62: LGTM: Correct usage of themeColor for Icon

The themeColor function is correctly used to apply theming to the Icon component's text color.


113-113: LGTM: Correct usage of themeColor for background

The themeColor function is correctly used to apply theming to the background color and hover state. The conditional application of hover styles based on the delimiter prop is properly maintained.


121-121: LGTM: Correct usage of themeColor for text color

The themeColor function is correctly used to apply theming to the text color with a proper fallback to "text-neutral-000".


135-135: LGTM: Correct usage of themeColor for description text color

The themeColor function is correctly used to apply theming to the description text color with a proper fallback to "text-neutral-000".


160-160: Verify hover state styling in FeaturedLink

The themeColor function is correctly used to apply theming to the background and text color of the FeaturedLink component. However, the hover state (hover:text-neutral-000) is not using themeColor. Please verify if this is intentional or if it should also use the theming function for consistency.

Is it intentional that the hover state text color is not using the themeColor function?


170-172: LGTM: Correct usage of themeColor for horizontal rule

The themeColor function is correctly used to apply theming to the horizontal rule's border color. This implementation is consistent with other theming changes in the file.


Line range hint 1-253: Overall assessment: Well-implemented theming changes

The implementation of the new useTheming hook and the use of the themeColor function throughout the PricingCards component is well done and aligns with the PR objectives. The changes consistently apply the new theming approach across various elements of the component.

A few minor suggestions for improvement:

  1. Consider adding fallback colors where they're missing for consistency.
  2. Verify the intentionality of non-themed hover states.
  3. Consider improving readability of long className strings.

These minor adjustments would further enhance the consistency and maintainability of the theming implementation.

src/core/styles/colors/utils.ts Show resolved Hide resolved
Copy link
Contributor

@aralovelace aralovelace left a comment

Choose a reason for hiding this comment

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

I just tested Pricing Cards in the storybook and all works.
I cant dig in to the logic yet but I scanned it looks good as well. Cant wait for the next show and tell to know moore about this

Copy link
Member

@kennethkalmer kennethkalmer left a comment

Choose a reason for hiding this comment

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

I like what you've done here 💅.

What do we need to do in downstream repos to make sure we have all the classes we need though?

scripts/compute-colors.ts Outdated Show resolved Hide resolved
@jamiehenson
Copy link
Member Author

What do we need to do in downstream repos to make sure we have all the classes we need though?

@kennethkalmer Right now, only ably-ui stuff uses themeColor and its ilk. We should prioritise continuing to do that in future to keep as much of the theming stuff as central as possible, but for times where we want to pull in themeColor in voltaire or something, then this script and process will have to be replicated there as well, but in terms of that approach that bridge can be crossed when it comes to it. Amid everything else there hasn't really been chance to properly think about the direction of this feature

@jamiehenson
Copy link
Member Author

If the question though was, "how does this work in voltaire", then the generated json is injected into downstream repo Tailwind configs as before, there are just a lot fewer classes

@jamiehenson jamiehenson force-pushed the reduce-tw-class-generation branch from 38d950c to 0a4107b Compare October 16, 2024 13:22
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: 3

🧹 Outside diff range and nitpick comments (10)
src/core/styles/colors/utils.ts (1)

6-11: Enhance error message for invalid class format.

The error handling for invalid class name format is a good practice. However, the error message could be more informative about the expected format.

Consider updating the error message to provide more context:

- throw new Error("Invalid TW class format");
+ throw new Error("Invalid Tailwind class format. Expected format: 'property-color-variant' (e.g., 'bg-blue-500')");

This change will make it easier for developers to understand and correct the issue when it occurs.

src/core/ProductTile.tsx (5)

22-25: LGTM: Effective implementation of useTheming hook

The useTheming hook is well-implemented, providing dynamic theming based on the selected prop. This aligns perfectly with the PR objectives of enhancing theming capabilities.

Consider destructuring the selected prop at the function parameter level for improved readability:

const ProductTile = ({
  name,
  selected,
  currentPage,
  className,
  onClick,
}: ProductTileProps) => {
  const { themeColor } = useTheming({
    baseTheme: "dark",
    theme: selected ? "light" : "dark",
  });
  // ...
};

This minor change would make the code slightly more concise and easier to read.


30-30: Consider refactoring the className for improved readability

The usage of themeColor function is correct and aligns with the new theming approach. However, the className string is becoming quite long and complex. Consider refactoring it for improved readability and maintainability.

Here's a suggestion using template literals and line breaks:

className={`
  rounded-lg p-12 flex flex-col gap-8 transition-colors
  ${themeColor("bg-neutral-1200")}
  ${selected ? "" : "hover:bg-neutral-1100"}
  ${className ?? ""}
`.trim()}

This approach maintains the current functionality while making the className more readable and easier to maintain.


41-41: LGTM: Correct usage of themeColor function

The themeColor function is correctly implemented in the className string. For consistency with other parts of the component, consider using template literals:

className={`${unavailable ? "ui-text-p2" : "ui-text-p3"} ${themeColor("text-neutral-300")} font-medium`}

This change would maintain the current functionality while aligning the syntax with other parts of the component.


46-46: LGTM: Correct usage of themeColor, but consider refactoring

The themeColor function is correctly implemented. However, the className string is becoming complex. Consider refactoring it for improved readability:

className={`
  ui-text-p2 ${themeColor("text-neutral-000")} font-bold
  ${unavailable ? "" : "mt-[-3px]"}
`.trim()}

This refactoring maintains the current functionality while making the className more readable and easier to maintain.


66-66: LGTM: Correct usage of themeColor, but consider refactoring and renaming

The themeColor function is correctly implemented. However, the additionalCSS prop value is quite long and could be refactored for improved readability. Also, consider renaming additionalCSS to additionalClassName for consistency with React naming conventions.

Suggested refactor:

additionalClassName={`
  ui-btn-secondary bg-transparent hover:bg-transparent w-full
  hover:text-neutral-1300 mt-8 text-center inline-block
  ${themeColor("text-neutral-000")}
`.trim()}

This refactoring improves readability while maintaining the current functionality. The prop rename aligns better with React conventions and clearly indicates its purpose.

scripts/compute-colors.ts (2)

16-19: Consider adjusting the regex pattern for more precise matching

The regex construction is efficient as it's defined outside the file reading loop. However, the current pattern might lead to incorrect matches due to the lack of a separator between joinedVariants and joinedPrefixes.

Consider modifying the pattern to ensure correct matching:

const regex = new RegExp(
  `themeColor\\("(((${joinedVariants})(${joinedPrefixes}))?-(${joinedColors})-(000|[1-9]00|1[0-3]00))"\\)`,
  "g"
);

This adjustment allows for optional variants and prefixes while ensuring proper separation between components.


66-82: LGTM: Main execution flow and error handling are well-implemented

The main execution flow and error handling are well-implemented. The creation of the output directory if it doesn't exist is a good practice to prevent errors.

A minor suggestion for improvement:

Consider adding more detailed logging to provide better visibility into the process:

console.log(`Found ${matches.length} unique theme color matches.`);
console.log(`Processed ${flippedMatches.length} flipped matches.`);

This additional logging will provide more insight into the script's operation.

src/core/styles/colors/types.ts (2)

22-32: Approve the addition of colors constant and ColorClassColorGroups type with a suggestion.

The introduction of the colors constant and ColorClassColorGroups type improves code organization and type safety for color-related operations. This change is beneficial for maintaining consistency across the codebase.

Consider adding "gui" and "secondary" to the colors constant for completeness, as they are used in the colorRoles object. This would ensure all color groups are represented in one place:

export const colors = [
  "neutral",
  "orange",
  "blue",
  "yellow",
  "green",
  "violet",
  "pink",
  "gui",
  "secondary",
] as const;

186-194: Approve the addition of colorGroupLengths with a suggestion for consistency.

The introduction of colorGroupLengths is a useful feature that provides easy access to the number of colors in each group. This can be beneficial for various color-related operations in the codebase.

For consistency, consider deriving all color group lengths from their respective color arrays:

export const colorGroupLengths = {
  neutral: neutralColors.length,
  orange: orangeColors.length,
  blue: blueColors.length,
  yellow: yellowColors.length,
  green: greenColors.length,
  violet: violetColors.length,
  pink: pinkColors.length,
  secondary: secondaryColors.length,
  gui: guiColors.length,
};

This approach ensures that all color group lengths are derived consistently and includes all color groups defined in the file.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 9aa44f5 and 0a4107b.

📒 Files selected for processing (11)
  • .gitignore (1 hunks)
  • package.json (1 hunks)
  • scripts/compute-colors.ts (1 hunks)
  • src/core/Icon/EncapsulatedIcon.tsx (2 hunks)
  • src/core/Pricing/PricingCards.tsx (11 hunks)
  • src/core/ProductTile.tsx (4 hunks)
  • src/core/Tooltip.tsx (4 hunks)
  • src/core/hooks/useTheming.tsx (1 hunks)
  • src/core/styles/colors/Colors.stories.tsx (6 hunks)
  • src/core/styles/colors/types.ts (2 hunks)
  • src/core/styles/colors/utils.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • .gitignore
  • package.json
  • src/core/Icon/EncapsulatedIcon.tsx
  • src/core/Pricing/PricingCards.tsx
  • src/core/Tooltip.tsx
  • src/core/hooks/useTheming.tsx
  • src/core/styles/colors/Colors.stories.tsx
🧰 Additional context used
📓 Learnings (3)
scripts/compute-colors.ts (1)
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: scripts/compute-colors.ts:37-37
Timestamp: 2024-10-14T14:50:06.863Z
Learning: In `scripts/compute-colors.ts`, when searching for `themeColor` usages, only `.tsx` files need to be processed; there is no need to include other file types such as `.ts`, `.jsx`, or `.js`.
src/core/ProductTile.tsx (1)
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: src/core/ProductTile.tsx:30-30
Timestamp: 2024-10-14T15:13:43.163Z
Learning: In `src/core/ProductTile.tsx`, prefer not to use utility libraries like `clsx` for conditional class names.
src/core/styles/colors/types.ts (3)
Learnt from: jamiehenson
PR: ably/ably-ui#510
File: src/core/styles/colors/types.ts:179-183
Timestamp: 2024-10-14T15:40:02.150Z
Learning: In `src/core/styles/colors/types.ts`, `secondary` is still present in `colorRoles` and hasn't been removed.
Learnt from: jamiehenson
PR: ably/ably-ui#486
File: src/core/styles/colors/types.ts:8-15
Timestamp: 2024-09-18T14:08:15.229Z
Learning: When updating `ColorClassVariants` and `ColorClassPrefixes`, only include variants and prefixes that relate to colour classes.
Learnt from: jamiehenson
PR: ably/ably-ui#486
File: src/core/styles/colors/types.ts:8-15
Timestamp: 2024-10-08T15:37:26.766Z
Learning: When updating `ColorClassVariants` and `ColorClassPrefixes`, only include variants and prefixes that relate to colour classes.
🪛 Biome
src/core/styles/colors/utils.ts

[error] 17-17: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.

(lint/suspicious/noGlobalIsNan)

🔇 Additional comments (8)
src/core/styles/colors/utils.ts (2)

1-5: LGTM: Import changes and existing function.

The updated import statement aligns well with the changes in the file. The convertTailwindClassToVar function remains unchanged and continues to serve its purpose.


1-27: Summary: New invertTailwindClassVariant function implementation

The introduction of invertTailwindClassVariant aligns well with the PR objectives of reducing generated Tailwind classes and improving theming capabilities. The function provides a mechanism to invert color variants, which is crucial for dynamic theming.

Key points for improvement:

  1. Enhance error messages to provide more context about expected formats.
  2. Implement more robust parsing of Tailwind class names and variants.
  3. Improve the handling of special cases (e.g., the "neutral" color) and add explanatory comments.
  4. Ensure proper validation of inputs throughout the function.

These improvements will enhance the function's reliability, maintainability, and ease of use. Overall, the changes are a step in the right direction for achieving the PR's goals.

🧰 Tools
🪛 Biome

[error] 17-17: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.

(lint/suspicious/noGlobalIsNan)

src/core/ProductTile.tsx (2)

5-5: LGTM: Import changes align with new theming approach

The addition of the useTheming hook import and the removal of ColorClass and determineThemeColor imports align well with the PR objectives. This change reflects the shift towards a more centralized theming approach using the new hook.


Line range hint 1-78: Overall: Well-implemented theming changes with room for minor improvements

The changes in this file successfully implement the new theming approach using the useTheming hook. The refactoring aligns well with the PR objectives, enhancing the component's theming capabilities.

Key points:

  1. The new useTheming hook is correctly implemented and used throughout the component.
  2. All instances of the old theming approach have been replaced with the new themeColor function.
  3. The changes maintain the component's functionality while improving its theming flexibility.

While the implementation is solid, there are opportunities to improve code readability and maintainability, particularly in complex className strings. Consider applying the suggested refactors to enhance the overall code quality.

Great job on successfully transitioning to the new theming system!

scripts/compute-colors.ts (2)

1-15: LGTM: Imports and constants are well-defined

The imports and constants are appropriately set up for the task. The use of path.join for constructing file paths ensures cross-platform compatibility, which is a good practice.


1-82: Overall assessment: Well-structured script with room for minor optimizations

The compute-colors.ts script is well-structured and effectively accomplishes its task of finding and processing theme color matches. It demonstrates good practices in error handling and file system operations. The suggestions provided in the review comments, if implemented, will further enhance its performance and robustness.

Key points:

  1. Consider adjusting the regex pattern for more precise matching.
  2. Optimize regex usage in the findStringInFiles function.
  3. Add more detailed logging for better visibility into the process.

These improvements will make the script more efficient and easier to maintain.

src/core/styles/colors/types.ts (2)

179-183: Approve the renaming of colorNames to colorRoles.

The renaming of colorNames to colorRoles is a good improvement in clarity. It better describes the purpose of this constant, which is to define the roles or categories of colors used in the application.

As noted in a previous learning, the secondary color group is still present in colorRoles, which maintains consistency with existing code that may rely on it.


Line range hint 1-194: Overall, the changes improve color management and type safety.

The modifications to src/core/styles/colors/types.ts align well with the PR objectives of enhancing theming capabilities and optimizing color-related code. The introduction of colors, ColorClassColorGroups, and colorGroupLengths provides a more structured and type-safe approach to managing colors in the application.

While there are minor suggestions for improvements, such as including all color groups in the colors constant and ensuring consistency in colorGroupLengths, these changes represent a significant step forward in organizing and typing color-related code.

src/core/styles/colors/utils.ts Show resolved Hide resolved
src/core/styles/colors/utils.ts Show resolved Hide resolved
scripts/compute-colors.ts Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants