2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Blazorアプリでダークモードを実装してみる

Posted at

ダークモードは、OS、アプリケーション、今や様々な場面で実装されています。
Blazorでtwitter風のダークモードを実装してみましょう。

サンプルコード

カスタムCSSによるUIの変更

「Blazor darkmode」で検索すると例がいくつか見つかりました。その中で、「Blazor WebAssembly - Dark Mode - CSS Variables - Applying Themes」というタイトルの動画を参考に、簡単にダークモードを実装してみたいと思います。

CSSのスコープ

Blazorプロジェクトを作成するといくつかのCSSファイルが作成されています。CSSの範囲を確認してみます。CSSの分離が行えるようになってから、app.cssに記述されていたスタイルがコンポーネントごとに設定できるのが確認できます。app.cssは全体に適応されます。app.cssに定義しておくことで、アプリケーション全体に適応できそうです。

pic.png

app.cssへの記述

全てのコンポーネントに適用されるapp.cssへ、コンポーネントに適応したい定義をあらかじめ書いておきます。デフォルトは::root、ダークブルーは.dark-mode-blue、ブラックは.dark-mode-blackとして、それぞれ適応したい色やスタイルを定義しておきます。

app.css
:root {
    /* white */
    --background: white;
    --font-color: black;
    --highlight: rgba(0,0,0,0.4);
    --highlight-2: #e2e3e5;
    --link: #0366d6;
    --background-img: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
    --border-color: #1861ac;
    --btn-font-color: #fff;
    --btn-background-color: #1b6ec2;
}

.dark-mode-blue {
    /* dark-mode blue */
    --background: rgb(21, 32, 43);
    --font-color: white;
    --highlight: rgb(21, 32, 43);
    --highlight-2: #414648;
    --link: #3ca4ff;
    --background-img: none;
    --border-color: #3ca4ff;
    --btn-font-color: white;
    --btn-background-color: rgb(21, 32, 43);
}

.dark-mode-black {
    /* dark-mode black */
    --background: black;
    --font-color: white;
    --highlight: black;
    --highlight-2: #414648;
    --link: #3ca4ff;
    --background-img: none;
    --border-color: #3ca4ff;
    --btn-font-color: white;
    --btn-background-color: black
}

これらのカスタムCSSを、ユーザーが選択したものが適用したい箇所に記述してみましょう。
例えば、MainLayoutのコンポーネントの背景色と文字色は次のようになります。

MainLayout.razor.css
div.main {
    background-color: var(--background);
    color: var(--font-color);
}

ダークモードの適用

適用したいスタイルを使いたいところで指定します。今回は、twitterのようにすべてにダークモードを指定したかったので、最上位のpageに対し、ダークモードを適用しています。
StateContainerは、適用するデザインの状態管理クラスです。文字列Propertyの変更とともにコンポーネントのStateHasChangedを呼び出して、再描写を行えるようにしておきます。

(参考)[ASP.NET Core Blazor 状態管理]
(https://docs.microsoft.com/ja-jp/aspnet/core/blazor/state-management?view=aspnetcore-5.0&pivots=webassembly)

MainLayout.razor
@inherits LayoutComponentBase

@implements IDisposable
@inject StateContainer StateContainer

<div class="page @(StateContainer.Property)"> 👈 ここで全体にスタイルが適用されるように指定
    <div class="sidebar">
        <NavMenu StateContainer="StateContainer"/>
    </div>

    <div class="main">
        <div class="top-row px-4">
            <a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a>
        </div>

        <div class="content px-4">
            @Body
        </div>
    </div>
</div>



@code {

    protected override void OnInitialized()
    {
        StateContainer.OnChange += StateHasChanged;
    }

    public void Dispose()
    {
        StateContainer.OnChange -= StateHasChanged;
    }
}

ダークモードへの切り替え

ダークモードへの切り替えは、StateContainerPropertyに、CSSで定義したクラス名がセットされることで、コンポーネントのStateHasChangedが呼ばれ、UIに反映されます。
Blazorではコンポーネント間におけるデータの受け渡しにStateContainerのような状態管理は必要になってきますね🤔

NavBar.razor
<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">BlazorDarkMode</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="fetchdata">
                <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
            </NavLink>
        </li>
        👇ボタンにより適応したいスタイルのクラス名をStateContainerのPropertyにセット
        <li class="nav-item px-3">
            <button class="btn btn-primary " @onclick="@(_=>StateContainer.Property = "")">デフォルト</button>
        </li>
        <li class="nav-item px-3">
            <button class="btn btn-primary dark-mode-blue" @onclick="@(_=>StateContainer.Property = "dark-mode-blue")">ダークブルー</button>
        </li>
        <li class="nav-item px-3">
            <button class="btn btn-primary dark-mode-black" @onclick="@(_=>StateContainer.Property = "dark-mode-black")">ブラック</button>
        </li>

    </ul>
</div>

@code {

    [Parameter]
    public StateContainer StateContainer { get; set; }

    private bool collapseNavMenu = true;

    private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
}

参考

Blazor WebAssembly - Dark Mode - CSS Variables - Applying Themes
ASP.NET Core Blazor 状態管理

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?