Skip to content
Snippets Groups Projects
Commit 827ca03f authored by Yassine Doghri's avatar Yassine Doghri
Browse files

refactor(color-themes): set themes declaration as a config property + generate css file dynamically

parent 71a063da
No related branches found
No related tags found
No related merge requests found
Showing
with 224 additions and 151 deletions
<?php
declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\BaseConfig;
class Colors extends BaseConfig
{
/**
* @var array<string, array<string, mixed>>
*/
public array $themes = [
/* Castopod's brand color */
'pine' => [
'accent-base' => [174, 100, 29],
'accent-hover' => [172, 100, 17],
'accent-muted' => [131, 100, 12],
'accent-contrast' => [0, 0, 100],
'heading-foreground' => [172, 100, 17],
'heading-background' => [111, 64, 94],
'background-elevated' => [0, 0, 100],
'background-base' => [173, 44, 96],
'background-navigation' => [172, 100, 17],
'background-header' => [172, 100, 17],
'background-highlight' => [111, 64, 94],
'background-backdrop' => [0, 0, 50],
'border-subtle' => [111, 42, 86],
'border-contrast' => [0, 0, 0],
'border-navigation' => [131, 100, 12],
'text-base' => [158, 8, 3],
'text-muted' => [172, 8, 38],
],
/* Red / Rose color */
'crimson' => [
'accent-base' => [350, 87, 61],
'accent-hover' => [348, 75, 40],
'accent-muted' => [348, 73, 32],
'accent-contrast' => [0, 0, 100],
'heading-foreground' => [348, 73, 32],
'heading-background' => [344, 79, 96],
'background-elevated' => [0, 0, 100],
'background-base' => [350, 44, 96],
'background-header' => [348, 75, 40],
'background-highlight' => [344, 79, 96],
'background-backdrop' => [0, 0, 50],
'border-subtle' => [348, 42, 86],
'border-contrast' => [0, 0, 0],
'text-base' => [340, 8, 3],
'text-muted' => [345, 8, 38],
],
/* Blue color */
'lake' => [
'accent-base' => [194, 100, 44],
'accent-hover' => [194, 100, 22],
'accent-muted' => [195, 100, 11],
'accent-contrast' => [0, 0, 100],
'heading-foreground' => [194, 100, 22],
'heading-background' => [195, 100, 92],
'background-elevated' => [0, 0, 100],
'background-base' => [196, 44, 96],
'background-header' => [194, 100, 22],
'background-highlight' => [195, 100, 92],
'background-backdrop' => [0, 0, 50],
'border-subtle' => [195, 42, 86],
'border-contrast' => [0, 0, 0],
'text-base' => [194, 8, 3],
'text-muted' => [195, 8, 38],
],
/* Orange color */
'amber' => [
'accent-base' => [17, 100, 57],
'accent-hover' => [17, 100, 35],
'accent-muted' => [17, 100, 24],
'accent-contrast' => [0, 0, 100],
'heading-foreground' => [17, 100, 35],
'heading-background' => [17, 100, 89],
'background-elevated' => [0, 0, 100],
'background-base' => [15, 44, 96],
'background-header' => [17, 100, 35],
'background-highlight' => [17, 100, 89],
'background-backdrop' => [0, 0, 50],
'border-subtle' => [17, 42, 86],
'border-contrast' => [0, 0, 0],
'text-base' => [15, 8, 3],
'text-muted' => [17, 8, 38],
],
/* Violet color */
'jacaranda' => [
'accent-base' => [254, 72, 52],
'accent-hover' => [254, 73, 30],
'accent-muted' => [254, 71, 19],
'accent-contrast' => [0, 0, 100],
'heading-foreground' => [254, 73, 30],
'heading-background' => [254, 73, 84],
'background-elevated' => [0, 0, 100],
'background-base' => [253, 44, 96],
'background-header' => [254, 73, 30],
'background-highlight' => [254, 88, 91],
'background-backdrop' => [0, 0, 50],
'border-subtle' => [254, 42, 86],
'border-contrast' => [0, 0, 0],
'text-base' => [253, 8, 3],
'text-muted' => [254, 8, 38],
],
/* Black color */
'onyx' => [
'accent-base' => [240, 17, 2],
'accent-hover' => [240, 17, 17],
'accent-muted' => [240, 17, 17],
'accent-contrast' => [0, 0, 100],
'heading-foreground' => [240, 17, 17],
'heading-background' => [240, 17, 94],
'background-elevated' => [0, 0, 100],
'background-base' => [240, 17, 96],
'background-header' => [240, 12, 17],
'background-highlight' => [240, 17, 94],
'background-backdrop' => [0, 0, 50],
'border-subtle' => [240, 17, 86],
'border-contrast' => [0, 0, 0],
'text-base' => [240, 8, 3],
'text-muted' => [240, 8, 38],
],
];
}
......@@ -51,6 +51,9 @@ $routes->addPlaceholder(
$routes->get('manifest.webmanifest', 'WebmanifestController', [
'as' => 'webmanifest',
]);
$routes->get('styles/themes.css', 'ColorsController', [
'as' => 'color-themes-css',
]);
// We get a performance increase by specifying the default
// route since we don't have to scan directories.
......
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
namespace App\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\Response;
class ColorsController extends Controller
{
/**
* @noRector ReturnTypeDeclarationRector
*/
public function index(): Response
{
$cacheName = 'colors.css';
if (
! ($colorsCssBody = cache($cacheName))
) {
$colorThemes = config('Colors')
->themes;
$colorsCssBody = '';
foreach ($colorThemes as $name => $color) {
$colorsCssBody .= ".theme-{$name} {";
foreach ($color as $variable => $value) {
$colorsCssBody .= "--color-{$variable}: {$value[0]} {$value[1]}% {$value[2]}%;";
}
$colorsCssBody .= '}';
}
cache()
->save($cacheName, $colorsCssBody, DECADE);
}
return $this->response->setHeader('Content-Type', 'text/css')
->setHeader('charset', 'UTF-8')
->setBody($colorsCssBody);
}
}
......@@ -2,7 +2,6 @@
@import "./custom.css";
@import "./fonts.css";
@import "./colors.css";
@import "./themes.css";
@import "./breadcrumb.css";
@import "./dropdown.css";
@import "./choices.css";
......
/* Castopod's brand color */
.theme-pine {
--color-accent-base: 174 100% 29%;
--color-accent-hover: 172 100% 17%;
--color-accent-muted: 131 100% 12%;
--color-accent-contrast: 0 0% 100%;
--color-heading-foreground: 172 100% 17%;
--color-heading-background: 111 64% 94%;
--color-background-elevated: 0 0% 100%;
--color-background-base: 173 44% 96%;
--color-background-navigation: 172 100% 17%;
--color-background-header: 172 100% 17%;
--color-background-highlight: 111 64% 94%;
--color-background-backdrop: 0 0% 50%;
--color-border-subtle: 111 42% 86%;
--color-border-contrast: 0 0% 0%;
--color-border-navigation: 131 100% 12%;
--color-text-base: 158 8% 3%;
--color-text-muted: 172 8% 38%;
}
/* Red / Rose color */
.theme-crimson {
--color-accent-base: 350 87% 61%;
--color-accent-hover: 348 75% 40%;
--color-accent-muted: 348 73% 32%;
--color-accent-contrast: 0 0% 100%;
--color-heading-foreground: 348 73% 32%;
--color-heading-background: 344 79% 96%;
--color-background-elevated: 0 0% 100%;
--color-background-base: 350 44% 96%;
--color-background-header: 348 75% 40%;
--color-background-highlight: 344 79% 96%;
--color-background-backdrop: 0 0% 50%;
--color-border-subtle: 348 42% 86%;
--color-border-contrast: 0 0% 0%;
--color-text-base: 340 8% 3%;
--color-text-muted: 345 8% 38%;
}
/* Blue color */
.theme-lake {
--color-accent-base: 194 100% 44%;
--color-accent-hover: 194 100% 22%;
--color-accent-muted: 195 100% 11%;
--color-accent-contrast: 0 0% 100%;
--color-heading-foreground: 194 100% 22%;
--color-heading-background: 195 100% 92%;
--color-background-elevated: 0 0% 100%;
--color-background-base: 196 44% 96%;
--color-background-header: 194 100% 22%;
--color-background-highlight: 195 100% 92%;
--color-background-backdrop: 0 0% 50%;
--color-border-subtle: 195 42% 86%;
--color-border-contrast: 0 0% 0%;
--color-text-base: 194 8% 3%;
--color-text-muted: 195 8% 38%;
}
/* Orange color */
.theme-amber {
--color-accent-base: 17 100% 57%;
--color-accent-hover: 17 100% 35%;
--color-accent-muted: 17 100% 24%;
--color-accent-contrast: 0 0% 100%;
--color-heading-foreground: 17 100% 35%;
--color-heading-background: 17 100% 89%;
--color-background-elevated: 0 0% 100%;
--color-background-base: 15 44% 96%;
--color-background-header: 17 100% 35%;
--color-background-highlight: 17 100% 89%;
--color-background-backdrop: 0 0% 50%;
--color-border-subtle: 17 42% 86%;
--color-border-contrast: 0 0% 0%;
--color-text-base: 15 8% 3%;
--color-text-muted: 17 8% 38%;
}
/* Violet color */
.theme-jacaranda {
--color-accent-base: 254 72% 52%;
--color-accent-hover: 254 73% 30%;
--color-accent-muted: 254 71% 19%;
--color-accent-contrast: 0 0% 100%;
--color-heading-foreground: 254 73% 30%;
--color-heading-background: 254 73% 84%;
--color-background-elevated: 0 0% 100%;
--color-background-base: 253 44% 96%;
--color-background-header: 254 73% 30%;
--color-background-highlight: 254 88% 91%;
--color-background-backdrop: 0 0% 50%;
--color-border-subtle: 254 42% 86%;
--color-border-contrast: 0 0% 0%;
--color-text-base: 253 8% 3%;
--color-text-muted: 254 8% 38%;
}
/* Black color */
.theme-onyx {
--color-accent-base: 240 17% 2%;
--color-accent-hover: 240 17% 17%;
--color-accent-muted: 240 17% 17%;
--color-accent-contrast: 0 0% 100%;
--color-heading-foreground: 240 17% 17%;
--color-heading-background: 240 17% 94%;
--color-background-elevated: 0 0% 100%;
--color-background-base: 240 17% 96%;
--color-background-header: 240 12% 17%;
--color-background-highlight: 240 17% 94%;
--color-background-backdrop: 0 0% 50%;
--color-border-subtle: 240 17% 86%;
--color-border-contrast: 0 0% 0%;
--color-text-base: 240 8% 3%;
--color-text-muted: 240 8% 38%;
}
......@@ -5,10 +5,12 @@
<head>
<meta charset="utf-8">
<title>404 Page Not Found</title>
<link rel='stylesheet' type='text/css' href='<?= route_to('color-themes-css') ?>' />
<?= service('vite')->asset('styles/index.css', 'css') ?>
</head>
<body class="flex flex-col items-center justify-center min-h-screen px-2 text-center bg-base">
<body class="flex flex-col items-center justify-center min-h-screen px-2 text-center bg-base theme-<?= service('settings')
->get('App.theme') ?>">
<?= svg('castopod-mascot_confused', 'h-64') ?>
<h1 class="text-3xl font-bold font-display md:text-4xl lg:text-5xl">404 - File Not Found</h1>
......
......@@ -7,10 +7,12 @@
<meta name="robots" content="noindex">
<title>Whoops!</title>
<link rel='stylesheet' type='text/css' href='<?= route_to('color-themes-css') ?>' />
<?= service('vite')->asset('styles/index.css', 'css') ?>
</head>
<body class="flex flex-col items-center justify-center min-h-screen px-2 text-center bg-base">
<body class="flex flex-col items-center justify-center min-h-screen px-2 text-center bg-base theme-<?= service('settings')
->get('App.theme') ?>">
<?= svg('castopod-mascot_confused', 'h-64') ?>
<h1 class="text-3xl font-bold font-display md:text-4xl lg:text-5xl">Whoops!</h1>
<p class="mb-6 text-lg text-skin-muted md:text-xl lg:text-2xl">We seem to have hit a snag. Please try again later...</p>
......
......@@ -14,6 +14,7 @@
<link rel="apple-touch-icon" href="<?= service('settings')->get('App.siteIcon')['180'] ?>">
<link rel="manifest" href="<?= route_to('webmanifest') ?>">
<link rel='stylesheet' type='text/css' href='<?= route_to('color-themes-css') ?>' />
<?= service('vite')
->asset('styles/index.css', 'css') ?>
<?= service('vite')
......
......@@ -6,7 +6,7 @@
</div>
<?= publication_pill($episode->published_at, $episode->publication_status, 'absolute top-0 left-0 ml-2 mt-2 text-sm'); ?>
<div class="absolute z-20 flex flex-col items-start px-4 py-2">
<?= episode_numbering($episode->number, $episode->season_number, 'text-xs font-semibold !no-underline border px-1 border-gray-500 mr-1', true) ?>
<?= episode_numbering($episode->number, $episode->season_number, 'text-xs font-semibold !no-underline px-1 bg-black/50 mr-1', true) ?>
<span class="font-semibold leading-tight line-clamp-2"><?= $episode->title ?></span>
</div>
</a>
......
......@@ -34,7 +34,7 @@
$episode->audio_file_duration,
) .
'</time>' .
'<img loading="lazy" src="' . $episode->cover->thumbnail_url . '" alt="' . $episode->title . '" class="object-cover w-20 rounded-lg aspect-square" />' .
'<img loading="lazy" src="' . $episode->cover->thumbnail_url . '" alt="' . $episode->title . '" class="object-cover w-20 rounded-lg shadow-inner aspect-square" />' .
'</div>' .
'<a class="overflow-x-hidden text-sm hover:underline" href="' . route_to(
'episode-view',
......
......@@ -17,12 +17,13 @@
subtitle="<?= lang('Settings.theme.accent_section_subtitle') ?>">
<div class="grid gap-4 grid-cols-colorButtons">
<?php foreach (['pine', 'lake', 'jacaranda', 'crimson', 'amber', 'onyx'] as $theme): ?>
<?php foreach (config('Colors')->themes as $themeName => $color): ?>
<Forms.ColorRadioButton
class="theme-<?= $theme ?> mx-auto"
value="<?= $theme ?>"
class="theme-<?= $themeName ?> mx-auto"
value="<?= $themeName ?>"
name="theme"
isChecked="<?= $theme === service('settings')->get('App.theme') ? 'true' : 'false' ?>" ><?= lang('Settings.theme.' . $theme) ?></Forms.ColorRadioButton>
isChecked="<?= $themeName === service('settings')
->get('App.theme') ? 'true' : 'false' ?>" ><?= lang('Settings.theme.' . $themeName) ?></Forms.ColorRadioButton>
<?php endforeach; ?>
</div>
......
......@@ -12,6 +12,7 @@
<link rel="icon" type="image/x-icon" href="<?= service('settings')
->get('App.siteIcon')['ico'] ?>" />
<link rel="apple-touch-icon" href="<?= service('settings')->get('App.siteIcon')['180'] ?>">
<link rel='stylesheet' type='text/css' href='<?= route_to('color-themes-css') ?>' />
<?= service('vite')
->asset('styles/index.css', 'css') ?>
<?= service('vite')
......
......@@ -24,6 +24,7 @@
<?= $metatags ?>
<link rel='stylesheet' type='text/css' href='<?= route_to('color-themes-css') ?>' />
<?= service('vite')
->asset('styles/index.css', 'css') ?>
<?= service('vite')
......@@ -90,7 +91,7 @@
<div class="inline-flex flex-row-reverse">
<?php $i = 0; ?>
<?php foreach ($episode->persons as $person): ?>
<img src="<?= $person->avatar->thumbnail_url ?>" alt="<?= $person->full_name ?>" class="object-cover w-8 h-8 -ml-5 border-2 rounded-full aspect-square border-background-header last:ml-0" />
<img src="<?= $person->avatar->thumbnail_url ?>" alt="<?= $person->full_name ?>" class="object-cover w-8 h-8 -ml-4 border-2 rounded-full aspect-square border-background-header last:ml-0" />
<?php $i++; if ($i === 3) {
break;
}?>
......
......@@ -4,7 +4,7 @@
<?= format_duration($episode->audio_file_duration) ?>
</time>
<img loading="lazy" src="<?= $episode->cover
->thumbnail_url ?>" alt="<?= $episode->title ?>" class="object-cover w-20 rounded-lg aspect-square" />
->thumbnail_url ?>" alt="<?= $episode->title ?>" class="object-cover w-20 rounded-lg shadow-inner aspect-square" />
</div>
<div class="flex items-center flex-1 gap-x-4">
<div class="flex flex-col flex-1">
......
......@@ -27,6 +27,7 @@
<?= $metatags ?>
<link rel='stylesheet' type='text/css' href='<?= route_to('color-themes-css') ?>' />
<?= service('vite')
->asset('styles/index.css', 'css') ?>
<?= service('vite')
......
......@@ -23,6 +23,7 @@
<?= $metatags ?>
<link rel='stylesheet' type='text/css' href='<?= route_to('color-themes-css') ?>' />
<?= service('vite')
->asset('styles/index.css', 'css') ?>
<?= service('vite')
......
......@@ -26,6 +26,7 @@
}
</script>
<link rel='stylesheet' type='text/css' href='<?= route_to('color-themes-css') ?>' />
<?= service('vite')
->asset('styles/index.css', 'css') ?>
<?= service('vite')
......
......@@ -24,6 +24,7 @@
<?= $metatags ?>
<link rel='stylesheet' type='text/css' href='<?= route_to('color-themes-css') ?>' />
<?= service('vite')
->asset('styles/index.css', 'css') ?>
<?= service('vite')
......
......@@ -25,7 +25,7 @@
<div class="inline-flex flex-row-reverse">
<?php $i = 0; ?>
<?php foreach ($podcast->persons as $person): ?>
<img src="<?= $person->avatar->thumbnail_url ?>" alt="<?= $person->full_name ?>" class="object-cover w-8 -ml-5 border-2 rounded-full aspect-square border-background-base last:ml-0" />
<img src="<?= $person->avatar->thumbnail_url ?>" alt="<?= $person->full_name ?>" class="object-cover w-8 -ml-4 border-2 rounded-full aspect-square border-background-base last:ml-0" />
<?php $i++; if ($i === 3) {
break;
}?>
......
......@@ -24,6 +24,7 @@
<?= $metatags ?>
<link rel='stylesheet' type='text/css' href='<?= route_to('color-themes-css') ?>' />
<?= service('vite')
->asset('styles/index.css', 'css') ?>
<?= service('vite')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment