-
Notifications
You must be signed in to change notification settings - Fork 0
Test #215
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
Conversation
WalkthroughThis 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
Sequence DiagramsequenceDiagram
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
Possibly related PRs
Poem
✨ Finishing Touches
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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
@usewithout 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-whiteis inconsistent with the zinc/slate naming convention used throughout the file. Consider using a standardized token like--zinc-50or--slate-50for 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:
- Add comments documenting the intended usage of each color token to ensure consistent application across components.
- 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
colorsandpalette. Consider:
- Adding TypeScript interfaces for color definitions
- 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.resolvefor 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-alibreaks 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.joinfor 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:
- Cache Bun dependencies to speed up builds
- Upload build artifacts for verification
- 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-whiteuses PascalCasezinc-800uses 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-domas 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-blackandGeneral-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:
- The semantic meaning of each color
- Guidelines for using different shades
- Recommended color combinations
- 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
⛔ Files ignored due to path filters (1)
bun.lockbis 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-scssdependency 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"' fiLength 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/tailwindis valid and properly configured. The package exists, exports are correctly mapped in package.json, and the requiredconfig.tsfile 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.jsonLength 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 basedeclaration is correctly used to define foundational styles, and:rootensures 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); |
There was a problem hiding this comment.
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.
| --table-header: rgba(244, 244, 245, 0.5000); | |
| --table-header: var(--zinc-100-alpha-50); |
| --warning: var(--amber-500); | ||
| --warning-border: var(--amber-200); | ||
| --warning-foreground: var(--General-white); |
There was a problem hiding this comment.
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
| 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 |
There was a problem hiding this comment.
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:
- Input validation for hex color format
- Support for 3-digit hex codes (#RGB)
- 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.
| 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)}%`; | |
| }; |
| 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(); | ||
| }; |
There was a problem hiding this comment.
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.
| 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(); | |
| }; |
| 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}`); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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); | |
| } | |
| }; |
| // 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%; | ||
| // } | ||
| // } |
There was a problem hiding this comment.
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 ... */
-// }
-// }| "hints": { | ||
| "typescript-config/consistent-casing": "off" | ||
| } |
There was a problem hiding this comment.
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:
- Documenting why this rule needs to be disabled
- 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
| { | ||
| "extends": [ | ||
| "development" | ||
| ] | ||
| ], | ||
| "hints": { | ||
| "typescript-config/consistent-casing": "off" | ||
| } |
There was a problem hiding this comment.
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%; |
There was a problem hiding this comment.
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%;| --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%; |
There was a problem hiding this comment.
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:
- WCAG 2.1 contrast ratios
- Color combinations accessibility
- 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
final
Summary by CodeRabbit
Based on the comprehensive changes, here are the release notes:
New Features
Improvements
Chores
Technical Updates