【问题标题】:How to dynamically switch theme with vmware clarity如何使用 vmware 清晰度动态切换主题
【发布时间】:2017-12-01 23:28:19
【问题描述】:

Vmware Clarity 0.10.16 刚刚发布了新的深色主题。这太棒了!

他们描述了如何添加新主题,但没有说明在页面内动态更改它的可能性。是因为不可行吗?

如果是,我该如何使用 Angular 4+ 来做到这一点?任何网站可以帮助我解释如何实现这一点?

提前致谢!

【问题讨论】:

    标签: angular vmware-clarity


    【解决方案1】:

    Clarity 现在附带浅色和深色主题的样式表。我们记录了如何使用 hereangular-cliwebpack 构建配置来使用它们。这意味着一旦构建了应用程序,这就是它唯一的风格。

    我对如何实现主题切换器以在两者之间切换有一些想法。下面是一个粗略的想法,我可能会从我的原型开始:

    1. 在没有任何主题 css 文件的情况下构建应用程序(根本没有清晰的样式)
    2. 将两个 css 文件复制到 assets 文件夹(在构建期间)
    3. <head> 中的样式表编写一个指令或组件,该指令或组件可以采用src 的@Input
    4. 将两个路径 /path/to/light.css/path/to/dark.css 存储在服务中,以便应用程序可以传递活动主题值并在需要时对其进行修改。
    5. 将服务添加到我们希望让用户更新主题的应用程序组件。

    这是否为您的应用提供了一些想法?

    我将在原型工作后在这里更新,以便您可以看到它的实际效果并找到源代码。

    【讨论】:

    • 有趣。我很想看看你的 POC。您如何看待此处描述的技术:stackoverflow.com/questions/42481704/…
    • 我认为要支持这样的方法,我们必须为每个主题构建和交付样式作为单个 style.css 文件。即使用户不需要一个主题或另一个主题,这也会使我们的 css 文件的大小翻倍。我想探索的一种方法是CSS custom properties (CSS variables),以便可以从应用程序方面应用主题。最大的障碍是 IE11 缺乏支持。 (Edge v15 确实支持它)所以这也意味着添加一个 polyfill 以支持 IE11。
    • 你能对你的想法进行演示吗?还是您的想法与杰里米的回答相似。如果能以某种方式规避最初的滞后,那就太好了。
    • 嘿,我的想法和 Jeremy 的很相似。
    【解决方案2】:

    我已经建立了一个概念证明,你可以如何做到这一点,但它确实有一些限制。由于一次只能包含一个主题文件,因此渲染正确的主题可能会有一些延迟,因为它发生在 Angular 渲染周期的后期。只有当浏览器的缓存为空时才会有大问题,因为后续访问会很快呈现,但这是这里的主要考虑因素。这是一个开始,您也许可以在此基础上构建更强大的东西。

    https://stackblitz.com/edit/clarity-theme-switcher?file=app%2Fapp.component.ts

    【讨论】:

    • 在尝试时得到“模块 'AppModule' 评估 main.ts 导入的意外值 'undefined'”。 :-(。另外,我们不可能在这里描述一些东西?stackoverflow.com/questions/42481704/…
    • 它目前在 Chrome 上为我工作,我还没有测试过其他浏览器。 StackBlitz 仍然是新的,因此可能存在问题。这可能是一种选择,尽管它也有点老套。您必须自己重建 Clarity 主题才能完成这项工作,然后将两个版本都发送给用户,无论他们使用的是哪个主题。这不是一个微不足道的代码量。我正在研究其他选项来解决这些缺点。
    • @JeremyWilken 难道不能以某种方式强制执行角度渲染周期吗?
    • 当然你可以强制一个新的变更检测周期,但这不是这里的问题。问题是主题 css 文件在浏览器中加载所需的时间。
    • 我想知道是否可以实现类似 Google 的 Material Design 主题。他们正在使用 mixins 将所有样式放入一个类中。 material.angular.io/guide/theming#multiple-themes
    【解决方案3】:

    这是我所做的:

    1. 我创建了两个 SCSS 样式表。将它们都加载到 angular.json 配置中。在样式表 1 中,导入 Clarity default 主题。在样式表 2 中,在类选择器中导入 Clarity dark 主题。像这样:
    .dark-mode {
        @import "~@clr/ui/src/utils/theme.dark.clarity"; // Dark theme variables
        @import '~@clr/ui/src/utils/components.clarity';
    
        // @import third party styling...
    
        // Fix styling HTML-tag.
        // node_modules\@clr\ui\src\typography\_typography.clarity.scss
        & html {
            color: $clr-global-font-color;
            font-family: $clr-font;
            font-size: $clr-baseline-px;
        }
    }
    
    1. AppComponent 构造函数中导入@Inject(DOCUMENT) private document: Document
    2. 为了启用暗模式,我使用了以下代码:
    this.document.documentElement.classList.add('dark-mode');
    

    我使用localStorage 来存储用户的偏好。

    这样做的优点是:

    • 没有 FOUC。
    • 我不需要调整现有样式表或替换现有样式表。

    缺点是:

    • 每个 CSS 选择器都将在 .dark-mode 类选择器中复制。这会使文件大小加倍。我不认为这有什么问题。
    • 需要对html-元素样式进行小修复。上述示例中包含的解决方案。

    【讨论】:

    • 这是最好的答案
    【解决方案4】:

    我已经实现了它,在 index.html 中添加了一个链接

    <link id="theme" rel="stylesheet" href="https://unpkg.com/@clr/ui/clr-ui.min.css" />
    

    然后在你的 app.component.ts 中

    linkRef: HTMLLinkElement;
    themes = [
        'https://unpkg.com/@clr/ui/clr-ui.min.css',
        'https://unpkg.com/@clr/ui/clr-ui-dark.min.css'
    ];
    constructor(){
      this.linkRef = document.getElementById('theme') as HTMLLinkElement;
      // you could change here the theme if you have it stored in local storage
      // for example
      // const theme = localStorage.getItem('theme')
      // if(theme) this.linkRef.href = this.themes[parseInt(theme)]
    }
    setTheme(dark:bool){
      this.linkRef.href = this.themes[dark ? 1 : 0]
    }
    

    【讨论】:

      猜你喜欢
      • 2020-10-09
      • 1970-01-01
      • 2017-08-05
      • 2022-09-23
      • 2019-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多