Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable CSS-like linear gradient fills for flowchart nodes #5913

Open
wants to merge 24 commits into
base: develop
Choose a base branch
from

Conversation

enourbakhsh
Copy link

@enourbakhsh enourbakhsh commented Oct 1, 2024

📑 Summary

This PR adds support for CSS-like linear-gradient fills to Mermaid, following the CSS linear-gradient syntax. It introduces a reusable gradient utility that can be applied to other diagrams in the future, though this PR focuses on flowcharts as an example of how the feature can be used. A wide-ranging, editable collection of side-by-side examples comparing Mermaid and CSS linear gradients is available on this CodePen.

mermaid-css

Resolves #2907 and #4476

📏 Design Decisions

The implementation involves updating the lexer to recognize the linear-gradient syntax and modifying the renderer to correctly apply the gradient fills to flowchart nodes. The design follows a CSS-like approach to maintain familiarity for users. See how gradient lines adapt dynamically to various shapes in this CodePen demo, which reflects the design principles behind the added feature.

gradient-line-length

📋 Tasks

Make sure you

  • 📖 have read the contribution guidelines
  • 💻 have added necessary unit/e2e tests.
  • 📓 have added documentation. Make sure MERMAID_RELEASE_VERSION is used for all new features.
  • 🦋 If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. Changesets that add features should be minor and those that fix bugs should be patch. Please prefix changeset messages with feat:, fix:, or chore:.

Copy link

changeset-bot bot commented Oct 1, 2024

🦋 Changeset detected

Latest commit: 5f46a0f

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

This PR includes changesets to release 1 package
Name Type
mermaid 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

@github-actions github-actions bot added the Type: Enhancement New feature or request label Oct 1, 2024
Copy link

netlify bot commented Oct 1, 2024

Deploy Preview for mermaid-js ready!

Name Link
🔨 Latest commit 5f46a0f
🔍 Latest deploy log https://app.netlify.com/sites/mermaid-js/deploys/673855fc9d28910008718405
😎 Deploy Preview https://deploy-preview-5913--mermaid-js.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@enourbakhsh enourbakhsh marked this pull request as draft October 1, 2024 04:45
Copy link

pkg-pr-new bot commented Oct 1, 2024

Open in Stackblitz

pnpm add https://pkg.pr.new/mermaid-js/mermaid@5913
pnpm add https://pkg.pr.new/mermaid-js/mermaid/@mermaid-js/mermaid-zenuml@5913
pnpm add https://pkg.pr.new/mermaid-js/mermaid/@mermaid-js/layout-elk@5913
pnpm add https://pkg.pr.new/mermaid-js/mermaid/@mermaid-js/parser@5913

commit: 5f46a0f

Copy link

argos-ci bot commented Oct 1, 2024

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Dec 31, 2024, 11:13 PM

Copy link

codecov bot commented Oct 1, 2024

Codecov Report

Attention: Patch coverage is 0% with 881 lines in your changes missing coverage. Please review.

Project coverage is 4.42%. Comparing base (8328f74) to head (5f46a0f).

Files with missing lines Patch % Lines
...kages/mermaid/src/rendering-util/createGradient.ts 0.00% 747 Missing ⚠️
.../src/diagrams/flowchart/flowRenderer-v3-unified.ts 0.00% 134 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           develop   #5913      +/-   ##
==========================================
- Coverage     4.49%   4.42%   -0.08%     
==========================================
  Files          382     383       +1     
  Lines        53914   54792     +878     
  Branches       621     622       +1     
==========================================
  Hits          2425    2425              
- Misses       51489   52367     +878     
Flag Coverage Δ
unit 4.42% <0.00%> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
.../src/diagrams/flowchart/flowRenderer-v3-unified.ts 0.00% <0.00%> (ø)
...kages/mermaid/src/rendering-util/createGradient.ts 0.00% <0.00%> (ø)

@enourbakhsh enourbakhsh marked this pull request as ready for review November 1, 2024 09:46
@enourbakhsh enourbakhsh marked this pull request as draft November 1, 2024 09:47
@enourbakhsh enourbakhsh force-pushed the feature/2907_add-linear-gradient-style branch 7 times, most recently from 5cf9e34 to 8f4b507 Compare November 14, 2024 11:39
@enourbakhsh enourbakhsh reopened this Nov 14, 2024
@enourbakhsh enourbakhsh force-pushed the feature/2907_add-linear-gradient-style branch from e13a378 to 35deffd Compare November 14, 2024 12:57
@enourbakhsh enourbakhsh force-pushed the feature/2907_add-linear-gradient-style branch 2 times, most recently from 8a721ff to 327ae28 Compare November 15, 2024 02:11
@enourbakhsh enourbakhsh force-pushed the feature/2907_add-linear-gradient-style branch from 327ae28 to b7a6cbd Compare November 15, 2024 16:04
@enourbakhsh enourbakhsh force-pushed the feature/2907_add-linear-gradient-style branch from d271375 to 299bfea Compare November 16, 2024 07:04
@enourbakhsh enourbakhsh marked this pull request as ready for review November 16, 2024 07:18
@enourbakhsh enourbakhsh force-pushed the feature/2907_add-linear-gradient-style branch from 299bfea to 6e11005 Compare November 16, 2024 07:43
@enourbakhsh enourbakhsh force-pushed the feature/2907_add-linear-gradient-style branch from 6e11005 to 5f46a0f Compare November 16, 2024 08:21
@enourbakhsh
Copy link
Author

@knsv @sidharthv96, your review on this PR would be appreciated when you have time. Thank you!

Copy link
Member

@sidharthv96 sidharthv96 left a comment

Choose a reason for hiding this comment

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

Hi @enourbakhsh thank you for your patience. This is a high-quality PR, with great tests and documentation. I wonder if there is an option to offload the complexity of gradients to CSS, instead of reimplementing the logic inside mermaid, or is there some technical limitation that prevents it?

@enourbakhsh
Copy link
Author

Hi @enourbakhsh thank you for your patience. This is a high-quality PR, with great tests and documentation. I wonder if there is an option to offload the complexity of gradients to CSS, instead of reimplementing the logic inside mermaid, or is there some technical limitation that prevents it?

Hi @sidharthv96, thank you for your feedback! I first tried the CSS approach using a div element with linear-gradient and clip-path inside a foreignObject since I agree it’s best to lean on CSS when possible. This pure CSS approach worked well for rectangular nodes but didn’t adapt to other shapes as expected. That’s why I went through the hassle of implementing the gradient logic directly in SVG, which is probably the most complete solution for converting CSS linear-gradient syntax to SVG <linearGradient> on the internet (at least as far as I’m aware, lol).

The thing is, with the CSS-based approach, we are limited to rendering the gradient in the rectangular frame of the node's bbox and then clipping it, which doesn’t respect the shape-dependent gradient line length explored in this CodePen. Please let me know if you know a workaround. Here’s a comparison of both methods:

flowchart TD
   A[Rectangle] --> B{Rhombus} --> C((Circle)) --> D[(Cylinder)]
   B --> E[/Parallelogram/]
   C --> F([Stadium])
   E --> G[[Subroutine]]
   classDef default fill:linear-gradient(135deg, red, yellow 15%, orange 85%, blue);
SVG-based <linearGradient> (current PR) CSS-based linear-gradient

As you can see, in the CSS method, the blue and red wings are mostly clipped in some nodes. It might not be a big deal for everyone, but it threw me off.

@sidharthv96
Copy link
Member

Ahh, that makes sense! I'm not against adding extra complexity if there is a valid reason. As the codepen was also full of rectangles, I didn't really understand why we needed to re-invent the wheel (although I knew there would be a good one). Now that we know what the problem is, I'll discuss with the team on how to proceed. Thank you!

// rendered on top, allowing layered effects like multiple semi-transparent backgrounds
const styles = [...(vertex.cssStyles || []), ...(vertex.cssCompiledStyles || [])];

// Log all cssCompiledStyles for the node if available
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
// Log all cssCompiledStyles for the node if available
// Log the combined style array if available

Comment on lines +730 to +735
// Setup SVG coordinates
const xc = bbox.x + nodeWidth / 2;
const yc = bbox.y + nodeHeight / 2;
const d1 = (gradientLineLength * (50 - minStop)) / 100;
const d2 = (gradientLineLength * (50 - maxStop)) / 100;
const { x1, y1, x2, y2 } = { x1: xc, y1: yc + d1, x2: xc, y2: yc + d2 }; // Vertical gradient @ 0deg (bottom to top)
Copy link
Author

Choose a reason for hiding this comment

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

This is where the magic happens—we use gradientLineLength to precisely control how the gradient spans the exact node shape at the given angle, something CSS can only do for rectangular shapes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Gradient Styling
2 participants