Skip to content

Feat/2101 background color#2912

Merged
Kiiv merged 10 commits into
mainfrom
feat/2101-background-color
Apr 23, 2026
Merged

Feat/2101 background color#2912
Kiiv merged 10 commits into
mainfrom
feat/2101-background-color

Conversation

@Kiiv

@Kiiv Kiiv commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Checklist

  • I've thoroughly read the latest contribution guidelines.
  • I've rebased my branch onto main before creating this PR.
  • I've added tests to cover my changes (if applicable).
  • I've verified pnpm typecheck and pnpm test.
  • I've added changesets (you can use /changeset-generator SKILL).
  • My change requires documentation updates.
  • I've updated the documentation accordingly (or will do in follow-up PR).

@changeset-bot

changeset-bot Bot commented Apr 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 536fb28

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 21 packages
Name Type
@likec4/language-server Minor
@likec4/style-preset Minor
@likec4/core Minor
@likec4/playground Minor
@likec4/language-services Minor
likec4 Minor
@likec4/lsp Minor
@likec4/mcp Minor
@likec4/vite-plugin Minor
likec4-vscode Minor
@likec4/styles Minor
@likec4/vscode-preview Minor
@likec4/config Minor
@likec4/diagram Minor
@likec4/generators Minor
@likec4/layouts Minor
@likec4/leanix-bridge Minor
@likec4/react Minor
@likec4/docs-astro Minor
@likec4/log Minor
@likec4/tsconfig Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1f1aa6f9-7869-44f7-826f-6a82306b40f7

📥 Commits

Reviewing files that changed from the base of the PR and between cd8da41 and 536fb28.

📒 Files selected for processing (1)
  • .changeset/improve-color-palette.md
✅ Files skipped from review due to trivial changes (1)
  • .changeset/improve-color-palette.md

📝 Walkthrough

Walkthrough

Replaces Mantine-based palette indexing with a custom palette generator, adds tone-adjustment utilities and tests, updates color computation to use named palette fields, adjusts relationship/edge-label colors and CSS dark-mode handling, updates docs and a changeset.

Changes

Cohort / File(s) Summary
Changeset & Docs
.changeset/improve-color-palette.md, apps/docs/src/content/docs/dsl/specification.mdx
Adds a changeset bumping minor versions and updates docs to state LikeC4 generates palettes from a base color (removes Mantine attribution).
Color Utilities & Tests
packages/core/src/utils/colors.ts, packages/core/src/utils/colors.spec.ts
Adds adjustToneRgb and adjustToneHex exports with clamping/rounding and comprehensive Vitest coverage validating RGB/hex equivalence, edge cases, and input formats.
Color Computation & Theme Tests
packages/core/src/styles/compute-color-values.ts, packages/core/src/styles/__test__/theme-index.ts
Removes Mantine palette indexing; adds internal getColorPalette(refColor) and maps named palette fields (el_main, el_secondary, rel_main, rel_secondary); updates contrast derivation and test theme hex constants.
Language Server Test
packages/language-server/src/model/__tests__/model-builder-custom-colors.spec.ts
Updates test input to hex form and adjusts expected derived theme color values to match new computation.
Style Presets & CSS
styled-system/preset/src/defaults/relationship-colors.ts, styled-system/preset/src/globalCss.ts, styled-system/preset/src/recipes/edgeLabel.ts
Updates several label hex values, changes --xy-edge-label-color light/dark lightness calculations (adds _dark), and fixes color reference path in edgeLabel recipe.

Sequence Diagram(s)

sequenceDiagram
  participant User as User (base color input)
  participant Parser as Parser / Language Server
  participant Compute as computeColorValues
  participant Palette as getColorPalette
  participant Adjust as adjustToneHex / adjustToneRgb
  participant Styles as styled-system / CSS
  participant Renderer as Renderer (UI)

  User->>Parser: provide color (e.g., `#db83db`)
  Parser->>Compute: request derived theme
  Compute->>Palette: normalize color -> build named palette
  Palette-->>Compute: return palette (el_main, el_secondary, rel_main, rel_secondary, ...)
  Compute->>Adjust: compute contrasts (hi/lo) and adjusted tones
  Adjust-->>Compute: return contrasted hexes
  Compute->>Styles: emit CSS vars / theme values
  Styles->>Renderer: style updates (edge labels, element fills, dark-mode variants)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Suggested reviewers

  • davydkov
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title references issue #2101 and mentions 'background color', which relates to the color palette improvements and styling changes throughout the changeset.
Description check ✅ Passed The PR description includes a complete contributor checklist with all items checked, demonstrating that the author has followed the contribution process and addressed all required areas including tests, documentation, and changesets.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/2101-background-color

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/core/src/utils/colors.ts (1)

13-23: Avoid the tuple cast in the new utility.

rgb.map(...) widens the tuple to number[], requiring the as cast. A small helper function preserves the return type without casting, aligning with the guideline: "Use TypeScript with explicit types; avoid using any and type casts with as".

♻️ Proposed refactor
 export function adjustToneRgb(rgb: [number, number, number], factor: number): [number, number, number] {
   // Clamp factor to range [-1, 1]
   factor = Math.max(-1, Math.min(1, factor))
 
-  return rgb.map(channel => {
+  const adjustChannel = (channel: number): number => {
     const adjusted = factor > 0
       ? channel + (255 - channel) * factor // lighten
       : channel * (1 + factor) // darken
     // return a value between 0 and 255
     return Math.round(Math.max(0, Math.min(255, adjusted)))
-  }) as [number, number, number]
+  }
+
+  return [adjustChannel(rgb[0]), adjustChannel(rgb[1]), adjustChannel(rgb[2])]
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/utils/colors.ts` around lines 13 - 23, The adjustToneRgb
function currently uses rgb.map(...) which widens the [number,number,number]
tuple to number[] and forces an unsafe "as" cast; change the implementation to
preserve the tuple type without casting by avoiding Array.prototype.map — either
destructure the input and compute each channel explicitly (return [calc(r),
calc(g), calc(b)]), or introduce a small typed helper (e.g., map3) that accepts
[A,B,C] and a mapper to return [R,R,R]; update adjustToneRgb to use that helper
or the explicit per-channel calculations and remove the "as [number, number,
number]" cast.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/docs/src/content/docs/dsl/specification.mdx`:
- Line 121: Fix the subject-verb agreement in the documentation sentence that
currently reads "LikeC4 generate a color palette used to build a color scheme
from the provided base color"—change "generate" to "generates" so the sentence
reads "LikeC4 generates a color palette..." to correct grammar in the sentence
containing the fragment "LikeC4 generate a color palette".

In `@packages/core/src/styles/compute-color-values.ts`:
- Around line 21-35: The computeColorValues function currently trusts
chroma.valid but then casts palette values (e.g., colors.el_main,
colors.el_secondary, colors.rel_main, etc.) to HexColor allowing non-hex inputs
like "rgb(...)" to leak; update computeColorValues to normalize each returned
palette value to a hex string before casting to HexColor (use chroma(...) or the
palette provider’s hex conversion) for all places where you cast to HexColor
(elements.fill, elements.stroke, elements.hiContrast, elements.loContrast,
relationships.line, relationships.label, relationships.labelBg and the refColor
handling around lines ~40-48) so the function always returns canonical hex
strings.

---

Nitpick comments:
In `@packages/core/src/utils/colors.ts`:
- Around line 13-23: The adjustToneRgb function currently uses rgb.map(...)
which widens the [number,number,number] tuple to number[] and forces an unsafe
"as" cast; change the implementation to preserve the tuple type without casting
by avoiding Array.prototype.map — either destructure the input and compute each
channel explicitly (return [calc(r), calc(g), calc(b)]), or introduce a small
typed helper (e.g., map3) that accepts [A,B,C] and a mapper to return [R,R,R];
update adjustToneRgb to use that helper or the explicit per-channel calculations
and remove the "as [number, number, number]" cast.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4350dbfc-8054-4afa-8f9b-00272345536a

📥 Commits

Reviewing files that changed from the base of the PR and between 935f6bb and 14cdf72.

📒 Files selected for processing (10)
  • .changeset/improve-color-palette.md
  • apps/docs/src/content/docs/dsl/specification.mdx
  • packages/core/src/styles/__test__/theme-index.ts
  • packages/core/src/styles/compute-color-values.ts
  • packages/core/src/utils/colors.spec.ts
  • packages/core/src/utils/colors.ts
  • packages/language-server/src/model/__tests__/model-builder-custom-colors.spec.ts
  • styled-system/preset/src/defaults/relationship-colors.ts
  • styled-system/preset/src/globalCss.ts
  • styled-system/preset/src/recipes/edgeLabel.ts

Comment thread apps/docs/src/content/docs/dsl/specification.mdx Outdated
Comment thread packages/core/src/styles/compute-color-values.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/core/src/styles/compute-color-values.ts (2)

53-53: Redundant chroma(...).hex() round-trip.

adjustToneHex already returns a hex string, so wrapping it in chroma(...).hex() is a no-op conversion. You can drop the wrapper and cast the result directly.

♻️ Proposed simplification
-  const rel_secondary = chroma(adjustToneHex(el_main, -0.25)).hex() as HexColor
+  const rel_secondary = adjustToneHex(el_main, -0.25) as HexColor
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/styles/compute-color-values.ts` at line 53, The expression
wrapping adjustToneHex(...) with chroma(...).hex() is redundant; update the
assignment to set rel_secondary directly to the hex string returned by
adjustToneHex and cast it to HexColor (i.e., replace
chroma(adjustToneHex(el_main, -0.25)).hex() with adjustToneHex(el_main, -0.25)
and keep the existing cast), referencing the rel_secondary constant and the
adjustToneHex helper.

104-111: Redundant chroma(x.hex()).hex() for loContrast.

lightColorRgb.hex() / darkColorRgb.hex() already yields a hex string; re-wrapping through chroma(...).hex() only adds work without changing the value. The hiContrast cases do need the wrap because .brighten(0.4) / .darken(0.4) return a chroma.Color, but loContrast can be simplified.

♻️ Proposed simplification
   if (Math.abs(contrastWithLight) > Math.abs(contrastWithDark)) {
     return {
       hiContrast: chroma(lightColorRgb.brighten(0.4)).hex() as HexColor,
-      loContrast: chroma(lightColorRgb.hex()).hex() as HexColor,
+      loContrast: lightColorRgb.hex() as HexColor,
     }
   } else {
     return {
       hiContrast: chroma(darkColorRgb.darken(0.4)).hex() as HexColor,
-      loContrast: chroma(darkColorRgb.hex()).hex() as HexColor,
+      loContrast: darkColorRgb.hex() as HexColor,
     }
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/styles/compute-color-values.ts` around lines 104 - 111,
Simplify redundant wrapping for loContrast: instead of calling
chroma(lightColorRgb.hex()).hex() and chroma(darkColorRgb.hex()).hex(), use the
hex strings directly from lightColorRgb.hex() and darkColorRgb.hex() (cast to
HexColor as needed) while keeping hiContrast computed via
chroma(...).brighten(0.4)/darken(0.4). Ensure you update the loContrast return
values in the branch that uses lightColorRgb and the branch that uses
darkColorRgb to return lightColorRgb.hex() as HexColor and darkColorRgb.hex() as
HexColor respectively.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/core/src/styles/compute-color-values.ts`:
- Line 53: The expression wrapping adjustToneHex(...) with chroma(...).hex() is
redundant; update the assignment to set rel_secondary directly to the hex string
returned by adjustToneHex and cast it to HexColor (i.e., replace
chroma(adjustToneHex(el_main, -0.25)).hex() with adjustToneHex(el_main, -0.25)
and keep the existing cast), referencing the rel_secondary constant and the
adjustToneHex helper.
- Around line 104-111: Simplify redundant wrapping for loContrast: instead of
calling chroma(lightColorRgb.hex()).hex() and chroma(darkColorRgb.hex()).hex(),
use the hex strings directly from lightColorRgb.hex() and darkColorRgb.hex()
(cast to HexColor as needed) while keeping hiContrast computed via
chroma(...).brighten(0.4)/darken(0.4). Ensure you update the loContrast return
values in the branch that uses lightColorRgb and the branch that uses
darkColorRgb to return lightColorRgb.hex() as HexColor and darkColorRgb.hex() as
HexColor respectively.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0f8b6754-7e59-4c49-87cf-9d152da32e25

📥 Commits

Reviewing files that changed from the base of the PR and between 14cdf72 and 6d5a21d.

📒 Files selected for processing (2)
  • apps/docs/src/content/docs/dsl/specification.mdx
  • packages/core/src/styles/compute-color-values.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/docs/src/content/docs/dsl/specification.mdx

@davydkov davydkov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for contribution!
Please mention related issue in changeset and merge it :)

@Kiiv Kiiv merged commit f5d011e into main Apr 23, 2026
16 checks passed
@Kiiv Kiiv deleted the feat/2101-background-color branch April 23, 2026 10:21
@likec4-ci likec4-ci Bot mentioned this pull request Apr 23, 2026
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