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

Support separate config for mermaid dark mode #10251

Open
2 tasks done
sidharthv96 opened this issue Jun 26, 2024 · 2 comments
Open
2 tasks done

Support separate config for mermaid dark mode #10251

sidharthv96 opened this issue Jun 26, 2024 · 2 comments
Labels
feature This is not a bug or issue with Docusausus, per se. It is a feature request for the future.

Comments

@sidharthv96
Copy link

sidharthv96 commented Jun 26, 2024

Have you read the Contributing Guidelines on issues?

Description

Currently, there is support to use different themes based on light/dark mode, but the options passed is the same.
So if a user wants to set different theme colors for light/dark mode, that is not possible.

Has this been requested on Canny?

No response

Motivation

This feature was requested in Mermaid's discord by users.
Upon further investigation, allowing an extra config option like the theme would enable users to pass different options based on the light/dark mode.
This would help users who are customising the diagram using themeVariables.

API design

Current type

export type ThemeConfig = {
    mermaid: {
      theme: {
        light: mermaidAPI.Theme;
        dark: mermaidAPI.Theme;
      };
      options: mermaidAPI.Config;
    };
  };

Proposed option 1

This is a non-breaking change, but it differs from the pattern used in theme

export type ThemeConfig = {
    mermaid: {
      theme: {
        light: mermaidAPI.Theme;
        dark: mermaidAPI.Theme;
      };
      options: mermaidAPI.Config;
      optionsDark:  mermaidAPI.Config;
    };
  };

Proposed option 2

By changing the key to config, it aligns with the type mermaidAPI.Config, and also allows us to retain options as a fallback in case config is not provided. This also aligns with the pattern followed in theme.

export type ThemeConfig = {
    mermaid: {
      theme: {
        light: mermaidAPI.Theme;
        dark: mermaidAPI.Theme;
      };
      config: {
         light: mermaidAPI.Config;
         dark: mermaidAPI.Config;
       };
      // Deprecate
      options: mermaidAPI.Config;
    };
  };

or, to ensure only one of config/options is present.

export type ThemeConfig = {
    mermaid: {
      theme: {
        light: mermaidAPI.Theme;
        dark: mermaidAPI.Theme;
      };
      config?: {
        light: mermaidAPI.Config;
        dark: mermaidAPI.Config;
      };
      options?: mermaidAPI.Config;
    } & (
      | {
          config: {light: mermaidAPI.Config; dark: mermaidAPI.Config};
          options?: never;
        }
      | {options: mermaidAPI.Config; config?: never}
    );
  };

Have you tried building it?

Yes, by changing useMermaidConfig to the following, where options is used as a fallback in case config key is not provided.

export function useMermaidConfig(): MermaidConfig {
  const {colorMode} = useColorMode();
  const mermaidThemeConfig = useMermaidThemeConfig();

  const theme = mermaidThemeConfig.theme[colorMode];
  const config = mermaidThemeConfig.config?.[colorMode] ?? mermaidThemeConfig.options;

  return useMemo(
    () => ({startOnLoad: false, ...config, theme}),
    [theme, config],
  );
}

Self-service

  • I'd be willing to contribute this feature to Docusaurus myself.
@sidharthv96 sidharthv96 added feature This is not a bug or issue with Docusausus, per se. It is a feature request for the future. status: needs triage This issue has not been triaged by maintainers labels Jun 26, 2024
@slorber slorber removed the status: needs triage This issue has not been triaged by maintainers label Jun 27, 2024
@slorber
Copy link
Collaborator

slorber commented Jun 27, 2024

The API design is the easy part of implementing Mermaid light/dark mode support. We might as well do {options: {light,dark}} (and keep supporting simpler {options: ...} too)


Keep in mind that we really want to move to server-rendered Mermaid diagrams (once available or through headless browser rendering). We don't want Mermaid in the client Docusaurus bundle (unlike now) and have layout shifts due to rendering diagrams client-side.

See also:

In an ideal world, we'd want to only render one Mermaid diagram per color mode, and use something like CSS variables to theme it.

In a less ideal world, we'd have to render the 2 diagrams at build time, append them both to the page, and depending on html[data-theme] one or the other would show, avoiding FOUC and layout shifts.

We really want to get rid of client-rendered layout shifts, and should avoid relying on React client-side code to choose which of the 2 diagrams to render, because until React hydration completes we might render the wrong diagram, or a spinner/placeholder.


export function useMermaidConfig(): MermaidConfig {
  const {colorMode} = useColorMode();

We use this at the moment, but to be honest it's not a great solution.
As said above we can wait for React hydration to complete before showing the appropriate diagram.

And this React hook to get the colorMode is misleading because initially (during hydration) it won't return you the actual color mode (coming from localStorage), but the one that we used during the SSG phase (ie a static color mode, because we can't know at build time what's the visitor localStorage color mode).

useColorMode() is misleading our users for a while for these very reasons, and I'm thinking removing it entirely, or prefixing it with useDangerousColorMode() or something 😅

See also #7986


We could support what you request, but to be honest I'm afraid supporting it might make our task to have proper support (build time, no layout shifts) for simpler Mermaid use-cases might become harder if we add support for more advanced Mermaid use-cases. Do you think it could be the case?

What is the main reason for us to have support for themed config/options?
Who plans to use it exactly, and how?
What is the expected output?

Please redirect your user requests to this issue so that we can understand better the context of this feature request.

@sidharthv96
Copy link
Author

sidharthv96 commented Jun 27, 2024

We might as well do {options: {light,dark}} (and keep supporting simpler {options: ...} too)
That was my first thought as well, but then thought that switching to a new key, while retaining the old options would make the code a lot cleaner, while having the least impact for users.

I have a working version here, without the docs changes. We can tweak to use {options: {light,dark}} itself if required.


In an ideal world, we'd want to only render one Mermaid diagram per color mode, and use something like CSS variables to theme it.

Completely agree. That was the first thing I checked when I first heard the requirement. But that's currently not possible due to how mermaid is implemented (we calculate related colors based on hex values passed in options/themes). I have a proposal to change that, but it will require a major overhaul of the theming engine. We are currently doing some refactorings on rendering which would make this a bit easier, but a proper solution is going to take some time.

In a less ideal world, we'd have to render the 2 diagrams at build time, append them both to the page, and depending on html[data-theme] one or the other would show, avoiding FOUC and layout shifts.

This is a great alternative.

Keep in mind that we really want to move to server-rendered Mermaid diagrams (once available or through headless browser rendering).

I would also love to have SSR, and we are making some initial steps to change our rendering pipeline to support SSR sometime in the far future. It is possible to render using headless browsers (in your case, at build time?), you can utilise mermaid-cli for it now.

I'm afraid supporting it might make our task to have proper support (build time, no layout shifts) for simpler Mermaid use-cases might become harder if we add support for more advanced Mermaid use-cases. Do you think it could be the case?

I think the proposed approach of having two sets of configs would actually make it simpler in the case of SSR, as we can render both the light & dark images with corresponding configs. Currently, docusaurus supports light/dark mode partially, so users who need to customise the themes for light/dark mode don't have a choice. By extending the config to support dark and light, we can offer full customisation for both, whether we use CSR or SSR.

One downside of this approach is that the users will have to duplicate options that are common for both themes. We could handle it in a few ways, but it'll add more complexity internally.


What is the main reason for us to have support for themed config/options?

Currently, to support dark & light mode diagrams that match the look and feel of the website.

Who plans to use it exactly, and how?

The current request came from @altitude, as part of their work on updating the theme on their doc site.

What is the expected output?

The mermaid diagrams on their site matches the overall color scheme on light and dark mode.

Screen.Recording.2024-06-27.at.12.48.13.PM.mov

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature This is not a bug or issue with Docusausus, per se. It is a feature request for the future.
Projects
None yet
Development

No branches or pull requests

2 participants