Skip to content

Commit

Permalink
Merge pull request #583 from getformwork/feature/improved-color-schemes
Browse files Browse the repository at this point in the history
Improve color schemes handling
  • Loading branch information
giuscris authored Oct 6, 2024
2 parents 8d68f83 + 5753923 commit d1978be
Show file tree
Hide file tree
Showing 19 changed files with 141 additions and 81 deletions.
28 changes: 6 additions & 22 deletions formwork/src/Panel/Controllers/AbstractController.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,12 @@ protected function translate(string $key, int|float|string|Stringable ...$argume
protected function defaults(): array
{
return [
'location' => $this->name,
'site' => $this->site(),
'panel' => $this->panel(),
'csrfToken' => $this->csrfToken->get($this->panel()->getCsrfTokenName()),
'modals' => $this->modals(),
'colorScheme' => $this->getColorScheme(),
'navigation' => [
'location' => $this->name,
'site' => $this->site(),
'panel' => $this->panel(),
'csrfToken' => $this->csrfToken->get($this->panel()->getCsrfTokenName()),
'modals' => $this->modals(),
'navigation' => [
'dashboard' => [
'label' => $this->translate('panel.dashboard.dashboard'),
'uri' => '/dashboard/',
Expand Down Expand Up @@ -235,19 +234,4 @@ protected function view(string $name, array $data = []): string
);
return $view->render();
}

/**
* Get color scheme
*/
private function getColorScheme(): string
{
$default = $this->config->get('system.panel.colorScheme');
if ($this->panel()->isLoggedIn()) {
if ($this->user()->colorScheme() === 'auto') {
return $this->request->cookies()->get('formwork_preferred_color_scheme', $default);
}
return $this->user()->colorScheme();
}
return $default;
}
}
13 changes: 13 additions & 0 deletions formwork/src/Panel/Panel.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Formwork\Http\Request;
use Formwork\Http\Session\MessageType;
use Formwork\Languages\LanguageCodes;
use Formwork\Users\ColorScheme;
use Formwork\Users\User;
use Formwork\Users\Users;
use Formwork\Utils\FileSystem;
Expand Down Expand Up @@ -143,6 +144,18 @@ public function assets(): Assets
return $this->assets ?? ($this->assets = new Assets($this->config->get('system.panel.paths.assets'), $this->realUri('/assets/')));
}

public function colorScheme(): ColorScheme
{
$colorScheme = ColorScheme::from($this->config->get('system.panel.colorScheme'));
if ($this->isLoggedIn()) {
if ($this->user()->colorScheme() === ColorScheme::Auto) {
return ColorScheme::from($this->request->cookies()->get('formwork_preferred_color_scheme', $colorScheme->value));
}
return $this->user()->colorScheme();
}
return $colorScheme;
}

/**
* Available translations helper
*
Expand Down
19 changes: 19 additions & 0 deletions formwork/src/Users/ColorScheme.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Formwork\Users;

enum ColorScheme: string
{
case Light = 'light';
case Dark = 'dark';
case Auto = 'auto';

public function getCompatibleSchemes(): string
{
return match ($this) {
self::Light => 'light',
self::Dark => 'dark',
self::Auto => 'light dark',
};
}
}
5 changes: 5 additions & 0 deletions formwork/src/Users/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ public function role(): Role
return $this->role;
}

public function colorScheme(): ColorScheme
{
return ColorScheme::from($this->data['colorScheme']);
}

/**
* Return user permissions
*/
Expand Down
2 changes: 1 addition & 1 deletion panel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},
"scripts": {
"build": "yarn build:css && yarn build:js",
"build:css": "sass ./src/scss/panel.scss:./assets/css/panel.min.css ./src/scss/panel-dark.scss:./assets/css/panel-dark.min.css --style=compressed --no-source-map",
"build:css": "sass ./src/scss/panel.scss:./assets/css/panel.min.css --style=compressed --no-source-map",
"build:js": "tsc && esbuild ./src/ts/app.ts --outfile=./assets/js/app.min.js --bundle --format=iife --global-name=Formwork --target=es6 --minify",
"watch:css": "yarn build:css --watch",
"watch:js": "yarn build:js --watch",
Expand Down
2 changes: 1 addition & 1 deletion panel/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@
'panel.checkAssets' => [
'action' => static function (Config $config, ViewFactory $viewFactory) {
$path = $config->get('system.panel.paths.assets');
$assets = ['css/panel.min.css', 'css/panel-dark.min.css', 'js/app.min.js'];
$assets = ['css/panel.min.css', 'js/app.min.js'];

foreach ($assets as $asset) {
$assetPath = FileSystem::joinPaths($path, $asset);
Expand Down
12 changes: 0 additions & 12 deletions panel/src/scss/components/_dark-color-scheme.scss

This file was deleted.

4 changes: 2 additions & 2 deletions panel/src/scss/components/_files-list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
display: block;
padding: 0 0.375rem;
border-radius: $border-radius;
background-color: var(--color-tooltip-light);
background-color: var(--color-tooltip);
font-size: $font-size-xs;
text-align: center;
@include user-select-none;
Expand All @@ -101,7 +101,7 @@
.is-thumbnails .dropdown-button {
margin-top: 0.25rem;
margin-right: 0.25rem;
background-color: var(--color-tooltip-light);
background-color: var(--color-tooltip);

&:hover,
&:focus {
Expand Down
2 changes: 1 addition & 1 deletion panel/src/scss/components/_tooltip.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
min-width: 2rem;
padding: 0.25rem 0.5rem;
border-radius: $border-radius;
background-color: var(--color-tooltip-dark);
background-color: var(--color-tooltip-inverted);
color: var(--color-base-900);
font-size: $font-size-xs;
pointer-events: none;
Expand Down
2 changes: 1 addition & 1 deletion panel/src/scss/components/_users.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
}

.user-summary-image .dropdown-button {
background-color: var(--color-tooltip-light);
background-color: var(--color-tooltip);
}

.user-summary-image img {
Expand Down
68 changes: 45 additions & 23 deletions panel/src/scss/components/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,30 @@
// Colors
// ===

$color-base-100: $color-gray-100 !default;
$color-base-200: $color-gray-200 !default;
$color-base-300: $color-gray-300 !default;
$color-base-400: $color-gray-400 !default;
$color-base-500: $color-gray-500 !default;
$color-base-600: $color-gray-600 !default;
$color-base-700: $color-gray-700 !default;
$color-base-800: $color-gray-800 !default;
$color-base-900: $color-gray-900 !default;
$color-base-light-100: $color-gray-100;
$color-base-light-200: $color-gray-200;
$color-base-light-300: $color-gray-300;
$color-base-light-400: $color-gray-400;
$color-base-light-500: $color-gray-500;
$color-base-light-600: $color-gray-600;
$color-base-light-700: $color-gray-700;
$color-base-light-800: $color-gray-800;
$color-base-light-900: $color-gray-900;

$color-base-dark-100: #f2f2f3;
$color-base-dark-200: #c4c7ca;
$color-base-dark-300: #979ca1;
$color-base-dark-400: #7c8288;
$color-base-dark-500: #4b4f53;
$color-base-dark-600: #333638;
$color-base-dark-700: #292b2e;
$color-base-dark-800: #1f2123;
$color-base-dark-900: #181a1b;

$color-backdrop: rgba($color-blue-100, 0.5);
$color-selection: rgba($color-blue-500, 0.25);
$color-focusring: rgba($color-blue-500, 0.375);

$color-tooltip-dark: rgba($color-base-100, 0.875);
$color-tooltip-light: rgba($color-base-600, 0.875);

$color-shadow-sm: rgba($color-blue-100, 3.75%);
$color-shadow-md: rgba($color-blue-100, 7.5%);
$color-shadow-lg: rgba($color-blue-100, 15%);
Expand All @@ -33,18 +40,18 @@ $color-shadow-lg: rgba($color-blue-100, 15%);
--color-shadow-md: #{$color-shadow-md};
--color-shadow-lg: #{$color-shadow-lg};

--color-tooltip-dark: #{$color-tooltip-dark};
--color-tooltip-light: #{$color-tooltip-light};
--color-tooltip-inverted: #{rgba($color-base-light-100, 0.875)};
--color-tooltip: #{rgba($color-base-light-600, 0.875)};

--color-base-100: #{$color-base-100};
--color-base-200: #{$color-base-200};
--color-base-300: #{$color-base-300};
--color-base-400: #{$color-base-400};
--color-base-500: #{$color-base-500};
--color-base-600: #{$color-base-600};
--color-base-700: #{$color-base-700};
--color-base-800: #{$color-base-800};
--color-base-900: #{$color-base-900};
--color-base-100: #{$color-base-light-100};
--color-base-200: #{$color-base-light-200};
--color-base-300: #{$color-base-light-300};
--color-base-400: #{$color-base-light-400};
--color-base-500: #{$color-base-light-500};
--color-base-600: #{$color-base-light-600};
--color-base-700: #{$color-base-light-700};
--color-base-800: #{$color-base-light-800};
--color-base-900: #{$color-base-light-900};

--color-accent-100: var(--color-blue-100);
--color-accent-200: var(--color-blue-200);
Expand Down Expand Up @@ -86,6 +93,21 @@ $color-shadow-lg: rgba($color-blue-100, 15%);
--color-danger-800: var(--color-red-800);
--color-danger-900: var(--color-red-900);
}

:root.color-scheme-dark {
--color-base-100: #{$color-base-dark-100};
--color-base-200: #{$color-base-dark-200};
--color-base-300: #{$color-base-dark-300};
--color-base-400: #{$color-base-dark-400};
--color-base-500: #{$color-base-dark-500};
--color-base-600: #{$color-base-dark-600};
--color-base-700: #{$color-base-dark-700};
--color-base-800: #{$color-base-dark-800};
--color-base-900: #{$color-base-dark-900};

--color-tooltip-inverted: #{rgba($color-base-dark-100, 0.875)};
--color-tooltip: #{rgba($color-base-dark-600, 0.875)};
}
/* stylelint-enable */

$font-colors: (
Expand Down
2 changes: 1 addition & 1 deletion panel/src/scss/components/forms/_forms-base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@

.form-select {
padding: 0.25rem 1.5rem 0.25rem 0.5rem;
background: var(--color-base-900) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 24'><path fill='#{urlencode-color($color-base-300)}' d='M0 0h32L16 24z'/></svg>") no-repeat right 0.75rem center;
background: var(--color-base-900) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 24'><path fill='#{urlencode-color($color-gray-300)}' d='M0 0h32L16 24z'/></svg>") no-repeat right 0.75rem center;
background-color: var(--color-base-900);
background-size: 8px 6px;
/* stylelint-disable-next-line scss/at-extend-no-missing-placeholder */
Expand Down
4 changes: 2 additions & 2 deletions panel/src/scss/components/forms/_forms-editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@

.cm-s-formwork .cm-formatting-quote + .cm-quote {
padding-left: 1.25rem;
background: var(--color-base-900) url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="#{urlencode-color($color-base-300)}" viewBox="0 0 16 16"><path d="M4.195 12.864a.247.247 0 01-.312.019l-1.363-.976a.254.254 0 01-.034-.382c.512-.539.899-1.04 1.16-1.5.24-.426.418-.86.534-1.303a.239.239 0 00-.236-.296H2.25a.25.25 0 01-.25-.25V4.25A.25.25 0 012.25 4h4.316a.25.25 0 01.25.25v2.762c0 1.116-.2 2.157-.602 3.124-.382.92-1.055 1.83-2.019 2.728zm7.184 0a.247.247 0 01-.312.019l-1.363-.976a.254.254 0 01-.034-.382c.512-.539.899-1.04 1.16-1.5.24-.426.418-.86.534-1.303a.239.239 0 00-.236-.296H9.434a.25.25 0 01-.25-.25V4.25a.25.25 0 01.25-.25h4.316a.25.25 0 01.25.25v2.762c0 1.116-.2 2.157-.602 3.124-.382.92-1.055 1.83-2.019 2.728z"/></svg>') no-repeat left center;
background: var(--color-base-900) url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="#{urlencode-color($color-gray-300)}" viewBox="0 0 16 16"><path d="M4.195 12.864a.247.247 0 01-.312.019l-1.363-.976a.254.254 0 01-.034-.382c.512-.539.899-1.04 1.16-1.5.24-.426.418-.86.534-1.303a.239.239 0 00-.236-.296H2.25a.25.25 0 01-.25-.25V4.25A.25.25 0 012.25 4h4.316a.25.25 0 01.25.25v2.762c0 1.116-.2 2.157-.602 3.124-.382.92-1.055 1.83-2.019 2.728zm7.184 0a.247.247 0 01-.312.019l-1.363-.976a.254.254 0 01-.034-.382c.512-.539.899-1.04 1.16-1.5.24-.426.418-.86.534-1.303a.239.239 0 00-.236-.296H9.434a.25.25 0 01-.25-.25V4.25a.25.25 0 01.25-.25h4.316a.25.25 0 01.25.25v2.762c0 1.116-.2 2.157-.602 3.124-.382.92-1.055 1.83-2.019 2.728z"/></svg>') no-repeat left center;
background-size: 1rem 1rem;
}

Expand Down Expand Up @@ -193,7 +193,7 @@
display: inline;
padding: 0 0.25rem 0 1.5rem;
border-radius: $border-radius;
background: var(--color-base-900) url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="#{urlencode-color($color-base-300)}" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M14.5 3.5h-13v9h13v-9zM1.5 2A1.5 1.5 0 000 3.5v9A1.5 1.5 0 001.5 14h13a1.5 1.5 0 001.5-1.5v-9A1.5 1.5 0 0014.5 2h-13z" clip-rule="evenodd"/><path fill-rule="evenodd" d="M5.584 8.09a.25.25 0 00-.409.018l-3.444 5.427-1.266-.804 3.444-5.426a1.75 1.75 0 012.864-.13l1.47 1.91a.25.25 0 00.23.096l2.679-.356a1.75 1.75 0 011.524.557l2.883 3.168-1.109 1.01-2.883-3.168a.25.25 0 00-.218-.08l-2.678.356A1.75 1.75 0 017.054 10l-1.47-1.91z" clip-rule="evenodd"/><path d="M11.5 6.5a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0z"/></svg>') no-repeat left 0.25rem center;
background: var(--color-base-900) url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="#{urlencode-color($color-gray-300)}" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M14.5 3.5h-13v9h13v-9zM1.5 2A1.5 1.5 0 000 3.5v9A1.5 1.5 0 001.5 14h13a1.5 1.5 0 001.5-1.5v-9A1.5 1.5 0 0014.5 2h-13z" clip-rule="evenodd"/><path fill-rule="evenodd" d="M5.584 8.09a.25.25 0 00-.409.018l-3.444 5.427-1.266-.804 3.444-5.426a1.75 1.75 0 012.864-.13l1.47 1.91a.25.25 0 00.23.096l2.679-.356a1.75 1.75 0 011.524.557l2.883 3.168-1.109 1.01-2.883-3.168a.25.25 0 00-.218-.08l-2.678.356A1.75 1.75 0 017.054 10l-1.47-1.91z" clip-rule="evenodd"/><path d="M11.5 6.5a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0z"/></svg>') no-repeat left 0.25rem center;
background-color: var(--color-base-700);
background-size: 1rem 1rem;
color: var(--color-base-100);
Expand Down
2 changes: 1 addition & 1 deletion panel/src/scss/components/forms/_forms-image.scss
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
display: block;
padding: 0 0.375rem;
border-radius: $border-radius;
background-color: var(--color-tooltip-light);
background-color: var(--color-tooltip);
content: attr(data-filename);
font-size: $font-size-xs;
text-align: center;
Expand Down
2 changes: 0 additions & 2 deletions panel/src/scss/panel-dark.scss

This file was deleted.

41 changes: 35 additions & 6 deletions panel/src/ts/components/color-scheme.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,59 @@
import { getCookies, setCookie } from "../utils/cookies";
import { $ } from "../utils/selectors";
import { app } from "../app";

type ColorSchemeName = "light" | "dark";
type ColorSchemePreference = ColorSchemeName | "light dark";

export class ColorScheme {
constructor() {
const setPreferredColorScheme = () => {
const getSupportedColorSchemes = (): ColorSchemePreference => {
const meta = $("meta[name=color-scheme]") as HTMLMetaElement;
if (!meta) {
return "light dark";
}
switch (meta.content) {
case "light":
return "light";
case "dark":
return "dark";
default:
return "light dark";
}
};

const setColorScheme = (colorScheme: ColorSchemeName) => {
document.documentElement.classList.remove("color-scheme-light", "color-scheme-dark");
document.documentElement.classList.add(`color-scheme-${colorScheme}`);
};

const setPreferredColorScheme = (event: Event) => {
const cookies = getCookies();
const cookieName = "formwork_preferred_color_scheme";
const oldValue = cookieName in cookies ? cookies[cookieName] : null;
let value: "light" | "dark" = "light";
let colorScheme: ColorSchemeName = "light";

if (window.matchMedia("(prefers-color-scheme: light)").matches) {
value = "light";
colorScheme = "light";
} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
value = "dark";
colorScheme = "dark";
}

if (value && value !== oldValue) {
setCookie(cookieName, value, {
if (colorScheme && colorScheme !== oldValue) {
setCookie(cookieName, colorScheme, {
"max-age": 2592000, // 1 month
path: app.config.baseUri,
samesite: "strict",
});

if (event.type === "change" && getSupportedColorSchemes() === "light dark") {
setColorScheme(colorScheme);
}
}
};

window.addEventListener("beforeunload", setPreferredColorScheme);
window.addEventListener("pagehide", setPreferredColorScheme);
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", setPreferredColorScheme);
}
}
4 changes: 2 additions & 2 deletions panel/views/errors/error.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<!DOCTYPE html>
<html>
<html class="color-scheme-<?= $panel->colorScheme()->value ?>">

<head>
<title><?php if (!empty($title)) : ?><?= $title ?> | <?php endif ?>Formwork</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex, nofollow">
<link rel="icon" type="image/svg+xml" href="<?= $this->assets()->uri('images/icon.svg') ?>">
<link rel="alternate icon" href="<?= $this->assets()->uri('images/icon.png') ?>">
<link rel="stylesheet" href="<?= $this->assets()->uri($colorScheme === 'dark' ? 'css/panel-dark.min.css' : 'css/panel.min.css', true) ?>">
<link rel="stylesheet" href="<?= $this->assets()->uri('css/panel.min.css', true) ?>">
</head>

<body>
Expand Down
5 changes: 3 additions & 2 deletions panel/views/layouts/login.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<!DOCTYPE html>
<html lang="<?= $app->translations()->getCurrent()->code() ?>">
<html lang="<?= $app->translations()->getCurrent()->code() ?>" class="color-scheme-<?= $panel->colorScheme()->value ?>">

<head>
<title><?php if (!empty($title)) : ?><?= $title ?> | <?php endif ?>Formwork</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<meta name="robots" content="noindex, nofollow">
<meta name="color-scheme" content="<?= $panel->colorScheme()->getCompatibleSchemes() ?>">
<link rel="icon" type="image/svg+xml" href="<?= $this->assets()->uri('images/icon.svg') ?>">
<link rel="alternate icon" href="<?= $this->assets()->uri('images/icon.png') ?>">
<link rel="stylesheet" href="<?= $this->assets()->uri($colorScheme === 'dark' ? 'css/panel-dark.min.css' : 'css/panel.min.css', true) ?>">
<link rel="stylesheet" href="<?= $this->assets()->uri('css/panel.min.css', true) ?>">
</head>

<body>
Expand Down
Loading

0 comments on commit d1978be

Please sign in to comment.