Skip to content

Conversation

@mrbadri
Copy link
Contributor

@mrbadri mrbadri commented Jan 28, 2025

final

Summary by CodeRabbit

Based on the comprehensive changes, here are the release notes:

  • New Features

    • Introduced a new design system package with comprehensive color palette and styling infrastructure
    • Added build scripts for generating color tokens and Tailwind configurations
    • Implemented light and dark theme color support
  • Improvements

    • Migrated from CSS to SCSS for more flexible styling
    • Enhanced color management with modular token generation
    • Updated PostCSS configuration to support SCSS syntax
  • Chores

    • Removed leaderboard update workflow
    • Updated GitHub Actions to automate design system builds
    • Restructured project configuration files
  • Technical Updates

    • Added TypeScript configuration for design system
    • Integrated Tailwind CSS color palette generation
    • Updated package dependencies and exports

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 28, 2025

Walkthrough

This pull request introduces a comprehensive design system for the project, focusing on creating a modular and flexible styling approach. The changes include establishing a new design system package with scripts for generating color tokens, SCSS styles, and Tailwind CSS configurations. The project transitions from using CSS to SCSS, introduces a more robust color palette generation mechanism, and sets up automated build processes for design tokens and styles.

Changes

File Change Summary
.github/workflows/ Added build-design-system.yml workflow, removed update-leaderboard.yml and updateLeaderboard.js
packages/design-system/ Created new package with scripts for color token generation, SCSS style generation, Tailwind configuration, and comprehensive styling files
packages/ui/ Updated styling approach, switched from CSS to SCSS, added design system imports
apps/core/app/ Updated import statements for global styles from CSS to SCSS

Sequence Diagram

sequenceDiagram
    participant DS as Design System
    participant Build as Build Scripts
    participant Tailwind as Tailwind Config
    participant SCSS as SCSS Styles

    DS->>Build: Generate color tokens
    Build->>Tailwind: Create colors configuration
    Build->>SCSS: Generate palette and color styles
    SCSS-->>DS: Apply design system styles
Loading

Possibly related PRs

Poem

🐰 A Rabbit's Design System Delight 🎨

Colors dancing, tokens bright,
SCSS and Tailwind taking flight,
From CSS to styles so clean,
Our design system reigns supreme!

Hop, hop, hooray! 🌈

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

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: 14

🧹 Nitpick comments (26)
packages/design-system/src/styles/base/_colors-light.scss (3)

1-1: Consider using an explicit namespace for palette imports.

Using @use without namespace (as *) could lead to naming conflicts. Consider using a descriptive namespace like @use "_palette.scss" as palette; for better maintainability and clarity.

-@use "_palette.scss" as *;
+@use "_palette.scss" as palette;

7-7: Standardize color token naming convention.

The use of --General-white is inconsistent with the zinc/slate naming convention used throughout the file. Consider using a standardized token like --zinc-50 or --slate-50 for white colors.

-    --background: var(--General-white);
+    --background: var(--zinc-50);
-    --destructive-foreground: var(--General-white);
+    --destructive-foreground: var(--zinc-50);
-    --popover: var(--General-white);
+    --popover: var(--zinc-50);
-    --primary-foreground: var(--General-white);
+    --primary-foreground: var(--zinc-50);
-    --warning-foreground: var(--General-white);
+    --warning-foreground: var(--zinc-50);

Also applies to: 12-12, 23-23, 26-26, 37-37


3-39: Consider enhancing theme implementation architecture.

Some suggestions to improve the theming system:

  1. Add comments documenting the intended usage of each color token to ensure consistent application across components.
  2. Consider implementing CSS color-scheme property for system-level theme detection:
 @layer base {
   .light {
+    color-scheme: light;
     /* existing properties */
   }
 }
packages/design-system/src/scripts/utills.ts (1)

23-23: Consider adding precision control for color calculations.

The saturation calculation could benefit from a precision control to avoid floating-point rounding issues.

-    const s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
+    const s = delta === 0 ? 0 : Number((delta / (1 - Math.abs(2 * l - 1))).toFixed(3));
packages/design-system/src/scripts/build-palette-style.ts (2)

6-7: Make file paths configurable.

Consider making the input and output file paths configurable through environment variables or command-line arguments for better flexibility.

+const DEFAULT_INPUT_PATH = '../tokens/token_Palette_Primitive.json';
+const DEFAULT_OUTPUT_PATH = '../styles/base/_palette.scss';
+
-const inputFilePath = path.join(__dirname, '../tokens/token_Palette_Primitive.json');
-const outputFilePath = path.join(__dirname, '../styles/base/_palette.scss');
+const inputFilePath = path.join(__dirname, process.env.INPUT_PATH || DEFAULT_INPUT_PATH);
+const outputFilePath = path.join(__dirname, process.env.OUTPUT_PATH || DEFAULT_OUTPUT_PATH);

53-54: Consider making the script more modular.

The script auto-execution at the bottom makes it harder to test and reuse. Consider separating the execution logic.

-// Run the script
-buildPaletteScss();
+// Only run if this is the main module
+if (require.main === module) {
+  buildPaletteScss();
+}
packages/design-system/src/tailwind/config.ts (1)

7-7: Consider adding type safety for color objects.

The spread operation could mask naming conflicts between colors and palette. Consider:

  1. Adding TypeScript interfaces for color definitions
  2. Adding runtime checks for duplicate color names
+import type { Config } from 'tailwindcss'
+
+interface ColorDefinition {
+  [key: string]: string | ColorDefinition
+}
+
 export const tailwindConfig = {
   theme: {
     extend: {
-      colors: { ...colors, ...palette },
+      colors: ((): ColorDefinition => {
+        const merged = { ...colors, ...palette };
+        // Optional: Add runtime checks for duplicates here
+        return merged;
+      })(),
     },
   },
-};
+} satisfies Config;
packages/design-system/src/scripts/build-main-style.ts (1)

4-6: Use path.resolve for more robust path handling.

Consider using path.resolve for more reliable path resolution across different environments.

-const outputDir = path.join(__dirname, "../styles");
-const outputFilePath = path.join(outputDir, "main.scss");
+const outputDir = path.resolve(__dirname, "..", "styles");
+const outputFilePath = path.resolve(outputDir, "main.scss");
packages/design-system/src/scripts/build-config-tailwind.ts (1)

9-22: Add type safety to the generated Tailwind config.

The generated config should be type-safe to catch potential issues at build time.

Apply this diff to add type information:

 const generateTailwindConfigContent = (): string => {
   return `
+import type { Config } from "tailwindcss";
 import { colors } from "./colors";
 import { palette } from "./palette";
 
-export const tailwindConfig = {
+export const tailwindConfig: Partial<Config> = {
   theme: {
     extend: {
       colors: { ...colors, ...palette },
     },
   },
 };
`.trim();
 };
packages/design-system/src/tailwind/colors.ts (1)

1-35: Add TypeScript types for the color system.

Adding type definitions would improve maintainability and provide better IDE support.

Add the following type definitions:

type ColorToken = `hsl(var(--${string}))`;

interface ColorSystem {
  accent: ColorToken;
  "accent-foreground": ColorToken;
  background: ColorToken;
  // ... other color keys
}

export const colors: ColorSystem = {
  // ... existing color definitions
};
packages/ui/tailwind.config.ts (1)

54-57: Use type-safe plugin imports.

Replace require calls with ES imports for better type safety and consistency.

Apply this diff to update plugin imports:

   plugins: [
     tailwindcssAnimate,
-    require("tailwind-scrollbar"),
-    require("tailwind-scrollbar-hide"),
+    import("tailwind-scrollbar"),
+    import("tailwind-scrollbar-hide"),
   ],
packages/design-system/src/tailwind/palette.ts (2)

82-82: Maintain consistent naming convention.

The token gray-ali breaks the established numeric shade naming pattern used throughout the palette. Consider using a numeric shade value or moving custom named colors to a separate category.


162-173: Add missing shade to maintain consistency.

The "purple" category is missing the "950" shade that is present in all other color categories.

  "purple": {
    "50": "var(--purple-50)",
    // ... existing shades ...
    "900": "var(--purple-900)",
+   "950": "var(--purple-950)",
  },
packages/design-system/src/scripts/build-colors-style.ts (2)

18-18: Consider using a theme configuration object.

The theme selector logic could be more maintainable by using a configuration object.

+const THEME_CONFIG = {
+  dark: { selector: ':root' },
+  light: { selector: '.light' }
+} as const;

-const selector = theme === "dark" ? ":root" : ".light";
+const selector = THEME_CONFIG[theme].selector;

47-52: Use path.join consistently for file paths.

The file path construction could be more robust by using path.join for all path segments.

-  const partFileName = theme === "dark" ? "Default" : "Light";
-  const inputFilePath = path.join(
-    tokensDir,
-    `token_Color_${partFileName}.json`,
-  );
+  const getTokenFileName = (theme: "dark" | "light") => 
+    theme === "dark" ? "Default" : "Light";
+  const inputFilePath = path.join(tokensDir, `token_Color_${getTokenFileName(theme)}.json`);
packages/design-system/src/scripts/build-colors-tailwind.ts (2)

38-41: Enhance error handling with process exit.

Consider exiting the process with a non-zero status code when the token file is missing, as this is a critical build step.

  if (!fs.existsSync(inputFilePath)) {
    console.error(`Token file not found: ${inputFilePath}`);
-   return;
+   process.exit(1);
  }

14-30: Add type safety for token structure.

Consider adding a type definition for the expected token structure to catch potential issues at compile time.

+interface ColorToken {
+  $value: string;
+}
+
+interface TokenStructure {
+  color: Record<string, ColorToken>;
+}

