@ -0,0 +1,125 @@ |
|||||
|
# Adding Dark Mode Support to the Basic Theme |
||||
|
Basic Theme uses plain bootstrap and does not have any custom colors & styles. This article will show you how to add dark mode support to the [Basic Theme](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Basic-Theme). |
||||
|
|
||||
|
Bootstrap brings the [Color Modes](https://getbootstrap.com/docs/5.3/customize/color-modes/#dark-mode) feature with version **5.3**. This feature allows you to add dark mode support to your website with a single line of code. Adding the `data-bs-theme="dark"` attribute changes the color mode of the element to dark mode. |
||||
|
|
||||
|
## Instructions |
||||
|
|
||||
|
1. Create a new project with the following command: |
||||
|
```bash |
||||
|
abp new BasicThemeDarkMode -t app --theme basic |
||||
|
``` |
||||
|
|
||||
|
2. Create a component that toggles the color mode. |
||||
|
|
||||
|
- Create a new file named `Components/ChangeTheme/Default.cshtml`: |
||||
|
```html |
||||
|
<div class="text-light mt-1"> |
||||
|
<button class="btn text-light" href="#" id="ToolbarChangeTheme"> |
||||
|
<i class="fas fa-sun"></i> |
||||
|
</button> |
||||
|
</div> |
||||
|
``` |
||||
|
|
||||
|
- Create a new file named `Components/ChangeTheme/ChangeThemeViewComponent.cs`: |
||||
|
```csharp |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace BasicThemeDarkMode.Web.Components.ChangeTheme; |
||||
|
|
||||
|
[Widget(ScriptFiles = new[]{"/Components/ChangeTheme/ChangeTheme.js"})] |
||||
|
public class ChangeThemeViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
public IViewComponentResult Invoke() |
||||
|
{ |
||||
|
return View("~/Components/ChangeTheme/Default.cshtml"); |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
- Create a JavaScript that manages the last selected theme and toggles the color mode. It stores the last selected theme in the *local storage*. So, you don't need to store it in the database. |
||||
|
|
||||
|
- Create a new file named `Components/ChangeTheme/ChangeTheme.js`: |
||||
|
```js |
||||
|
$(function () { |
||||
|
function changeTheme(theme) { |
||||
|
window.localStorage.setItem('theme', theme); |
||||
|
document.getElementsByTagName('body')[0].setAttribute('data-bs-theme', theme); |
||||
|
} |
||||
|
|
||||
|
function toggleTheme(){ |
||||
|
getTheme() == 'light' ? changeTheme('dark') : changeTheme('light'); |
||||
|
} |
||||
|
|
||||
|
function getTheme(){ |
||||
|
return window.localStorage.getItem('theme') ?? 'dark'; |
||||
|
} |
||||
|
|
||||
|
function init(){ |
||||
|
let theme = getTheme(); |
||||
|
if(theme){ |
||||
|
changeTheme(theme); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
document.getElementById('ToolbarChangeTheme').addEventListener('click', () => { |
||||
|
toggleTheme(); |
||||
|
}); |
||||
|
|
||||
|
init(); |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
3. Create a new [Toolbar Contributor](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Toolbars) and add a newly created view component to the application toolbar. |
||||
|
|
||||
|
- Create a new class named `BasicThemeDarkModeToolbarContributor.cs`: |
||||
|
```csharp |
||||
|
using BasicThemeDarkMode.Web.Components.ChangeTheme; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars; |
||||
|
|
||||
|
namespace BasicThemeDarkMode.Web; |
||||
|
|
||||
|
public class BasicThemeDarkModeToolbarContributor : IToolbarContributor |
||||
|
{ |
||||
|
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context) |
||||
|
{ |
||||
|
if (context.Toolbar.Name == StandardToolbars.Main) |
||||
|
{ |
||||
|
context.Toolbar.Items |
||||
|
.Add(new ToolbarItem(typeof(ChangeThemeViewComponent))); |
||||
|
} |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
- Configure [Toolbar Options](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Toolbars) and add a newly created contributor: |
||||
|
```csharp |
||||
|
Configure<AbpToolbarOptions>(options => |
||||
|
{ |
||||
|
options.Contributors.Add(new BasicThemeDarkModeToolbarContributor()); |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
That's it! Now, you can toggle the color mode by clicking the sun icon in the toolbar: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
- Users Page in Dark Mode: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
- Settings Page in Dark Mode: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
- Login Page in Dark Mode: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
## Conclusion |
||||
|
|
||||
|
The theme is stored in **local storage** and it's initialized on the client-side. You can use **Cookies** to render the page in the last selected theme on **server-side** to prevent the flash effect while navigating pages. This document shows the concept of adding dark mode support of bootstrap to the Basic Theme. |
||||
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 189 KiB |
@ -0,0 +1,80 @@ |
|||||
|
# Caps Lock Directive |
||||
|
|
||||
|
In password inputs, You may want to show if Caps Lock is on. To make this even easier, you can use the `TrackCapsLockDirective` which has been exposed by the `@abp/ng.core` package. |
||||
|
|
||||
|
|
||||
|
## Getting Started |
||||
|
|
||||
|
`TrackCapsLockDirective` is standalone. In order to use the `TrackCapsLockDirective` in an HTML template, import it to related module or your standalone component: |
||||
|
|
||||
|
**Importing to NgModule** |
||||
|
```ts |
||||
|
import { TrackCapsLockDirective } from '@abp/ng.core'; |
||||
|
|
||||
|
@NgModule({ |
||||
|
//... |
||||
|
declarations: [ |
||||
|
..., |
||||
|
TestComponent |
||||
|
], |
||||
|
imports: [ |
||||
|
..., |
||||
|
TrackCapsLockDirective |
||||
|
], |
||||
|
}) |
||||
|
export class MyFeatureModule {} |
||||
|
``` |
||||
|
|
||||
|
## Usage |
||||
|
|
||||
|
The `TrackCapsLockDirective` is very easy to use. The directive's selector is **`abpCapsLock`**. By adding the `abpCapsLock` event to an element, you can track the status of Caps Lock. You can use this to warn user. |
||||
|
|
||||
|
See an example usage: |
||||
|
|
||||
|
**NgModule Component usage** |
||||
|
```ts |
||||
|
@Component({ |
||||
|
selector: 'test-component', |
||||
|
template: ` |
||||
|
<div class="d-flex flex-column"> |
||||
|
<label>Password</label> |
||||
|
<input (abpCapsLock)="capsLock = $event"/> |
||||
|
<i *ngIf="capsLock">icon</i> |
||||
|
</div> |
||||
|
` |
||||
|
}) |
||||
|
export class TestComponent{ |
||||
|
capsLock = false; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
**Standalone Component usage** |
||||
|
```ts |
||||
|
import { TrackCapsLockDirective } from '@abp/ng.core' |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'standalone-component', |
||||
|
standalone: true, |
||||
|
template: ` |
||||
|
<div class="d-flex flex-column"> |
||||
|
<label>Password</label> |
||||
|
<input (abpCapsLock)="capsLock = $event"/> |
||||
|
<i *ngIf="capsLock">icon</i> |
||||
|
</div> |
||||
|
`, |
||||
|
imports: [TrackCapsLockDirective] |
||||
|
}) |
||||
|
export class StandaloneComponent{ |
||||
|
capsLock = false; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
The `abpCapsLock` event has been added to the `<input>` element. Press Caps Lock to activate the `TrackCapsLockDirective`. |
||||
|
|
||||
|
See the result: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
To see Caps Lock icon press Caps Lock. |
||||
|
|
||||
|
 |
||||
@ -0,0 +1,77 @@ |
|||||
|
# Show Password Directive |
||||
|
|
||||
|
In password input, text can be shown easily via changing input type attribute to `text`. To make this even easier, you can use the `ShowPasswordDirective` which has been exposed by the `@abp/ng.core` package. |
||||
|
|
||||
|
|
||||
|
## Getting Started |
||||
|
`ShowPasswordDirective` is standalone. In order to use the `ShowPasswordDirective` in an HTML template, import it to related module or your standalone component: |
||||
|
|
||||
|
**Importing to NgModule** |
||||
|
```ts |
||||
|
import { ShowPasswordDirective } from '@abp/ng.core'; |
||||
|
|
||||
|
@NgModule({ |
||||
|
//... |
||||
|
declarations: [ |
||||
|
..., |
||||
|
TestComponent |
||||
|
], |
||||
|
imports: [ |
||||
|
..., |
||||
|
ShowPasswordDirective |
||||
|
], |
||||
|
}) |
||||
|
export class MyFeatureModule {} |
||||
|
``` |
||||
|
|
||||
|
## Usage |
||||
|
|
||||
|
The `ShowPasswordDirective` is very easy to use. The directive's selector is **`abpShowPassword`**. By adding the `abpShowPassword` attribute to an input element, you can activate the `ShowPasswordDirective` for the input element. |
||||
|
|
||||
|
See an example usage: |
||||
|
|
||||
|
**NgModule Component usage** |
||||
|
```ts |
||||
|
@Component({ |
||||
|
selector: 'test-component', |
||||
|
template: ` |
||||
|
<div class="d-flex flex-column"> |
||||
|
<label>Password</label> |
||||
|
<input [abpShowPassword]="showPassword"/> |
||||
|
<i (click)="showPassword = !showPassword">icon</i> |
||||
|
</div> |
||||
|
` |
||||
|
}) |
||||
|
export class TestComponent{ |
||||
|
showPassword = false; |
||||
|
} |
||||
|
``` |
||||
|
**Standalone Component usage** |
||||
|
```ts |
||||
|
import { ShowPasswordDirective } from '@abp/ng.core'; |
||||
|
@Component({ |
||||
|
selector: 'standalone-component', |
||||
|
standalone: true, |
||||
|
template: ` |
||||
|
<div class="d-flex flex-column"> |
||||
|
<label>Password</label> |
||||
|
<input [abpShowPassword]="showPassword"/> |
||||
|
<i (click)="showPassword = !showPassword">icon</i> |
||||
|
</div> |
||||
|
`, |
||||
|
imports: [ShowPasswordDirective] |
||||
|
}) |
||||
|
export class StandaloneComponent{ |
||||
|
showPassword = false; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
The `abpShowPassword` attribute has been added to the `<input>` element. Click icon to activate the `ShowPasswordDirective`. |
||||
|
|
||||
|
See the result: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
To see password input click icon. |
||||
|
|
||||
|
 |
||||
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.8 KiB |