support dark mode UI

This commit is contained in:
Pig Fang 2021-06-06 14:27:21 +08:00
parent 1ad19878f8
commit 7e04f72292
No known key found for this signature in database
GPG Key ID: A8198F548DADA9E2
14 changed files with 69 additions and 15 deletions

View File

@ -20,6 +20,7 @@ use Lorisleiva\LaravelSearchString\Concerns\SearchString;
* @property int $score * @property int $score
* @property int $permission * @property int $permission
* @property string $ip * @property string $ip
* @property bool $is_dark_mode
* @property string $last_sign_at * @property string $last_sign_at
* @property string $register_at * @property string $register_at
* @property bool $verified * @property bool $verified
@ -53,6 +54,7 @@ class User extends Authenticatable
'avatar' => 'integer', 'avatar' => 'integer',
'permission' => 'integer', 'permission' => 'integer',
'verified' => 'bool', 'verified' => 'bool',
'is_dark_mode' => 'bool',
]; ];
protected $hidden = ['password', 'remember_token']; protected $hidden = ['password', 'remember_token'];
@ -65,6 +67,7 @@ class User extends Authenticatable
'last_sign_at' => ['date' => true], 'last_sign_at' => ['date' => true],
'register_at' => ['date' => true], 'register_at' => ['date' => true],
'verified' => ['boolean' => true], 'verified' => ['boolean' => true],
'is_dark_mode' => ['boolean' => true],
]; ];
public function isAdmin(): bool public function isAdmin(): bool

View File

@ -22,6 +22,7 @@ class ViewServiceProvider extends ServiceProvider
'site_name' => option_localized('site_name'), 'site_name' => option_localized('site_name'),
'navbar_color' => $color, 'navbar_color' => $color,
'color_mode' => in_array($color, $lightColors) ? 'light' : 'dark', 'color_mode' => in_array($color, $lightColors) ? 'light' : 'dark',
'dark_mode' => (bool) optional(auth()->user())->is_dark_mode,
'locale' => str_replace('_', '-', app()->getLocale()), 'locale' => str_replace('_', '-', app()->getLocale()),
]); ]);
}); });
@ -46,7 +47,11 @@ class ViewServiceProvider extends ServiceProvider
View::composer('shared.user-menu', Composers\UserMenuComposer::class); View::composer('shared.user-menu', Composers\UserMenuComposer::class);
View::composer('shared.sidebar', function ($view) { View::composer('shared.sidebar', function ($view) {
$view->with('sidebar_color', option('sidebar_color')); $isDarkMode = (bool) optional(auth()->user())->is_dark_mode;
$color = option('sidebar_color');
$color = $isDarkMode ? str_replace('light', 'dark', $color) : $color;
$view->with('sidebar_color', $color);
}); });
View::composer('shared.side-menu', Composers\SideMenuComposer::class); View::composer('shared.side-menu', Composers\SideMenuComposer::class);

View File

@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddIsDarkModeField extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('is_dark_mode')->after('ip')->default(false);
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('is_dark_mode');
});
}
}

View File

@ -80,7 +80,9 @@ const Viewer: React.FC<Props> = (props) => {
const [paused, setPaused] = useState(false) const [paused, setPaused] = useState(false)
const [running, setRunning] = useState(false) const [running, setRunning] = useState(false)
const [reset, setReset] = useState(0) const [reset, setReset] = useState(0)
const [background, setBackground] = useState('#fff') const [background, setBackground] = useState(() =>
document.body.classList.contains('dark-mode') ? '#6c757d' : '#fff',
)
const [bgPicture, setBgPicture] = useState(-1) const [bgPicture, setBgPicture] = useState(-1)
const indicator = (() => { const indicator = (() => {

View File

@ -7,6 +7,7 @@ export type User = {
avatar: number avatar: number
permission: UserPermission permission: UserPermission
ip: string ip: string
is_dark_mode: boolean
last_sign_at: string last_sign_at: string
register_at: string register_at: string
verified: boolean verified: boolean

View File

@ -13,8 +13,14 @@ interface ChartData {
} }
async function createChart(el: HTMLDivElement) { async function createChart(el: HTMLDivElement) {
const isDarkMode = document.body.classList.contains('dark-mode')
const textColor = isDarkMode ? '#fff' : '#000'
const chart = echarts.init(el, void 0, { renderer: 'svg' }) const chart = echarts.init(el, void 0, { renderer: 'svg' })
chart.setOption({ chart.setOption({
textStyle: {
color: textColor,
},
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: { axisPointer: {
@ -27,6 +33,9 @@ async function createChart(el: HTMLDivElement) {
], ],
legend: { legend: {
data: [], data: [],
textStyle: {
color: textColor,
},
}, },
xAxis: [ xAxis: [
{ {

View File

@ -19,6 +19,9 @@ const ActionButton = styled.a`
transition-property: color; transition-property: color;
transition-duration: 0.3s; transition-duration: 0.3s;
color: #000; color: #000;
.dark-mode & {
color: #fff;
}
&:hover { &:hover {
color: #999; color: #999;
} }

View File

@ -131,4 +131,15 @@ describe('background', () => {
baseElement.querySelector<HTMLDivElement>('.card-body')!.style.background, baseElement.querySelector<HTMLDivElement>('.card-body')!.style.background,
).toStartWith('url') ).toStartWith('url')
}) })
it('default for dark mode', () => {
document.body.classList.add('dark-mode')
const { baseElement } = render(<Viewer isAlex={false} />)
expect(
baseElement.querySelector<HTMLDivElement>('.card-body')!.style.background,
).toBe('rgb(108, 117, 125)')
document.body.classList.remove('dark-mode')
})
}) })

View File

@ -5,7 +5,7 @@
<title>{% block title %}{% endblock %} - {{ site_name }}</title> <title>{% block title %}{% endblock %} - {{ site_name }}</title>
</head> </head>
<body class="hold-transition sidebar-mini"> <body class="{{ dark_mode ? 'dark-mode' : '' }} hold-transition sidebar-mini">
<div class="wrapper"> <div class="wrapper">
{{ include('shared.header') }} {{ include('shared.header') }}
{{ include('shared.sidebar', {scope: 'admin'}) }} {{ include('shared.sidebar', {scope: 'admin'}) }}
@ -14,7 +14,7 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="d-flex justify-content-between flex-wrap"> <div class="d-flex justify-content-between flex-wrap">
<div> <div>
<h1 class="m-0 text-dark">{{ block('title') }}</h1> <h1 class="m-0">{{ block('title') }}</h1>
</div> </div>
<div> <div>
<div class="breadcrumb"></div> <div class="breadcrumb"></div>

View File

@ -24,7 +24,7 @@
</div> </div>
{% endif %} {% endif %}
{{ csrf_field() }} {{ csrf_field() }}
<div class="container-fluid my-4 px-2"> <div class="container-fluid my-4 px-4">
<div class="row mb-3"> <div class="row mb-3">
<div class="col-sm-3">{{ trans('admin.i18n.group') }}</div> <div class="col-sm-3">{{ trans('admin.i18n.group') }}</div>
<div class="col-sm-9"> <div class="col-sm-9">
@ -54,11 +54,9 @@
</div> </div>
</div> </div>
</form> </form>
<div class="callout callout-info"> <a class="btn btn-block btn-outline-info" href="https://blessing.netlify.com/ui-text.html" target="_blank">
<a href="https://blessing.netlify.com/ui-text.html" target="_blank"> {{ trans('admin.i18n.tip') }}
{{ trans('admin.i18n.tip') }} </a>
</a>
</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -5,7 +5,7 @@
<title>{% block title %}{% endblock %} - {{ site_name }}</title> <title>{% block title %}{% endblock %} - {{ site_name }}</title>
</head> </head>
<body class="hold-transition layout-top-nav"> <body class="{{ dark_mode ? 'dark-mode' : '' }} hold-transition layout-top-nav">
<div class="wrapper"> <div class="wrapper">
<nav class="main-header navbar navbar-expand navbar-{{ navbar_color }} navbar-{{ color_mode }} ml-0"> <nav class="main-header navbar navbar-expand navbar-{{ navbar_color }} navbar-{{ color_mode }} ml-0">
<div class="container"> <div class="container">

View File

@ -9,7 +9,7 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="d-flex justify-content-between flex-wrap"> <div class="d-flex justify-content-between flex-wrap">
<div> <div>
<h1 class="m-0 text-dark">{{ trans('skinlib.show.title') }}</h1> <h1 class="m-0">{{ trans('skinlib.show.title') }}</h1>
</div> </div>
<div> <div>
<div class="breadcrumb"></div> <div class="breadcrumb"></div>

View File

@ -9,7 +9,7 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="d-flex justify-content-between flex-wrap"> <div class="d-flex justify-content-between flex-wrap">
<div> <div>
<h1 class="m-0 text-dark">{{ block('title') }}</h1> <h1 class="m-0">{{ block('title') }}</h1>
</div> </div>
<div> <div>
<div class="breadcrumb"></div> <div class="breadcrumb"></div>

View File

@ -5,7 +5,7 @@
<title>{% block title %}{% endblock %} - {{ site_name }}</title> <title>{% block title %}{% endblock %} - {{ site_name }}</title>
</head> </head>
<body class="hold-transition sidebar-mini"> <body class="{{ dark_mode ? 'dark-mode' : '' }} hold-transition sidebar-mini">
<div class="wrapper"> <div class="wrapper">
{{ include('shared.header') }} {{ include('shared.header') }}
{{ include('shared.sidebar', {scope: 'user'}) }} {{ include('shared.sidebar', {scope: 'user'}) }}
@ -14,7 +14,7 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="d-flex justify-content-between flex-wrap"> <div class="d-flex justify-content-between flex-wrap">
<div> <div>
<h1 class="m-0 text-dark">{{ block('title') }}</h1> <h1 class="m-0">{{ block('title') }}</h1>
</div> </div>
<div> <div>
<div class="breadcrumb"></div> <div class="breadcrumb"></div>