-const generateColorsTsContent = (tokens: Record<string, any>): string => {
+const generateColorsTsContent = (tokens: TokenStructure): string => {
packages/design-system/src/styles/main.scss (1)

1-2: Consider using namespaced imports.

Importing everything into the global namespace with as * could lead to naming conflicts. Consider using namespaced imports for better control and clarity.

-@use "./base/_colors-dark.scss" as *;
-@use "./base/_colors-light.scss" as *;
+@use "./base/_colors-dark.scss" as dark;
+@use "./base/_colors-light.scss" as light;
.github/workflows/build-design-system.yml (1)

11-34: Consider enhancing the workflow with caching and artifacts.

Consider adding these improvements to make the workflow more robust:

  1. Cache Bun dependencies to speed up builds
  2. Upload build artifacts for verification
  3. Add error notifications
 jobs:
   build-design-system:
     runs-on: ubuntu-latest
 
     steps:
     # Step 1: Checkout the repository
     - name: Checkout repository
       uses: actions/checkout@v3
 
     # Step 2: Set up Bun
     - name: Setup Bun
       uses: oven-sh/setup-bun@v1
       with:
         bun-version: latest
+
+    # Step 3: Cache dependencies
+    - name: Cache Bun dependencies
+      uses: actions/cache@v3
+      with:
+        path: ~/.bun/install/cache
+        key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
+        restore-keys: |
+          ${{ runner.os }}-bun-
 
     # Step 3: Navigate to the design-system package and install dependencies
     - name: Install dependencies
       working-directory: ./packages/design-system
       run: bun install
 
     # Step 4: Run the build script
     - name: Run build script
       working-directory: ./packages/design-system
       run: bun run build
+
+    # Step 5: Upload build artifacts
+    - name: Upload build artifacts
+      uses: actions/upload-artifact@v3
+      with:
+        name: design-system-build
+        path: packages/design-system/dist
+
+    # Step 6: Notify on failure
+    - name: Notify on failure
+      if: failure()
+      uses: actions/github-script@v6
+      with:
+        script: |
+          github.rest.issues.createComment({
+            issue_number: context.issue.number,
+            owner: context.repo.owner,
+            repo: context.repo.repo,
+            body: '❌ Design system build failed! Please check the workflow logs.'
+          })
packages/design-system/src/styles/base/_colors-dark.scss (2)

6-7: Maintain consistent casing in variable references.

The casing of color variable references is inconsistent:

  • General-white uses PascalCase
  • zinc-800 uses kebab-case
-    --accent-foreground: var(--General-white);
+    --accent-foreground: var(--general-white);
-    --card-foreground: var(--General-white);
+    --card-foreground: var(--general-white);

Also applies to: 10-11


34-34: Use standard CSS opacity format.

The table header opacity uses a non-standard format with a middle dot (·).

-    --table-header: rgba(39, 39, 42, 0.5000);
+    --table-header: rgb(39 39 42 / 50%);
packages/ui/package.json (2)

Line range hint 9-13: Add missing peer dependency.

Since this is a React UI package, it should also specify react-dom as a peer dependency.

   "peerDependencies": {
-    "react": "^18"
+    "react": "^18",
+    "react-dom": "^18"
   },

81-81: Consider adding SCSS module declarations.

Since you're exporting SCSS files, consider adding type declarations to ensure proper TypeScript integration.

Create a new file src/types/scss.d.ts:

declare module '*.scss' {
  const content: { [className: string]: string };
  export default content;
}
packages/ui/src/styles/globals.scss (1)

1-2: Document imported styles.

Add comments to explain what styles are being imported from each module.

+// Import Tailwind utilities and components
 @use "./_tailinwd.scss" as *;
+// Import design system tokens, colors, and components
 @use "@repo/design-system/styles" as *;
packages/design-system/src/styles/base/_palette.scss (2)

3-4: Consider using semantic names for base colors.

Instead of General-black and General-white, consider using semantic names that reflect their purpose (e.g., --color-base-dark, --color-base-light).

- --General-black: 0 0% 0%;
- --General-white: 0 0% 100%;
+ --color-base-dark: 0 0% 0%;
+ --color-base-light: 0 0% 100%;

1-270: Consider documenting color usage guidelines.

The color system would benefit from documentation that explains:

  1. The semantic meaning of each color
  2. Guidelines for using different shades
  3. Recommended color combinations
  4. Accessibility considerations

Consider adding a comment block at the top of the file:

/**
 * Color Palette System
 * ------------------
 * This file defines the base color palette for the design system.
 * 
 * Usage Guidelines:
 * - 50-200: Background, hover states
 * - 300-600: Primary UI elements
 * - 700-950: Text, borders, high-contrast elements
 * 
 * Accessibility:
 * - Ensure text meets WCAG 2.1 contrast requirements
 * - Use sufficient contrast between interactive elements
 * - Test color combinations for color blindness
 */
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a1f5f6c and a4f31b1.

⛔ Files ignored due to path filters (1)
  • bun.lockb is excluded by !**/bun.lockb
📒 Files selected for processing (31)
  • .github/workflows/build-design-system.yml (1 hunks)
  • .github/workflows/update-leaderboard.yml (0 hunks)
  • .github/workflows/updateLeaderboard.js (0 hunks)
  • .hintrc (1 hunks)
  • apps/core/app/auth/layout.tsx (1 hunks)
  • apps/core/app/layout.tsx (1 hunks)
  • packages/design-system/package.json (1 hunks)
  • packages/design-system/src/scripts/build-colors-style.ts (1 hunks)
  • packages/design-system/src/scripts/build-colors-tailwind.ts (1 hunks)
  • packages/design-system/src/scripts/build-config-tailwind.ts (1 hunks)
  • packages/design-system/src/scripts/build-main-style.ts (1 hunks)
  • packages/design-system/src/scripts/build-palette-style.ts (1 hunks)
  • packages/design-system/src/scripts/build-palette-tailwind.ts (1 hunks)
  • packages/design-system/src/scripts/build.ts (1 hunks)
  • packages/design-system/src/scripts/utills.ts (1 hunks)
  • packages/design-system/src/styles/base/_colors-dark.scss (1 hunks)
  • packages/design-system/src/styles/base/_colors-light.scss (1 hunks)
  • packages/design-system/src/styles/base/_palette.scss (1 hunks)
  • packages/design-system/src/styles/main.scss (1 hunks)
  • packages/design-system/src/tailwind/colors.ts (1 hunks)
  • packages/design-system/src/tailwind/config.ts (1 hunks)
  • packages/design-system/src/tailwind/palette.ts (1 hunks)
  • packages/design-system/src/tokens/token_Palette_primitive.json (1 hunks)
  • packages/design-system/tsconfig.json (1 hunks)
  • packages/design-system/tsconfig.lint.json (1 hunks)
  • packages/ui/package.json (4 hunks)
  • packages/ui/postcss.config.mjs (1 hunks)
  • packages/ui/src/globals.css (0 hunks)
  • packages/ui/src/styles/_tailinwd.scss (1 hunks)
  • packages/ui/src/styles/globals.scss (1 hunks)
  • packages/ui/tailwind.config.ts (3 hunks)
💤 Files with no reviewable changes (3)
  • .github/workflows/update-leaderboard.yml
  • .github/workflows/updateLeaderboard.js
  • packages/ui/src/globals.css
✅ Files skipped from review due to trivial changes (7)
  • apps/core/app/layout.tsx
  • packages/design-system/tsconfig.lint.json
  • packages/design-system/src/tokens/token_Palette_primitive.json
  • packages/ui/src/styles/_tailinwd.scss
  • apps/core/app/auth/layout.tsx
  • packages/design-system/tsconfig.json
  • packages/design-system/package.json
🧰 Additional context used
🪛 GitHub Actions: Build Design System
packages/design-system/src/scripts/build-palette-tailwind.ts

[error] 36-36: File not found: Unable to read '/home/runner/work/pixel-client/pixel-client/packages/design-system/src/tokens/token_Palette_Primitive.json'. The required input file is missing.

🔇 Additional comments (6)
packages/ui/postcss.config.mjs (1)

3-3: Verify postcss-scss dependency installation.

The addition of SCSS syntax support is correct, but we need to ensure the required dependency is properly installed.

✅ Verification successful

postcss-scss dependency is properly installed

The required postcss-scss dependency is correctly declared in package.json with version ^4.0.9.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if postcss-scss is listed in package.json
if [ -f "packages/ui/package.json" ]; then
    echo "Checking postcss-scss in package.json..."
    cat packages/ui/package.json | jq '.dependencies["postcss-scss"] // .devDependencies["postcss-scss"] // "Not found"'
fi

Length of output: 256

packages/design-system/src/scripts/build-main-style.ts (1)

9-14: Validate SCSS imports exist before generating content.

Add validation to ensure the imported SCSS files exist before generating the content.

packages/ui/tailwind.config.ts (1)

3-3: Verify the design system package import path.

Ensure that the import path for the design system package is correct and that the package is properly linked in your workspace.

Also applies to: 6-6

✅ Verification successful

Import path is correctly configured

The import path @repo/design-system/tailwind is valid and properly configured. The package exists, exports are correctly mapped in package.json, and the required config.ts file is present at the expected location.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the package and the imported file exist
ls -l packages/design-system/tailwind/config.* 2>/dev/null || echo "Design system config not found"

Length of output: 121


Script:

#!/bin/bash
# Check if design-system package exists and list its contents
echo "=== Checking design-system package ==="
ls -la packages/design-system/ 2>/dev/null || echo "design-system package not found"

echo -e "\n=== Looking for package.json ==="
find packages/design-system -name "package.json" -type f -exec cat {} \; 2>/dev/null || echo "No package.json found"

echo -e "\n=== Searching for tailwind files ==="
fd -t f tailwind packages/design-system/

echo -e "\n=== Checking workspace configuration ==="
cat package.json

Length of output: 2178


Script:

#!/bin/bash
echo "=== Checking for config.ts ==="
ls -l packages/design-system/src/tailwind/config.ts 2>/dev/null || echo "config.ts not found"

echo -e "\n=== Checking build scripts content ==="
cat packages/design-system/src/scripts/build-config-tailwind.ts 2>/dev/null || echo "build script not found"

Length of output: 1407

.github/workflows/build-design-system.yml (1)

3-9: LGTM! Efficient trigger configuration.

The workflow is correctly configured to run only when relevant files change, which is a good practice for optimizing CI/CD performance.

packages/ui/src/styles/globals.scss (1)

221-232: LGTM! Well-documented utility classes.

The no-scrollbar utility classes are well-documented with clear browser compatibility comments.

packages/design-system/src/styles/base/_palette.scss (1)

1-2: LGTM! Good use of CSS layering.

The @layer base declaration is correctly used to define foundational styles, and :root ensures global scope for the color variables.

--success: var(--green-100);
--success-border: var(--green-200);
--success-foreground: var(--green-700);
--table-header: rgba(244, 244, 245, 0.5000);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace hardcoded rgba value with a token.

The --table-header uses a hardcoded rgba value which breaks the token-based approach. Consider defining this in the palette and referencing it as a variable.

-    --table-header: rgba(244, 244, 245, 0.5000);
+    --table-header: var(--zinc-100-alpha-50);
📝 Committable suggestion

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

Suggested change
--table-header: rgba(244, 244, 245, 0.5000);
--table-header: var(--zinc-100-alpha-50);

Comment on lines +35 to +37
--warning: var(--amber-500);
--warning-border: var(--amber-200);
--warning-foreground: var(--General-white);
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Warning state colors fail WCAG contrast requirements

The combination of amber-500 (HSL 38 92% 50%) and white foreground has a contrast ratio of approximately 2.52:1, which fails to meet WCAG AA requirements (minimum 4.5:1 for normal text, 3:1 for large text). Consider using a darker shade of amber for the warning background to improve accessibility.

🔗 Analysis chain

Verify contrast ratio for warning state colors.

The warning state uses --amber-500 with white foreground text. Please verify that this combination meets WCAG contrast requirements for accessibility.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check contrast ratio between warning background and foreground colors
# Note: This script assumes you have a color.js file that can calculate contrast ratios

# Extract color values from palette
rg --no-filename "amber-500|General-white" ../_palette.scss

# You would need to verify these values meet WCAG AA standards (minimum 4.5:1 for normal text)

Length of output: 118


Script:

#!/bin/bash
# Find potential color definition files
fd -e scss -e css palette
fd -e scss -e css color

# Search for amber and white color definitions
rg -i "amber.*500|general.*white"

Length of output: 2909

Comment on lines +2 to +26
export const hexToHsl = (hex: string): string => {
const r = parseInt(hex.slice(1, 3), 16) / 255;
const g = parseInt(hex.slice(3, 5), 16) / 255;
const b = parseInt(hex.slice(5, 7), 16) / 255;

const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const delta = max - min;

let h = 0;
if (delta !== 0) {
if (max === r) {
h = ((g - b) / delta + (g < b ? 6 : 0)) * 60;
} else if (max === g) {
h = ((b - r) / delta + 2) * 60;
} else {
h = ((r - g) / delta + 4) * 60;
}
}

const l = (max + min) / 2;
const s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));

return `${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
}; No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input validation and support for different hex formats.

The function needs validation and support for different hex formats:

  1. Input validation for hex color format
  2. Support for 3-digit hex codes (#RGB)
  3. Optional support for alpha channel (#RGBA, #RRGGBBAA)

Here's a suggested implementation:

 export const hexToHsl = (hex: string): string => {
+    // Validate hex format
+    const hexRegex = /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/;
+    if (!hexRegex.test(hex)) {
+        throw new Error('Invalid hex color format');
+    }
+
+    // Normalize hex to 6 characters
+    const normalizedHex = hex.length === 4 
+        ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`
+        : hex;
+
-    const r = parseInt(hex.slice(1, 3), 16) / 255;
-    const g = parseInt(hex.slice(3, 5), 16) / 255;
-    const b = parseInt(hex.slice(5, 7), 16) / 255;
+    const r = parseInt(normalizedHex.slice(1, 3), 16) / 255;
+    const g = parseInt(normalizedHex.slice(3, 5), 16) / 255;
+    const b = parseInt(normalizedHex.slice(5, 7), 16) / 255;
📝 Committable suggestion

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

Suggested change
export const hexToHsl = (hex: string): string => {
const r = parseInt(hex.slice(1, 3), 16) / 255;
const g = parseInt(hex.slice(3, 5), 16) / 255;
const b = parseInt(hex.slice(5, 7), 16) / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const delta = max - min;
let h = 0;
if (delta !== 0) {
if (max === r) {
h = ((g - b) / delta + (g < b ? 6 : 0)) * 60;
} else if (max === g) {
h = ((b - r) / delta + 2) * 60;
} else {
h = ((r - g) / delta + 4) * 60;
}
}
const l = (max + min) / 2;
const s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
return `${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
};
export const hexToHsl = (hex: string): string => {
// Validate hex format
const hexRegex = /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/;
if (!hexRegex.test(hex)) {
throw new Error('Invalid hex color format');
}
// Normalize hex to 6 characters
const normalizedHex = hex.length === 4
? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`
: hex;
const r = parseInt(normalizedHex.slice(1, 3), 16) / 255;
const g = parseInt(normalizedHex.slice(3, 5), 16) / 255;
const b = parseInt(normalizedHex.slice(5, 7), 16) / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const delta = max - min;
let h = 0;
if (delta !== 0) {
if (max === r) {
h = ((g - b) / delta + (g < b ? 6 : 0)) * 60;
} else if (max === g) {
h = ((b - r) / delta + 2) * 60;
} else {
h = ((r - g) / delta + 4) * 60;
}
}
const l = (max + min) / 2;
const s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
return `${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
};

Comment on lines +10 to +31
const generateScssContent = (tokens: Record<string, any>): string => {
const lines: string[] = [];

for (const group in tokens) {
const groupTokens = tokens[group];
for (const key in groupTokens) {
const value = groupTokens[key];
if (value.$type === 'color') {
lines.push(` --${group}-${key}: ${hexToHsl(value.$value)};`);
}
}
lines.push(''); // Add an empty line after each group
}

return `
@layer base {
:root {
${lines.join('\n')}
}
}
`.trim();
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add type safety and improve error handling.

The token structure needs proper type definitions, and the function should handle potential type mismatches.

+interface ColorToken {
+    $type: 'color';
+    $value: string;
+}
+
+interface TokenGroup {
+    [key: string]: ColorToken;
+}
+
+interface TokenPalette {
+    [group: string]: TokenGroup;
+}
+
-const generateScssContent = (tokens: Record<string, any>): string => {
+const generateScssContent = (tokens: TokenPalette): string => {
   const lines: string[] = [];

   for (const group in tokens) {
     const groupTokens = tokens[group];
     for (const key in groupTokens) {
       const value = groupTokens[key];
-      if (value.$type === 'color') {
+      if (value.$type === 'color' && typeof value.$value === 'string') {
         lines.push(`  --${group}-${key}: ${hexToHsl(value.$value)};`);
+      } else {
+        console.warn(`Skipping invalid token: ${group}-${key}`);
       }
     }
     lines.push(''); // Add an empty line after each group
   }
📝 Committable suggestion

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

Suggested change
const generateScssContent = (tokens: Record<string, any>): string => {
const lines: string[] = [];
for (const group in tokens) {
const groupTokens = tokens[group];
for (const key in groupTokens) {
const value = groupTokens[key];
if (value.$type === 'color') {
lines.push(` --${group}-${key}: ${hexToHsl(value.$value)};`);
}
}
lines.push(''); // Add an empty line after each group
}
return `
@layer base {
:root {
${lines.join('\n')}
}
}
`.trim();
};
interface ColorToken {
$type: 'color';
$value: string;
}
interface TokenGroup {
[key: string]: ColorToken;
}
interface TokenPalette {
[group: string]: TokenGroup;
}
const generateScssContent = (tokens: TokenPalette): string => {
const lines: string[] = [];
for (const group in tokens) {
const groupTokens = tokens[group];
for (const key in groupTokens) {
const value = groupTokens[key];
if (value.$type === 'color' && typeof value.$value === 'string') {
lines.push(` --${group}-${key}: ${hexToHsl(value.$value)};`);
} else {
console.warn(`Skipping invalid token: ${group}-${key}`);
}
}
lines.push(''); // Add an empty line after each group
}
return `
@layer base {
:root {
${lines.join('\n')}
}
}
`.trim();
};

Comment on lines +34 to +51
export const buildPaletteScss = (): void => {
// Read and parse the JSON file
const rawData = fs.readFileSync(inputFilePath, 'utf-8');
const tokens = JSON.parse(rawData);

// Generate SCSS content
const scssContent = generateScssContent(tokens);

// Ensure the output directory exists
const outputDir = path.dirname(outputFilePath);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}

// Write the SCSS content to the file
fs.writeFileSync(outputFilePath, scssContent, 'utf-8');
console.log(`SCSS file created at: ${outputFilePath}`);
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add comprehensive error handling.

File operations and JSON parsing need proper error handling to provide meaningful error messages.

 export const buildPaletteScss = (): void => {
-  // Read and parse the JSON file
-  const rawData = fs.readFileSync(inputFilePath, 'utf-8');
-  const tokens = JSON.parse(rawData);
+  try {
+    // Read and parse the JSON file
+    if (!fs.existsSync(inputFilePath)) {
+      throw new Error(`Input file not found: ${inputFilePath}`);
+    }
+
+    const rawData = fs.readFileSync(inputFilePath, 'utf-8');
+    let tokens: TokenPalette;
+    
+    try {
+      tokens = JSON.parse(rawData);
+    } catch (e) {
+      throw new Error(`Invalid JSON in input file: ${e.message}`);
+    }

-  // Generate SCSS content
-  const scssContent = generateScssContent(tokens);
+    // Generate SCSS content
+    const scssContent = generateScssContent(tokens);

-  // Ensure the output directory exists
-  const outputDir = path.dirname(outputFilePath);
-  if (!fs.existsSync(outputDir)) {
-    fs.mkdirSync(outputDir, { recursive: true });
-  }
+    // Ensure the output directory exists
+    const outputDir = path.dirname(outputFilePath);
+    if (!fs.existsSync(outputDir)) {
+      fs.mkdirSync(outputDir, { recursive: true });
+    }

-  // Write the SCSS content to the file
-  fs.writeFileSync(outputFilePath, scssContent, 'utf-8');
-  console.log(`SCSS file created at: ${outputFilePath}`);
+    // Write the SCSS content to the file
+    fs.writeFileSync(outputFilePath, scssContent, 'utf-8');
+    console.log(`SCSS file created at: ${outputFilePath}`);
+  } catch (error) {
+    console.error('Failed to build palette SCSS:', error.message);
+    process.exit(1);
+  }
 };
📝 Committable suggestion

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

Suggested change
export const buildPaletteScss = (): void => {
// Read and parse the JSON file
const rawData = fs.readFileSync(inputFilePath, 'utf-8');
const tokens = JSON.parse(rawData);
// Generate SCSS content
const scssContent = generateScssContent(tokens);
// Ensure the output directory exists
const outputDir = path.dirname(outputFilePath);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
// Write the SCSS content to the file
fs.writeFileSync(outputFilePath, scssContent, 'utf-8');
console.log(`SCSS file created at: ${outputFilePath}`);
};
export const buildPaletteScss = (): void => {
try {
// Read and parse the JSON file
if (!fs.existsSync(inputFilePath)) {
throw new Error(`Input file not found: ${inputFilePath}`);
}
const rawData = fs.readFileSync(inputFilePath, 'utf-8');
let tokens: TokenPalette;
try {
tokens = JSON.parse(rawData);
} catch (e) {
throw new Error(`Invalid JSON in input file: ${e.message}`);
}
// Generate SCSS content
const scssContent = generateScssContent(tokens);
// Ensure the output directory exists
const outputDir = path.dirname(outputFilePath);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
// Write the SCSS content to the file
fs.writeFileSync(outputFilePath, scssContent, 'utf-8');
console.log(`SCSS file created at: ${outputFilePath}`);
} catch (error) {
console.error('Failed to build palette SCSS:', error.message);
process.exit(1);
}
};

Comment on lines +4 to +210
// TODO: Delete
// @layer base {
// :root {
// /* primary */
// --primary-50: #ecefff;
// --primary-100: #dde2ff;
// --primary-200: #c2caff;
// --primary-300: #9ca5ff;
// --primary-400: #7576ff;
// --primary-500: #6155ff;
// --primary-600: #553af5;
// --primary-700: #4629d9;
// --primary-800: #3925ae;
// --primary-900: #322689;

// /* Erorr */
// --error-50: #fef2f2;
// --error-100: #fee2e2;
// --error-200: #fecaca;
// --error-300: #fca5a5;
// --error-400: #f87171;
// --error-500: #ef4444;
// --error-600: #dc2626;
// --error-700: #b91c1c;
// --error-800: #991b1b;
// --error-900: #7f1d1d;

// /* Warning */
// --warning-50: #fff4ed;
// --warning-100: #ffe6d5;
// --warning-200: #feccaa;
// --warning-300: #fdac74;
// --warning-400: #fb8a3c;
// --warning-500: #f97316;
// --warning-600: #ea670c;
// --warning-700: #c2570c;
// --warning-800: #9a4a12;
// --warning-900: #7c3d12;

// /* gray */
// --gray-50: #f9fafb;
// --gray-100: #f3f4f6;
// --gray-200: #e5e7eb;
// --gray-300: #d1d5db;
// --gray-400: #9ca3af;
// --gray-500: #6b7280;
// --gray-600: #4b5563;
// --gray-700: #374151;
// --gray-800: #1f2937;
// --gray-900: #111827;

// /* Success */
// --success-50: #f0fdf4;
// --success-100: #f0fdf5;
// --success-200: #bbf7d1;
// --success-300: #86efad;
// --success-400: #4ade80;
// --success-500: #22c55e;
// --success-600: #16a34a;
// --success-700: #15803c;
// --success-800: #166533;
// --success-900: #14532b;

// /* Info */
// --info-50: #f0f9ff;
// --info-100: #e0f2fe;
// --info-200: #bae5fd;
// --info-300: #7dd1fc;
// --info-400: #38bbf8;
// --info-500: #0ea2e9;
// --info-600: #0288d1;
// --info-700: #0367a1;
// --info-800: #075785;
// --info-900: #10C496E;

// --background: 0 0% 100%;
// --foreground: 240 10% 4%;
// --card: 240 5% 96%;
// --card-foreground: 222 47% 11%;
// --popover: 0 0% 100%;
// --popover-foreground: 222 47% 11%;
// --primary: 250 62% 58%;
// --primary-foreground: 210 40% 98%;
// --secondary: 240 5% 96%;
// --secondary-foreground: 240 6% 10%;
// --muted: 240 5% 96%;
// --muted-foreground: 240 4% 46%;
// --accent: 240 5% 96%;
// --accent-foreground: 240 6% 10%;
// --destructive: 0 72% 51%;
// --destructive-foreground: 0 0% 100%;
// --border: 240 6% 90%;
// --input: 240 6% 90%;
// --ring: 240 5% 65%;

// --table-header: 240 5% 96% · 50%;
// --warning-foreground: 26 90% 37%;
// --warning: 48 97% 77%;
// --warning-border: 48 97% 77%;
// --success-foreground: 142 72% 29%;
// --success: 145 80% 10%;
// --success-border: 141 79% 85%;

// --information-foreground: 224 76% 48%;
// --information: 226 57% 21%;
// --information-border: 213 97% 87%;

// --error: 0 93% 94%;
// --error-border: 0 96% 89%;
// --error-foreground: 0 72% 51%;

// --radius: 0.5rem;
// --chart-1: 12 76% 61%;
// --chart-2: 173 58% 39%;
// --chart-3: 197 37% 24%;
// --chart-4: 43 74% 66%;
// --chart-5: 27 87% 67%;
// --table-header: 240 5% 96% · 50%;
// }

// .dark {
// --background: 240 10% 4%;
// --foreground: 0 0% 98%;
// --card: 240 6% 10%;
// --card-foreground: 0 0% 100%;
// --popover: 240 10% 4%;
// --popover-foreground: 0 0% 100%;
// --primary: 250 62% 58%;
// --primary-foreground: 0 0% 100%;
// --secondary: 240 4% 16%;
// --secondary-foreground: 0 0% 100%;
// --muted: 240 5% 96%;
// --muted-foreground: 240 5% 65%;
// --accent: 240 4% 16%;
// --accent-foreground: 0 0% 100%;
// --destructive: 350 89% 60%;
// --destructive-foreground: 0 0% 0%;
// --border: 240 4% 16%;
// --input: 240 4% 16%;
// --ring: 240 5% 84%;

// --table-header: 240 4% 16% · 50%;
// --warning-foreground: 48 96% 89%;
// --warning: 22 78% 26%;
// --warning-border: 22 78% 26%;
// --success-foreground: 138 76% 97%;
// --success: 141 84% 93%;
// --success-border: 144 61% 20%;

// --information-foreground: 214 95% 93%;
// --information: 214 95% 93%;
// --information-border: 224 64% 33%;

// --error: 350 89% 60%;
// --error-border: 0 63% 31%;
// --error-foreground: 0 93% 94%;

// --chart-1: 220 70% 50%;
// --chart-2: 160 60% 45%;
// --chart-3: 30 80% 55%;
// --chart-4: 280 65% 60%;
// --chart-5: 340 75% 55%;
// --table-header: 240 4% 16% · 50%;
// }

// .light {
// --background: 0 0% 100%;
// --foreground: 240 10% 4%;
// --card: 240 5% 96%;
// --card-foreground: 222 47% 11%;
// --popover: 0 0% 100%;
// --popover-foreground: 222 47% 11%;
// --primary: 250 62% 58%;
// --primary-foreground: 210 40% 98%;
// --secondary: 240 5% 96%;
// --secondary-foreground: 240 6% 10%;
// --muted: 240 5% 96%;
// --muted-foreground: 240 4% 46%;
// --accent: 240 5% 96%;
// --accent-foreground: 240 6% 10%;
// --destructive: 0 72% 51%;
// --destructive-foreground: 0 0% 100%;
// --border: 240 6% 90%;
// --input: 240 6% 90%;
// --ring: 240 5% 65%;

// --table-header: 240 5% 96% · 50%;
// --warning-foreground: 26 90% 37%;
// --warning: 48 97% 77%;
// --warning-border: 48 97% 77%;
// --success-foreground: 142 72% 29%;
// --success: 145 80% 10%;
// --success-border: 141 79% 85%;
// --information-foreground: 224 76% 48%;
// --information: 226 57% 21%;
// --information-border: 213 97% 87%;
// --error: 0 93% 94%;
// --error-border: 0 96% 89%;
// --error-foreground: 0 72% 51%;
// --radius: 0.5rem;
// --chart-1: 12 76% 61%;
// --chart-2: 173 58% 39%;
// --chart-3: 197 37% 24%;
// --chart-4: 43 74% 66%;
// --chart-5: 27 87% 67%;
// }
// }
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove commented-out code.

The large block of commented-out color variables should be removed since these values are now managed by the design system.

-// TODO: Delete
-// @layer base {
-//   :root {
-     /* ... large block of commented code ... */
-//   }
-// }

Comment on lines +5 to +7
"hints": {
"typescript-config/consistent-casing": "off"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Re-enable typescript-config/consistent-casing with proper configuration

The codebase follows standard React/TypeScript naming conventions (PascalCase for components, camelCase for hooks/utilities). Instead of disabling the rule entirely, consider configuring it to allow these conventional patterns:

{
  "hints": {
    "typescript-config/consistent-casing": ["error", {
      "allowedCasing": ["camelCase", "PascalCase"]
    }]
  }
}
🔗 Analysis chain

Consider the implications of disabling typescript-config/consistent-casing.

Disabling the consistent-casing rule might lead to inconsistent naming conventions across your TypeScript files. Instead of completely disabling it, consider:

  1. Documenting why this rule needs to be disabled
  2. Using a more specific configuration to target only necessary cases

Let's verify the impact and current state of casing inconsistencies in the codebase:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential casing inconsistencies in TypeScript files
# that might have led to disabling this rule

# Look for files with mixed casing patterns
echo "Files with potential mixed casing patterns:"
rg -l '[A-Z][a-z]+[A-Z]' --type ts

# Look for similar filenames with different casing
echo -e "\nPotentially conflicting filenames:"
find . -name "*.ts" -o -name "*.tsx" | sort -f | uniq -Di

Length of output: 12640

Comment on lines 1 to +7
{
"extends": [
"development"
]
],
"hints": {
"typescript-config/consistent-casing": "off"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Remove orphaned .hintrc configuration file

This .hintrc file appears to be an orphaned configuration as the project:

  • Has no hint-related dependencies installed
  • Uses ESLint for code quality checks instead
🔗 Analysis chain

Verify hint configuration compatibility.

The configuration appears structurally valid, but let's ensure it's compatible with your development setup.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the hint configuration and its dependencies

# Check if hint is installed and get its version
echo "Checking hint installation:"
npm list hint

# Verify if the 'development' configuration exists in dependencies
echo -e "\nChecking for 'development' configuration:"
npm list @hint/configuration-development

# Look for any hint-related errors in package-lock.json
echo -e "\nChecking for hint-related dependency issues:"
jq '.packages | with_entries(select(.key | contains("hint")))' package-lock.json

Length of output: 548


Script:

#!/bin/bash
# Check for hint-related configuration and dependencies

echo "Checking package.json for hint dependencies:"
if [ -f "package.json" ]; then
    jq '.dependencies, .devDependencies' package.json
else
    echo "package.json not found"
fi

echo -e "\nSearching for hint configuration files:"
fd -e hintrc -e .hintrc

echo -e "\nSearching for TypeScript configuration:"
fd tsconfig.json

Length of output: 692

--gray-800: 215 28% 17%;
--gray-900: 221 39% 11%;
--gray-950: 224 71% 4%;
--gray-ali: 210 20% 98%;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove non-standard color variable.

The --gray-ali variable breaks the consistent naming pattern and appears to be a one-off addition. Consider removing it or integrating it into the standard gray scale.

- --gray-ali: 210 20% 98%;

Comment on lines +6 to +267
--amber-50: 48 100% 96%;
--amber-100: 48 96% 89%;
--amber-200: 48 97% 77%;
--amber-300: 46 97% 65%;
--amber-400: 43 96% 56%;
--amber-500: 38 92% 50%;
--amber-600: 32 95% 44%;
--amber-700: 26 90% 37%;
--amber-800: 23 83% 31%;
--amber-900: 22 78% 26%;
--amber-950: 21 92% 14%;

--blue-50: 214 100% 97%;
--blue-100: 214 95% 93%;
--blue-200: 213 97% 87%;
--blue-300: 212 96% 78%;
--blue-400: 213 94% 68%;
--blue-500: 217 91% 60%;
--blue-600: 221 83% 53%;
--blue-700: 224 76% 48%;
--blue-800: 226 71% 40%;
--blue-900: 224 64% 33%;
--blue-950: 226 57% 21%;

--cyan-50: 183 100% 96%;
--cyan-100: 185 96% 90%;
--cyan-200: 186 94% 82%;
--cyan-300: 187 92% 69%;
--cyan-400: 188 86% 53%;
--cyan-500: 189 94% 43%;
--cyan-600: 192 91% 36%;
--cyan-700: 193 82% 31%;
--cyan-800: 194 70% 27%;
--cyan-900: 196 64% 24%;
--cyan-950: 197 79% 15%;

--emerald-50: 152 81% 96%;
--emerald-100: 149 80% 90%;
--emerald-200: 152 76% 80%;
--emerald-300: 156 72% 67%;
--emerald-400: 158 64% 52%;
--emerald-500: 160 84% 39%;
--emerald-600: 161 94% 30%;
--emerald-700: 163 94% 24%;
--emerald-800: 163 88% 20%;
--emerald-900: 164 86% 16%;
--emerald-950: 166 91% 9%;

--fuchsia-50: 289 100% 98%;
--fuchsia-100: 287 100% 95%;
--fuchsia-200: 288 96% 91%;
--fuchsia-300: 291 93% 83%;
--fuchsia-400: 292 91% 73%;
--fuchsia-500: 292 84% 61%;
--fuchsia-600: 293 69% 49%;
--fuchsia-700: 295 72% 40%;
--fuchsia-800: 295 70% 33%;
--fuchsia-900: 297 64% 28%;
--fuchsia-950: 297 90% 16%;

--gray-100: 220 14% 96%;
--gray-200: 220 13% 91%;
--gray-300: 216 12% 84%;
--gray-400: 218 11% 65%;
--gray-500: 220 9% 46%;
--gray-600: 215 14% 34%;
--gray-700: 217 19% 27%;
--gray-800: 215 28% 17%;
--gray-900: 221 39% 11%;
--gray-950: 224 71% 4%;
--gray-ali: 210 20% 98%;

--green-50: 138 76% 97%;
--green-100: 141 84% 93%;
--green-200: 141 79% 85%;
--green-300: 142 77% 73%;
--green-400: 142 69% 58%;
--green-500: 142 71% 45%;
--green-600: 142 76% 36%;
--green-700: 142 72% 29%;
--green-800: 143 64% 24%;
--green-900: 144 61% 20%;
--green-950: 145 80% 10%;

--indigo-50: 226 100% 97%;
--indigo-100: 226 100% 94%;
--indigo-200: 228 96% 89%;
--indigo-300: 230 94% 82%;
--indigo-400: 234 89% 74%;
--indigo-500: 239 84% 67%;
--indigo-600: 243 75% 59%;
--indigo-700: 245 58% 51%;
--indigo-800: 244 55% 41%;
--indigo-900: 242 47% 34%;
--indigo-950: 244 47% 20%;

--lime-50: 78 92% 95%;
--lime-100: 80 89% 89%;
--lime-200: 81 88% 80%;
--lime-300: 82 85% 67%;
--lime-400: 83 78% 55%;
--lime-500: 84 81% 44%;
--lime-600: 85 85% 35%;
--lime-700: 86 78% 27%;
--lime-800: 86 69% 23%;
--lime-900: 88 61% 20%;
--lime-950: 89 80% 10%;

--neutral-50: 0 0% 98%;
--neutral-100: 0 0% 96%;
--neutral-200: 0 0% 90%;
--neutral-300: 0 0% 83%;
--neutral-400: 0 0% 64%;
--neutral-500: 0 0% 45%;
--neutral-600: 0 0% 32%;
--neutral-700: 0 0% 25%;
--neutral-800: 0 0% 15%;
--neutral-900: 0 0% 9%;
--neutral-950: 0 0% 4%;

--orange-50: 33 100% 96%;
--orange-100: 34 100% 92%;
--orange-200: 32 98% 83%;
--orange-300: 31 97% 72%;
--orange-400: 27 96% 61%;
--orange-500: 25 95% 53%;
--orange-600: 21 90% 48%;
--orange-700: 17 88% 40%;
--orange-800: 15 79% 34%;
--orange-900: 15 75% 28%;
--orange-950: 13 81% 15%;

--pink-50: 327 73% 97%;
--pink-100: 326 78% 95%;
--pink-200: 326 85% 90%;
--pink-300: 327 87% 82%;
--pink-400: 329 86% 70%;
--pink-500: 330 81% 60%;
--pink-600: 333 71% 51%;
--pink-700: 335 78% 42%;
--pink-800: 336 74% 35%;
--pink-900: 336 69% 30%;
--pink-950: 336 84% 17%;

--purple-50: 251 62% 95%;
--purple-100: 250 61% 90%;
--purple-200: 250 63% 80%;
--purple-300: 250 62% 70%;
--purple-400: 250 62% 60%;
--purple-500: 250 62% 58%;
--purple-600: 250 62% 40%;
--purple-700: 250 62% 30%;
--purple-800: 250 63% 20%;
--purple-900: 250 61% 10%;

--red-50: 0 86% 97%;
--red-100: 0 93% 94%;
--red-200: 0 96% 89%;
--red-300: 0 94% 82%;
--red-400: 0 91% 71%;
--red-500: 0 84% 60%;
--red-600: 0 72% 51%;
--red-700: 0 74% 42%;
--red-800: 0 70% 35%;
--red-900: 0 63% 31%;
--red-950: 0 75% 15%;

--rose-50: 356 100% 97%;
--rose-100: 356 100% 95%;
--rose-200: 353 96% 90%;
--rose-300: 353 96% 82%;
--rose-400: 351 95% 71%;
--rose-500: 350 89% 60%;
--rose-600: 347 77% 50%;
--rose-700: 345 83% 41%;
--rose-800: 343 80% 35%;
--rose-900: 342 75% 30%;
--rose-950: 343 88% 16%;

--sky-50: 204 100% 97%;
--sky-100: 204 94% 94%;
--sky-200: 201 94% 86%;
--sky-300: 199 95% 74%;
--sky-400: 198 93% 60%;
--sky-500: 199 89% 48%;
--sky-600: 200 98% 39%;
--sky-700: 201 96% 32%;
--sky-800: 201 90% 27%;
--sky-900: 202 80% 24%;
--sky-950: 204 80% 16%;

--slate-50: 210 40% 98%;
--slate-100: 210 40% 96%;
--slate-200: 214 32% 91%;
--slate-300: 213 27% 84%;
--slate-400: 215 20% 65%;
--slate-500: 215 16% 47%;
--slate-600: 215 19% 35%;
--slate-700: 215 25% 27%;
--slate-800: 217 33% 17%;
--slate-900: 222 47% 11%;
--slate-950: 229 84% 5%;

--stone-50: 60 9% 98%;
--stone-100: 60 5% 96%;
--stone-200: 20 6% 90%;
--stone-300: 24 6% 83%;
--stone-400: 24 5% 64%;
--stone-500: 25 5% 45%;
--stone-600: 33 5% 32%;
--stone-700: 30 6% 25%;
--stone-800: 12 6% 15%;
--stone-900: 24 10% 10%;
--stone-950: 20 14% 4%;

--teal-50: 166 76% 97%;
--teal-100: 167 85% 89%;
--teal-200: 168 84% 78%;
--teal-300: 171 77% 64%;
--teal-400: 172 66% 50%;
--teal-500: 173 80% 40%;
--teal-600: 175 84% 32%;
--teal-700: 175 77% 26%;
--teal-800: 176 69% 22%;
--teal-900: 176 61% 19%;
--teal-950: 179 84% 10%;

--violet-50: 250 100% 98%;
--violet-100: 251 91% 95%;
--violet-200: 251 95% 92%;
--violet-300: 252 95% 85%;
--violet-400: 255 92% 76%;
--violet-500: 258 90% 66%;
--violet-600: 262 83% 58%;
--violet-700: 263 70% 50%;
--violet-800: 263 69% 42%;
--violet-900: 264 67% 35%;
--violet-950: 261 73% 23%;

--yellow-50: 55 92% 95%;
--yellow-100: 55 97% 88%;
--yellow-200: 53 98% 77%;
--yellow-300: 50 98% 64%;
--yellow-400: 48 96% 53%;
--yellow-500: 45 93% 47%;
--yellow-600: 41 96% 40%;
--yellow-700: 35 92% 33%;
--yellow-800: 32 81% 29%;
--yellow-900: 28 73% 26%;
--yellow-950: 26 83% 14%;

--zinc-50: 0 0% 98%;
--zinc-100: 240 5% 96%;
--zinc-200: 240 6% 90%;
--zinc-300: 240 5% 84%;
--zinc-400: 240 5% 65%;
--zinc-500: 240 4% 46%;
--zinc-600: 240 5% 34%;
--zinc-700: 240 5% 26%;
--zinc-800: 240 4% 16%;
--zinc-900: 240 6% 10%;
--zinc-950: 240 10% 4%;
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Color palette requires accessibility improvements

The color palette has several WCAG 2.1 compliance issues:

  • Success (green) and warning (yellow) states fail accessibility requirements on all background colors (contrast ratios < 3:1)
  • Primary interactive colors (blue-500) only meet large text requirements (≥18px)
  • Most semantic colors don't meet normal text requirements (contrast ratios < 4.5:1)

Recommendations:

  • Increase contrast for green and yellow states against light backgrounds
  • Add darker variants for normal text usage
  • Keep current shades for large text and decorative elements
🔗 Analysis chain

Verify color palette accessibility.

The color palette needs to be verified for:

  1. WCAG 2.1 contrast ratios
  2. Color combinations accessibility
  3. Sufficient contrast between adjacent shades
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Install and use color-contrast-checker to verify WCAG compliance
npm install color-contrast-checker
python3 << 'EOF'
import json
import math
from typing import Tuple

def hsl_to_rgb(h: float, s: float, l: float) -> Tuple[int, int, int]:
    h /= 360
    s /= 100
    l /= 100
    
    def hue_to_rgb(p: float, q: float, t: float) -> float:
        if t < 0:
            t += 1
        if t > 1:
            t -= 1
        if t < 1/6:
            return p + (q - p) * 6 * t
        if t < 1/2:
            return q
        if t < 2/3:
            return p + (q - p) * (2/3 - t) * 6
        return p
    
    if s == 0:
        r = g = b = l
    else:
        q = l * (1 + s) if l < 0.5 else l + s - l * s
        p = 2 * l - q
        r = hue_to_rgb(p, q, h + 1/3)
        g = hue_to_rgb(p, q, h)
        b = hue_to_rgb(p, q, h - 1/3)
    
    return (round(r * 255), round(g * 255), round(b * 255))

def relative_luminance(r: int, g: int, b: int) -> float:
    rs = r / 255
    gs = g / 255
    bs = b / 255
    
    rs = rs / 12.92 if rs <= 0.03928 else ((rs + 0.055) / 1.055) ** 2.4
    gs = gs / 12.92 if gs <= 0.03928 else ((gs + 0.055) / 1.055) ** 2.4
    bs = bs / 12.92 if bs <= 0.03928 else ((bs + 0.055) / 1.055) ** 2.4
    
    return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs

def contrast_ratio(l1: float, l2: float) -> float:
    lighter = max(l1, l2)
    darker = min(l1, l2)
    return (lighter + 0.05) / (darker + 0.05)

# Test a few key combinations
colors = {
    'blue-500': (217, 91, 60),
    'blue-900': (224, 64, 33),
    'gray-100': (220, 14, 96),
    'gray-900': (221, 39, 11)
}

results = []
for name1, hsl1 in colors.items():
    rgb1 = hsl_to_rgb(*hsl1)
    lum1 = relative_luminance(*rgb1)
    for name2, hsl2 in colors.items():
        if name1 >= name2:
            continue
        rgb2 = hsl_to_rgb(*hsl2)
        lum2 = relative_luminance(*rgb2)
        ratio = contrast_ratio(lum1, lum2)
        results.append({
            'combination': f'{name1} vs {name2}',
            'contrast_ratio': ratio,
            'meets_AA_normal': ratio >= 4.5,
            'meets_AA_large': ratio >= 3
        })

print(json.dumps(results, indent=2))
EOF

Length of output: 973


Script:

#!/bin/bash
python3 << 'EOF'
import json
from typing import Tuple

def hsl_to_rgb(h: float, s: float, l: float) -> Tuple[int, int, int]:
    h /= 360
    s /= 100
    l /= 100
    
    def hue_to_rgb(p: float, q: float, t: float) -> float:
        if t < 0:
            t += 1
        if t > 1:
            t -= 1
        if t < 1/6:
            return p + (q - p) * 6 * t
        if t < 1/2:
            return q
        if t < 2/3:
            return p + (q - p) * (2/3 - t) * 6
        return p
    
    if s == 0:
        r = g = b = l
    else:
        q = l * (1 + s) if l < 0.5 else l + s - l * s
        p = 2 * l - q
        r = hue_to_rgb(p, q, h + 1/3)
        g = hue_to_rgb(p, q, h)
        b = hue_to_rgb(p, q, h - 1/3)
    
    return (round(r * 255), round(g * 255), round(b * 255))

def relative_luminance(r: int, g: int, b: int) -> float:
    rs = r / 255
    gs = g / 255
    bs = b / 255
    
    rs = rs / 12.92 if rs <= 0.03928 else ((rs + 0.055) / 1.055) ** 2.4
    gs = gs / 12.92 if gs <= 0.03928 else ((gs + 0.055) / 1.055) ** 2.4
    bs = bs / 12.92 if bs <= 0.03928 else ((bs + 0.055) / 1.055) ** 2.4
    
    return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs

def contrast_ratio(l1: float, l2: float) -> float:
    lighter = max(l1, l2)
    darker = min(l1, l2)
    return (lighter + 0.05) / (darker + 0.05)

# Test semantic colors against backgrounds
colors = {
    # Primary interactive
    'blue-500': (217, 91, 60),
    'blue-600': (221, 83, 53),
    'blue-700': (224, 76, 48),
    # Error states
    'red-500': (0, 84, 60),
    'red-600': (0, 72, 51),
    # Success states
    'green-500': (142, 71, 45),
    'green-600': (142, 76, 36),
    # Warning
    'yellow-500': (45, 93, 47),
    'yellow-600': (41, 96, 40),
    # Backgrounds
    'gray-50': (0, 0, 98),
    'gray-100': (220, 14, 96),
    'gray-200': (220, 13, 91)
}

results = []
# Test adjacent shades
adjacent_pairs = [
    ('blue-500', 'blue-600'),
    ('blue-600', 'blue-700'),
    ('red-500', 'red-600'),
    ('green-500', 'green-600'),
    ('yellow-500', 'yellow-600')
]

# Test against backgrounds
semantic_colors = ['blue-500', 'red-500', 'green-500', 'yellow-500']
backgrounds = ['gray-50', 'gray-100', 'gray-200']

for color1, color2 in adjacent_pairs:
    rgb1 = hsl_to_rgb(*colors[color1])
    rgb2 = hsl_to_rgb(*colors[color2])
    lum1 = relative_luminance(*rgb1)
    lum2 = relative_luminance(*rgb2)
    ratio = contrast_ratio(lum1, lum2)
    results.append({
        'test_type': 'adjacent_shades',
        'combination': f'{color1} vs {color2}',
        'contrast_ratio': ratio,
        'meets_AA_normal': ratio >= 4.5,
        'meets_AA_large': ratio >= 3
    })

for semantic in semantic_colors:
    rgb1 = hsl_to_rgb(*colors[semantic])
    lum1 = relative_luminance(*rgb1)
    for bg in backgrounds:
        rgb2 = hsl_to_rgb(*colors[bg])
        lum2 = relative_luminance(*rgb2)
        ratio = contrast_ratio(lum1, lum2)
        results.append({
            'test_type': 'semantic_on_background',
            'combination': f'{semantic} vs {bg}',
            'contrast_ratio': ratio,
            'meets_AA_normal': ratio >= 4.5,
            'meets_AA_large': ratio >= 3
        })

print(json.dumps(results, indent=2))
EOF

Length of output: 3287

@mrbadri mrbadri closed this Jan 29, 2025
@mrbadri mrbadri deleted the test branch January 31, 2025 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants