Skip to content
This repository was archived by the owner on Feb 7, 2024. It is now read-only.
This repository was archived by the owner on Feb 7, 2024. It is now read-only.

space toggles for switching themes #6

Closed
@mayank99

Description

@mayank99

Clear and concise description of the problem

the current approach for dual themes is quite clever indeed, but it can be problematic in a few ways.

  1. it relies on implementation details like .shiki and span selectors. not a deal-breaker.
  2. it could get unwieldy/verbose when considering additional themes (e.g. high-contrast). also not a deal-breaker. 🤷
  3. it relies on !important, which is pretty much deprecated in this day and age of cascade layers. As a user, it is important (ha!) to me that i have control over the cascade, as i might need to change the colors for particular cases (such as text highlighting, print stylesheets, or forced colors mode).

for reference, here is the css currently needed from the user's side for switching themes:

@media (prefers-color-scheme: dark) {
 .shiki {
   background-color: var(--shiki-dark-bg) !important;
   color: var(--shiki-dark) !important;

   & span {
    color: var(--shiki-dark) !important;
   }
 }
}

Suggested solution

(edit: make sure to see update at the end)

i was just thinking about this, and realized that the space toggle technique would be a good fit for this use case, as it would allow users to switch values with a single css declaration.

@media (prefers-color-scheme: dark) {
 :root {
   --is-shiki-dark: var(--yes);
 }
}

(where --yes: initial; is just a convenience constant)

the inline style implementation would look like this, with full support for complex textmate grammar.

<pre style="--is-shiki-dark: /* no */;">
 ...
  <span style="color: var(--is-shiki-dark, #ECEFF4) #6F42C1;">

this is already very good, but we can take this idea further:

  1. for full control over the cascade, a custom property could be used instead of color.

    - <span style="color: var(--is-shiki-dark, #ECEFF4) #6F42C1;">
    + <span style="--shiki-color: var(--is-shiki-dark, #ECEFF4) #6F42C1;">

    and shikiji could ship with a small stylesheet, which can be imported into user's desired cascade layer:

    :root {
      --no: ;
      --yes: initial;
      --is-shiki-dark: var(--no);
    }
    .shiki {
      background-color: var(--shiki-bg);
      color: var(--shiki-color);
    
      & span {
        color: var(--shiki-color);
      }
    }

    (this --shiki-color is an implementation detail that could be obscured/minified into something like --_)s-c. the user only needs to care about the public api, which is --is-shiki-dark)

  2. for supporting multiple themes, cyclic dependency space toggles can be used instead of regular space toggles.

    <pre>
     ...
      <span style="
       --_s-c-light: hotpink;
       --_s-c-dark: red;
       --_s-c-hc-light: black; /* hc means "high contrast", _ means implementation detail */
       --_s-c-hc-dark: white;
      ">

    and shikiji would ship with this small stylesheet that can be imported inside or outside a cascade layer.

    :root {
       --shiki-theme:     var(--shiki--light);
     
       --shiki--light:    var(--shiki-theme,);
       --shiki--dark:     var(--shiki-theme,);
       --shiki--hc-light: var(--shiki-theme,);
       --shiki--hc-dark:  var(--shiki-theme,);
    }
    
    .shiki,
    .shiki span {
       color:
         var(--shiki--light,    var(--_s-c-light))
         var(--shiki--dark,     var(--_s-c-dark))
         var(--shiki--hc-light, var(--_s-c-hc-light))
         var(--shiki--hc-dark,  var(--_s-c-hc-dark));
    }

    finally, the user only needs to set --shiki-theme in their own stylesheet.

    :root {
      --shiki-theme: var(--shiki--light);
    
      @media (prefers-contrast: more) {
        --shiki-theme: var(--shiki--hc-light);
      }
    
      @media (prefers-color-scheme: dark) {
        --shiki-theme: var(--shiki--dark);
      }
    
      @media (prefers-color-scheme: dark) and (prefers-contrast: more) {
        --shiki-theme: var(--shiki--hc-dark);
      }
    }

    here's a small demo showing this technique in action: stackblitz.com/edit/js-txy3pa

let me know what you think or if i can clarify anything.

Update

As of 3 minutes ago, there is support for multiple themes, complete with the ability to modify prefixes. This makes the scope of this change much smaller :D At this point, I would be ok with just replacing inline color style with --shiki-light, so that !important is not necessary in the custom css. Everything else could be left upto the user.


Alternative

css-variables theming, but as i understand this makes it difficult to achieve full support for complex syntax highlighting, so not ideal.

Additional context

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions