feat(settings): add theme settings to set an accent color for all public pages
set 6 base accent colors: pine, lake, jacaranda, crimson, amber and onyx
This commit is contained in:
parent
a746a781b4
commit
5c529a83aa
|
@ -447,4 +447,6 @@ class App extends BaseConfig
|
|||
'192' => '/icon-192.png',
|
||||
'512' => '/icon-512.png',
|
||||
];
|
||||
|
||||
public string $theme = 'crimson';
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
@layer components {
|
||||
.color-radio-btn {
|
||||
@apply absolute opacity-0;
|
||||
|
||||
&:focus + label {
|
||||
@apply ring-accent;
|
||||
}
|
||||
|
||||
&:checked {
|
||||
@apply ring-2 ring-contrast;
|
||||
|
||||
& + label {
|
||||
@apply flex items-center justify-center text-2xl text-accent-contrast bg-accent-base;
|
||||
|
||||
&::before {
|
||||
content: "✓";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& + label {
|
||||
@apply inline-block w-16 h-16 text-sm font-semibold rounded-full cursor-pointer border-contrast bg-accent-base text-accent-contrast border-3;
|
||||
color: hsl(var(--color-text-muted));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,54 +1,3 @@
|
|||
/*
|
||||
--color-brand-lighter: hsl(173 44% 96%);
|
||||
--color-brand-light: hsl(111 64% 94%);
|
||||
--color-brand-base: hsl(174 100% 29%);
|
||||
--color-brand-dark: hsl(172 100% 17%);
|
||||
--color-brand-darker: hsl(131 100% 12%);
|
||||
|
||||
--color-background-elevated: hsl(0 0% 100%);
|
||||
--color-background-base: hsl(173 44% 96%);
|
||||
|
||||
--color-text-base: hsl(240 17% 2%);
|
||||
--color-text-muted: hsl(240 8% 63%);
|
||||
--color-text-inverted: hsl(0 0% 100%);
|
||||
|
||||
--color-brand-lighter: 173 44% 96%;
|
||||
--color-brand-light: 111 64% 94%;
|
||||
--color-brand-base: 174 100% 29%;
|
||||
--color-brand-dark: 172 100% 17%;
|
||||
--color-brand-darker: 131 100% 12%;
|
||||
|
||||
--color-background-elevated: 0 0% 100%;
|
||||
--color-background-base: 173 44% 96%;
|
||||
|
||||
--color-text-base: 240 17% 2%;
|
||||
--color-text-muted: 240 8% 63%;
|
||||
--color-text-inverted: 0 0% 100%;
|
||||
*/
|
||||
|
||||
/*
|
||||
--color-accent-base: 0 100% 38%;
|
||||
--color-accent-hover: 0 100% 48%;
|
||||
--color-accent-muted: 0 8% 63%;
|
||||
|
||||
--color-heading-foreground: 0 64% 94%;
|
||||
--color-heading-background: 0 100% 17%;
|
||||
|
||||
--color-background-elevated: 209 35% 15%;
|
||||
--color-background-base: 210 34% 13%;
|
||||
--color-background-navigation: 210 34% 11%;
|
||||
--color-background-header: 200 38% 15%;
|
||||
--color-background-highlight: 200 38% 25%;
|
||||
--color-background-backdrop: 0 0% 50%;
|
||||
|
||||
--color-border-subtle: 240 8% 27%;
|
||||
--color-border-contrast: 240 8% 78%;
|
||||
--color-border-navigation: 210 34% 4%;
|
||||
|
||||
--color-text-base: 240 17% 100%;
|
||||
--color-text-muted: 240 8% 63%;
|
||||
*/
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--color-accent-base: 174 100% 29%;
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
@import "./custom.css";
|
||||
@import "./fonts.css";
|
||||
@import "./colors.css";
|
||||
@import "./themes.css";
|
||||
@import "./breadcrumb.css";
|
||||
@import "./dropdown.css";
|
||||
@import "./choices.css";
|
||||
@import "./radioBtn.css";
|
||||
@import "./colorRadioBtn.css";
|
||||
@import "./switch.css";
|
||||
@import "./radioToggler.css";
|
||||
@import "./formInputTabs.css";
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
@layer components {
|
||||
.form-radio-btn {
|
||||
@apply absolute mt-3 ml-3 border-contrast border-3 text-accent-base;
|
||||
}
|
||||
|
||||
.form-radio-btn:focus + label {
|
||||
@apply ring-accent;
|
||||
}
|
||||
&:focus {
|
||||
@apply ring-accent;
|
||||
}
|
||||
|
||||
.form-radio-btn + label {
|
||||
@apply inline-block py-2 pl-8 pr-2 text-sm font-semibold rounded-lg cursor-pointer border-contrast bg-elevated border-3;
|
||||
color: hsl(var(--color-text-muted));
|
||||
}
|
||||
&:checked {
|
||||
@apply ring-2 ring-contrast;
|
||||
|
||||
.form-radio-btn:checked + label {
|
||||
@apply text-accent-contrast bg-accent-base;
|
||||
}
|
||||
& + label {
|
||||
@apply text-accent-contrast bg-accent-base;
|
||||
}
|
||||
}
|
||||
|
||||
.form-radio-btn:checked {
|
||||
@apply ring-2 ring-contrast;
|
||||
& + label {
|
||||
@apply inline-block py-2 pl-8 pr-2 text-sm font-semibold rounded-lg cursor-pointer border-contrast bg-elevated border-3;
|
||||
color: hsl(var(--color-text-muted));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/* 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%;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Views\Components\Forms;
|
||||
|
||||
class ColorRadioButton extends FormComponent
|
||||
{
|
||||
protected bool $isChecked = false;
|
||||
|
||||
public function setIsChecked(string $value): void
|
||||
{
|
||||
$this->isChecked = $value === 'true';
|
||||
}
|
||||
|
||||
public function render(): string
|
||||
{
|
||||
$radioInput = form_radio(
|
||||
[
|
||||
'id' => $this->value,
|
||||
'name' => $this->name,
|
||||
'class' => 'color-radio-btn',
|
||||
],
|
||||
$this->value,
|
||||
old($this->name) ? old($this->name) === $this->value : $this->isChecked,
|
||||
);
|
||||
|
||||
return <<<HTML
|
||||
<div class="{$this->class}">
|
||||
{$radioInput}
|
||||
<label for="{$this->value}" title="{$this->slot}" data-tooltip="bottom"></label>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
}
|
|
@ -31,6 +31,14 @@ $routes->group(
|
|||
'as' => 'settings-instance-delete-icon',
|
||||
'filter' => 'permission:settings-manage',
|
||||
]);
|
||||
$routes->get('theme', 'SettingsController::theme', [
|
||||
'as' => 'settings-theme',
|
||||
'filter' => 'permission:settings-manage',
|
||||
]);
|
||||
$routes->post('theme', 'SettingsController::attemptSetInstanceTheme', [
|
||||
'as' => 'settings-theme',
|
||||
'filter' => 'permission:settings-manage',
|
||||
]);
|
||||
});
|
||||
|
||||
$routes->group('persons', function ($routes): void {
|
||||
|
|
|
@ -88,7 +88,7 @@ class SettingsController extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
return redirect('settings-general')->with('message', lang('Settings.general.instanceEditSuccess'));
|
||||
}
|
||||
|
||||
public function deleteIcon(): RedirectResponse
|
||||
|
@ -100,6 +100,25 @@ class SettingsController extends BaseController
|
|||
service('settings')
|
||||
->forget('App.siteIcon');
|
||||
|
||||
return redirect()->back();
|
||||
return redirect('settings-general')->with('message', lang('Settings.general.deleteIconSuccess'));
|
||||
}
|
||||
|
||||
public function theme(): string
|
||||
{
|
||||
helper('form');
|
||||
return view('settings/theme');
|
||||
}
|
||||
|
||||
public function attemptSetInstanceTheme(): RedirectResponse
|
||||
{
|
||||
$theme = $this->request->getPost('theme');
|
||||
service('settings')
|
||||
->set('App.theme', $theme);
|
||||
|
||||
// delete all pages cache
|
||||
cache()
|
||||
->deleteMatching('page*');
|
||||
|
||||
return redirect('settings-theme')->with('message', lang('Settings.theme.setInstanceThemeSuccess'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
return [
|
||||
'go_to_website' => 'View site',
|
||||
'go_to_admin' => 'Go to admin',
|
||||
'dashboard' => 'Dashboard',
|
||||
'admin' => 'Home',
|
||||
'podcasts' => 'Podcasts',
|
||||
'podcast-list' => 'All podcasts',
|
||||
'podcast-create' => 'New podcast',
|
||||
'podcast-import' => 'Import a podcast',
|
||||
'persons' => 'Persons',
|
||||
'person-list' => 'All persons',
|
||||
'person-create' => 'New person',
|
||||
'fediverse' => 'Fediverse',
|
||||
'fediverse-blocked-actors' => 'Blocked accounts',
|
||||
'fediverse-blocked-domains' => 'Blocked domains',
|
||||
'users' => 'Users',
|
||||
'user-list' => 'All users',
|
||||
'user-create' => 'New user',
|
||||
'pages' => 'Pages',
|
||||
'page-list' => 'All pages',
|
||||
'page-create' => 'New Page',
|
||||
'settings' => 'Settings',
|
||||
'settings-general' => 'General',
|
||||
'account' => [
|
||||
'my-account' => 'My account',
|
||||
'change-password' => 'Change password',
|
||||
'logout' => 'Logout',
|
||||
],
|
||||
];
|
|
@ -17,6 +17,7 @@ return [
|
|||
'contributors' => 'contributors',
|
||||
'pages' => 'pages',
|
||||
'settings' => 'settings',
|
||||
'theme' => 'theme',
|
||||
'add' => 'add',
|
||||
'new' => 'new',
|
||||
'edit' => 'edit',
|
||||
|
|
|
@ -10,6 +10,7 @@ declare(strict_types=1);
|
|||
|
||||
return [
|
||||
'go_to_website' => 'View site',
|
||||
'go_to_admin' => 'Go to admin',
|
||||
'dashboard' => 'Dashboard',
|
||||
'admin' => 'Home',
|
||||
'podcasts' => 'Podcasts',
|
||||
|
@ -28,6 +29,9 @@ return [
|
|||
'pages' => 'Pages',
|
||||
'page-list' => 'All pages',
|
||||
'page-create' => 'New Page',
|
||||
'settings' => 'Settings',
|
||||
'settings-general' => 'General',
|
||||
'settings-theme' => 'Theme',
|
||||
'account' => [
|
||||
'my-account' => 'My account',
|
||||
'change-password' => 'Change password',
|
||||
|
|
|
@ -10,7 +10,7 @@ declare(strict_types=1);
|
|||
|
||||
return [
|
||||
'title' => 'General settings',
|
||||
'form' => [
|
||||
'general' => [
|
||||
'site_section_title' => 'Instance',
|
||||
'site_icon' => 'Site icon',
|
||||
'site_icon_delete' => 'Delete site icon',
|
||||
|
@ -19,5 +19,20 @@ return [
|
|||
'site_name' => 'Site name',
|
||||
'site_description' => 'Site description',
|
||||
'submit' => 'Save',
|
||||
'instanceEditSuccess' => 'Instance has been updated successfully!',
|
||||
'deleteIconSuccess' => 'Site icon has been remove successfully!',
|
||||
],
|
||||
'theme' => [
|
||||
'title' => 'Theme',
|
||||
'accent_section_title' => 'Accent color',
|
||||
'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.',
|
||||
'pine' => 'Pine',
|
||||
'crimson' => 'Crimson',
|
||||
'amber' => 'Amber',
|
||||
'lake' => 'Lake',
|
||||
'jacaranda' => 'Jacaranda',
|
||||
'onyx' => 'Onyx',
|
||||
'submit' => 'Save',
|
||||
'setInstanceThemeSuccess' => 'Theme has been updated successfully!',
|
||||
],
|
||||
];
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
return [
|
||||
'go_to_website' => 'Visiter le site',
|
||||
'dashboard' => 'Tableau de bord',
|
||||
'admin' => 'Accueil',
|
||||
'podcasts' => 'Podcasts',
|
||||
'podcast-list' => 'Tous les podcasts',
|
||||
'podcast-create' => 'Créer un podcast',
|
||||
'podcast-import' => 'Importer un podcast',
|
||||
'persons' => 'Intervenants',
|
||||
'person-list' => 'Tous les intervenants',
|
||||
'person-create' => 'Nouvel intervenant',
|
||||
'fediverse' => 'Fédiverse',
|
||||
'fediverse-blocked_actors' => 'Utilisateurs blockés',
|
||||
'fediverse-blocked_domains' => 'Domaines blockés',
|
||||
'users' => 'Utilisateurs',
|
||||
'user-list' => 'Tous les utilisateurs',
|
||||
'user-create' => 'Créer un utilisateur',
|
||||
'pages' => 'Pages',
|
||||
'page-list' => 'Toutes les pages',
|
||||
'page-create' => 'Créer une page',
|
||||
'settings' => 'Paramètres',
|
||||
'settings-general' => 'Général',
|
||||
'account' => [
|
||||
'my-account' => 'Mon compte',
|
||||
'change-password' => 'Modifier le mot de passe',
|
||||
'logout' => 'Déconnexion',
|
||||
],
|
||||
];
|
|
@ -16,6 +16,8 @@ return [
|
|||
'episodes' => 'épisodes',
|
||||
'contributors' => 'contributeurs',
|
||||
'pages' => 'pages',
|
||||
'settings' => 'paramètres',
|
||||
'theme' => 'thème',
|
||||
'add' => 'ajouter',
|
||||
'new' => 'créer',
|
||||
'edit' => 'modifier',
|
||||
|
|
|
@ -28,6 +28,9 @@ return [
|
|||
'pages' => 'Pages',
|
||||
'page-list' => 'Toutes les pages',
|
||||
'page-create' => 'Créer une page',
|
||||
'settings' => 'Paramètres',
|
||||
'settings-general' => 'Général',
|
||||
'settings-themes' => 'Thèmes',
|
||||
'account' => [
|
||||
'my-account' => 'Mon compte',
|
||||
'change-password' => 'Modifier le mot de passe',
|
||||
|
|
|
@ -10,15 +10,28 @@ declare(strict_types=1);
|
|||
|
||||
return [
|
||||
'title' => 'Paramètres généraux',
|
||||
'form' => [
|
||||
'general' => [
|
||||
'site_section_title' => 'Instance',
|
||||
'site_section_subtitle' => 'configuration de l’instance',
|
||||
'site_icon' => 'Favicon du site',
|
||||
'site_icon_delete' => 'Supprimer la favicon du site',
|
||||
'site_icon_hint' => 'Les favicons sont ce que vous voyez sur les onglets de votre navigateur, dans votre barre de favoris, et lorsque vous ajoutez un site web en raccourci sur des appareils mobiles.',
|
||||
'site_icon_helper' => 'La favicon doit être carrée, avec au minimum 512px de largeur et de hauteur.',
|
||||
'site_name' => 'Titre du site',
|
||||
'site_description' => 'Description du site',
|
||||
'submit' => 'Save',
|
||||
'submit' => 'Sauvegarder',
|
||||
'instanceEditSuccess' => 'L’instance a bien été mise à jour !',
|
||||
'deleteIconSuccess' => 'La favicon du site a bien été retirée !',
|
||||
],
|
||||
'theme' => [
|
||||
'title' => 'Thème',
|
||||
'accent_section_title' => 'Couleur d’accentuation',
|
||||
'accent_section_subtitle' => 'Sélectionnez une couleur qui déterminera l’apparence de toutes les pages publiques.',
|
||||
'pine' => 'Pin',
|
||||
'crimson' => 'Cramoisi',
|
||||
'amber' => 'Ambre',
|
||||
'lake' => 'Lac',
|
||||
'jacaranda' => 'Jacaranda',
|
||||
'onyx' => 'Onyx',
|
||||
'setInstanceThemeSuccess' => 'Le thème a bien été mis à jour !',
|
||||
],
|
||||
];
|
||||
|
|
|
@ -107,6 +107,7 @@ module.exports = {
|
|||
podcastMain: "1fr minmax(200px, 300px)",
|
||||
cards: "repeat(auto-fill, minmax(14rem, 1fr))",
|
||||
latestEpisodes: "repeat(5, 1fr)",
|
||||
colorButtons: "repeat(auto-fill, minmax(4rem, 1fr))",
|
||||
},
|
||||
gridTemplateRows: {
|
||||
admin: "40px 1fr",
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<a href="<?= route_to(
|
||||
'home',
|
||||
) ?>" class="inline-flex items-center h-full px-6 text-sm font-semibold hover:underline focus:ring-inset focus:ring-accent">
|
||||
<?= lang('AdminNavigation.go_to_website') ?>
|
||||
<?= lang('Navigation.go_to_website') ?>
|
||||
<?= icon('external-link', 'ml-1 opacity-60') ?>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -48,12 +48,12 @@
|
|||
$menuItems = [
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('AdminNavigation.account.my-account'),
|
||||
'title' => lang('Navigation.account.my-account'),
|
||||
'uri' => route_to('my-account'),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('AdminNavigation.account.change-password'),
|
||||
'title' => lang('Navigation.account.change-password'),
|
||||
'uri' => route_to('change-password'),
|
||||
],
|
||||
[
|
||||
|
@ -61,7 +61,7 @@
|
|||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('AdminNavigation.account.logout'),
|
||||
'title' => lang('Navigation.account.logout'),
|
||||
'uri' => route_to('logout'),
|
||||
],
|
||||
];
|
||||
|
|
|
@ -24,7 +24,7 @@ $navigation = [
|
|||
],
|
||||
'settings' => [
|
||||
'icon' => 'settings',
|
||||
'items' => ['settings-general'],
|
||||
'items' => ['settings-general', 'settings-theme'],
|
||||
],
|
||||
]; ?>
|
||||
|
||||
|
@ -33,7 +33,7 @@ $navigation = [
|
|||
<div>
|
||||
<button class="inline-flex items-center w-full px-4 py-1 font-semibold focus:ring-accent" type="button">
|
||||
<?= icon($data['icon'], 'opacity-60 text-2xl mr-4') ?>
|
||||
<?= lang('AdminNavigation.' . $section) ?>
|
||||
<?= lang('Navigation.' . $section) ?>
|
||||
</button>
|
||||
<ul class="flex flex-col">
|
||||
<?php foreach ($data['items'] as $item): ?>
|
||||
|
@ -42,7 +42,7 @@ $navigation = [
|
|||
<a class="w-full py-1 pl-14 pr-2 text-sm hover:opacity-100 focus:ring-inset focus:ring-accent<?= $isActive
|
||||
? ' font-semibold opacity-100 inline-flex items-center'
|
||||
: ' opacity-75' ?>" href="<?= route_to($item) ?>"><?= ($isActive ? icon('chevron-right', 'mr-2') : '') . lang(
|
||||
'AdminNavigation.' . $item,
|
||||
'Navigation.' . $item,
|
||||
) ?></a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
<?= csrf_field() ?>
|
||||
|
||||
<Forms.Section
|
||||
title="<?= lang('Settings.form.site_section_title') ?>">
|
||||
title="<?= lang('Settings.general.site_section_title') ?>">
|
||||
|
||||
<Forms.Field
|
||||
name="site_name"
|
||||
label="<?= lang('Settings.form.site_name') ?>"
|
||||
label="<?= lang('Settings.general.site_name') ?>"
|
||||
value="<?= service('settings')
|
||||
->get('App.siteName') ?>"
|
||||
required="true" />
|
||||
|
@ -26,7 +26,7 @@
|
|||
<Forms.Field
|
||||
as="Textarea"
|
||||
name="site_description"
|
||||
label="<?= lang('Settings.form.site_description') ?>"
|
||||
label="<?= lang('Settings.general.site_description') ?>"
|
||||
value="<?= service('settings')
|
||||
->get('App.siteDescription') ?>"
|
||||
required="true"
|
||||
|
@ -36,21 +36,21 @@
|
|||
<Forms.Field
|
||||
name="site_icon"
|
||||
type="file"
|
||||
label="<?= lang('Settings.form.site_icon') ?>"
|
||||
hint="<?= lang('Settings.form.site_icon_hint') ?>"
|
||||
helper="<?= lang('Settings.form.site_icon_helper') ?>"
|
||||
label="<?= lang('Settings.general.site_icon') ?>"
|
||||
hint="<?= lang('Settings.general.site_icon_hint') ?>"
|
||||
helper="<?= lang('Settings.general.site_icon_helper') ?>"
|
||||
accept=".png,.jpeg,.jpg"
|
||||
class="flex-1"
|
||||
/>
|
||||
<?php if (config('App')->siteIcon['ico'] !== service('settings')->get('App.siteIcon')['ico']): ?>
|
||||
<div class="relative ml-2">
|
||||
<a href="<?= route_to('settings-instance-delete-icon') ?>" class="absolute p-1 text-red-700 bg-red-100 border-2 rounded-full hover:text-red-900 border-contrast -top-3 -right-3 focus:ring-accent" title="<?= lang('Settings.form.site_icon_delete') ?>" data-tooltip="top"><?= icon('delete-bin') ?></a>
|
||||
<a href="<?= route_to('settings-instance-delete-icon') ?>" class="absolute p-1 text-red-700 bg-red-100 border-2 rounded-full hover:text-red-900 border-contrast -top-3 -right-3 focus:ring-accent" title="<?= lang('Settings.general.site_icon_delete') ?>" data-tooltip="top"><?= icon('delete-bin') ?></a>
|
||||
<img src="<?= service('settings')->get('App.siteIcon')['64'] ?>" alt="<?= service('settings')->get('App.siteName') ?> Favicon" class="w-10 h-10" />
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<Button variant="primary" type="submit" class="self-end"><?= lang('Settings.form.submit') ?></Button>
|
||||
<Button variant="primary" type="submit" class="self-end"><?= lang('Settings.general.submit') ?></Button>
|
||||
|
||||
</Forms.Section>
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?= $this->extend('_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
<?= lang('Settings.theme.title') ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('pageTitle') ?>
|
||||
<?= lang('Settings.theme.title') ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<form action="<?= route_to('settings-theme') ?>" method="POST" class="flex flex-col gap-y-4" enctype="multipart/form-data">
|
||||
<?= csrf_field() ?>
|
||||
<Forms.Section
|
||||
title="<?= lang('Settings.theme.accent_section_title') ?>"
|
||||
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): ?>
|
||||
<Forms.ColorRadioButton
|
||||
class="theme-<?= $theme ?> mx-auto"
|
||||
value="<?= $theme ?>"
|
||||
name="theme"
|
||||
isChecked="<?= $theme === service('settings')->get('App.theme') ? 'true' : 'false' ?>" ><?= lang('Settings.theme.' . $theme) ?></Forms.ColorRadioButton>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<Button variant="primary" type="submit" class="self-end"><?= lang('Settings.theme.submit') ?></Button>
|
||||
|
||||
</Forms.Section>
|
||||
|
||||
</form>
|
||||
<?= $this->endSection() ?>
|
|
@ -4,7 +4,7 @@
|
|||
<?= svg('castopod-logo-base', 'h-6') ?>
|
||||
</a>
|
||||
<a href="<?= route_to('admin', ) ?>" class="inline-flex items-center h-full px-6 text-sm font-semibold hover:underline focus:ring-inset focus:ring-accent">
|
||||
<?= lang('AdminNavigation.go_to_admin') ?>
|
||||
<?= lang('Navigation.go_to_admin') ?>
|
||||
<?= icon('external-link', 'ml-1 opacity-60') ?>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -43,12 +43,12 @@
|
|||
$menuItems = [
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('AdminNavigation.account.my-account'),
|
||||
'title' => lang('Navigation.account.my-account'),
|
||||
'uri' => route_to('my-account'),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('AdminNavigation.account.change-password'),
|
||||
'title' => lang('Navigation.account.change-password'),
|
||||
'uri' => route_to('change-password'),
|
||||
],
|
||||
[
|
||||
|
@ -56,7 +56,7 @@
|
|||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('AdminNavigation.account.logout'),
|
||||
'title' => lang('Navigation.account.logout'),
|
||||
'uri' => route_to('logout'),
|
||||
],
|
||||
];
|
||||
|
|
|
@ -29,12 +29,13 @@
|
|||
->asset('js/audio-player.ts', 'js') ?>
|
||||
</head>
|
||||
|
||||
<body class="flex flex-col min-h-screen mx-auto bg-base">
|
||||
<body class="flex flex-col min-h-screen mx-auto bg-base theme-<?= service('settings')
|
||||
->get('App.theme') ?>">
|
||||
<?php if (service('authentication')->check()): ?>
|
||||
<?= $this->include('_admin_navbar') ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<header class="py-8 text-white border-b bg-elevated border-subtle">
|
||||
<header class="py-8 border-b bg-elevated border-subtle">
|
||||
<div class="container flex flex-col items-start px-2 py-4 mx-auto">
|
||||
<a href="<?= route_to('home') ?>"
|
||||
class="inline-flex items-center mb-2 text-sm focus:ring-accent"><?= icon(
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
->asset('js/audio-player.ts', 'js') ?>
|
||||
</head>
|
||||
|
||||
<body class="flex flex-col min-h-screen mx-auto md:min-h-full md:grid md:grid-cols-podcast bg-base">
|
||||
<body class="flex flex-col min-h-screen mx-auto md:min-h-full md:grid md:grid-cols-podcast bg-base theme-<?= service('settings')
|
||||
->get('App.theme') ?>">
|
||||
<?php if (can_user_interact()): ?>
|
||||
<div class="col-span-full">
|
||||
<?= $this->include('_admin_navbar') ?>
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
->asset('js/app.ts', 'js') ?>
|
||||
</head>
|
||||
|
||||
<body class="flex flex-col min-h-screen mx-auto bg-base">
|
||||
<body class="flex flex-col min-h-screen mx-auto bg-base theme-<?= service('settings')
|
||||
->get('App.theme') ?>">
|
||||
<?php if (service('authentication')->check()): ?>
|
||||
<?= $this->include('_admin_navbar') ?>
|
||||
<?php endif; ?>
|
||||
|
@ -37,14 +38,16 @@
|
|||
<div class="container flex items-center justify-between px-2 py-4 mx-auto">
|
||||
<a href="<?= route_to(
|
||||
'home',
|
||||
) ?>" class="inline-flex items-baseline text-3xl font-semibold font-display"><?= 'castopod' .
|
||||
svg('castopod-logo-base', 'h-6 ml-2') ?></a>
|
||||
) ?>" class="inline-flex items-baseline text-3xl font-semibold font-display"><?= service('settings')
|
||||
->get('App.siteName') === 'Castopod' ? 'castopod' .
|
||||
svg('castopod-logo-base', 'h-6 ml-2') : service('settings')
|
||||
->get('App.siteName') ?></a>
|
||||
</div>
|
||||
</header>
|
||||
<main class="container flex-1 px-4 py-10 mx-auto">
|
||||
<Heading class="inline-block mb-2"><?= lang('Home.all_podcasts') ?> (<?= count(
|
||||
$podcasts,
|
||||
) ?>)</Heading>
|
||||
$podcasts,
|
||||
) ?>)</Heading>
|
||||
<section class="grid gap-4 grid-cols-cards">
|
||||
<?php if ($podcasts): ?>
|
||||
<?php foreach ($podcasts as $podcast): ?>
|
||||
|
|
|
@ -20,12 +20,13 @@
|
|||
->asset('js/map.ts', 'js') ?>
|
||||
</head>
|
||||
|
||||
<body class="flex flex-col h-full min-h-screen mx-auto bg-base">
|
||||
<body class="flex flex-col h-full min-h-screen mx-auto bg-base theme-<?= service('settings')
|
||||
->get('App.theme') ?>">
|
||||
<?php if (service('authentication')->check()): ?>
|
||||
<?= $this->include('_admin_navbar') ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<header class="py-8 text-white border-b border-subtle bg-elevated">
|
||||
<header class="py-8 border-b border-subtle bg-elevated">
|
||||
<div class="container flex flex-col items-start px-2 py-4 mx-auto">
|
||||
<a href="<?= route_to('home') ?>"
|
||||
class="inline-flex items-center mb-2 text-sm focus:ring-accent"><?= icon(
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
->asset('js/app.ts', 'js') ?>
|
||||
</head>
|
||||
|
||||
<body class="flex flex-col min-h-screen mx-auto bg-base">
|
||||
<body class="flex flex-col min-h-screen mx-auto bg-base theme-<?= service('settings')
|
||||
->get('App.theme') ?>">
|
||||
<?php if (service('authentication')->check()): ?>
|
||||
<?= $this->include('_admin_navbar') ?>
|
||||
<?php endif; ?>
|
||||
|
@ -29,7 +30,7 @@
|
|||
'arrow-left',
|
||||
'mr-2',
|
||||
) . lang('Page.back_to_home') ?></a>
|
||||
<h1 class="text-3xl font-semibold"><?= $page->title ?></h1>
|
||||
<Heading tagName="h1" class="text-3xl font-semibold"><?= $page->title ?></Heading>
|
||||
</div>
|
||||
</header>
|
||||
<main class="container flex-1 px-4 py-10 mx-auto">
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
->asset('js/audio-player.ts', 'js') ?>
|
||||
</head>
|
||||
|
||||
<body class="flex flex-col min-h-screen mx-auto md:min-h-full md:grid md:grid-cols-podcast bg-base">
|
||||
<body class="flex flex-col min-h-screen mx-auto md:min-h-full md:grid md:grid-cols-podcast bg-base theme-<?= service('settings')
|
||||
->get('App.theme') ?>">
|
||||
<?php if (can_user_interact()): ?>
|
||||
<div class="col-span-full">
|
||||
<?= $this->include('_admin_navbar') ?>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
data-toggle="funding-links"
|
||||
data-toggle-class="hidden"
|
||||
aria-label="<?= lang('Common.close') ?>"
|
||||
class="self-start p-1 text-2xl"><?= icon('close') ?></button>
|
||||
class="self-start p-1 text-2xl rounded-full focus:ring-accent"><?= icon('close') ?></button>
|
||||
</div>
|
||||
<div class="flex flex-col items-start p-4 space-y-4">
|
||||
<?php foreach ($podcast->fundingPlatforms as $fundingPlatform): ?>
|
||||
|
@ -24,7 +24,7 @@
|
|||
title="<?= $fundingPlatform->link_content ?>"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-flex items-center font-semibold text-accent-base">
|
||||
class="inline-flex items-center font-semibold text-accent-base hover:text-accent-hover focus:ring-accent">
|
||||
<?= icon(
|
||||
$fundingPlatform->type .
|
||||
'/' .
|
||||
|
|
|
@ -33,13 +33,13 @@
|
|||
<div class="px-2 sm:px-4">
|
||||
<div class="mb-2"><?= $podcast->description_html ?></div>
|
||||
<div class="flex gap-x-4 gap-y-2">
|
||||
<span class="px-2 py-1 text-sm font-semibold border rounded-sm border-subtle bg-highlight text-skin-muted">
|
||||
<span class="px-2 py-1 text-sm font-semibold border rounded-sm border-subtle bg-highlight">
|
||||
<?= lang(
|
||||
'Podcast.category_options.' . $podcast->category->code,
|
||||
) ?>
|
||||
</span>
|
||||
<?php foreach ($podcast->other_categories as $other_category): ?>
|
||||
<span class="px-2 py-1 text-sm font-semibold border rounded-sm border-subtle bg-highlight text-skin-muted">
|
||||
<span class="px-2 py-1 text-sm font-semibold border rounded-sm border-subtle bg-highlight">
|
||||
<?= lang(
|
||||
'Podcast.category_options.' . $other_category->code,
|
||||
) ?>
|
||||
|
|
|
@ -33,9 +33,10 @@
|
|||
</head>
|
||||
|
||||
|
||||
<body class="flex flex-col min-h-screen bg-base">
|
||||
<body class="flex flex-col min-h-screen bg-base theme-<?= service('settings')
|
||||
->get('App.theme') ?>">
|
||||
<header class="flex flex-col items-center mb-8">
|
||||
<h1 class="w-full pt-8 pb-32 text-lg font-semibold text-center text-skin-base bg-elevated"><?= lang(
|
||||
<h1 class="w-full pt-8 pb-32 text-lg font-semibold text-center text-white bg-header"><?= lang(
|
||||
'Fediverse.follow.subtitle',
|
||||
) ?></h1>
|
||||
<div class="flex flex-col w-full max-w-xs -mt-24 overflow-hidden shadow bg-elevated rounded-xl">
|
||||
|
@ -52,7 +53,7 @@
|
|||
</header>
|
||||
|
||||
<main class="w-full max-w-md px-4 mx-auto">
|
||||
<form action="<?= route_to('attempt-follow', $actor->username) ?>" method="POST" class="flex flex-col">
|
||||
<form action="<?= route_to('attempt-follow', $actor->username) ?>" method="POST" class="flex flex-col gap-y-2">
|
||||
<?= csrf_field() ?>
|
||||
<?= view('_message_block') ?>
|
||||
|
||||
|
@ -62,18 +63,15 @@
|
|||
hint="<?= lang('Fediverse.your_handle_hint') ?>"
|
||||
required="true"
|
||||
/>
|
||||
<Button variant="primary" type="submit" class="self-end mt-2" iconRight="send-plane"><?= lang('Fediverse.follow.submit') ?></Button>
|
||||
<Button variant="primary" type="submit" class="self-end" iconRight="send-plane"><?= lang('Fediverse.follow.submit') ?></Button>
|
||||
</form>
|
||||
</main>
|
||||
|
||||
<footer
|
||||
class="container flex flex-col items-center px-2 py-4 mx-auto mt-auto text-xs border-t md:justify-between md:flex-row">
|
||||
<?= render_page_links('inline-flex mb-4 md:mb-0') ?>
|
||||
<p>
|
||||
<?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="inline-flex font-semibold hover:underline focus:ring-accent" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
]) ?>
|
||||
</p>
|
||||
class="flex-col w-full px-2 py-4 mt-auto text-xs text-center border-t text-skin-muted border-subtle">
|
||||
<?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="inline-flex font-semibold hover:underline focus:ring-accent" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
]) ?>
|
||||
</footer>
|
||||
</body>
|
||||
|
|
|
@ -34,9 +34,10 @@
|
|||
->asset('js/podcast.ts', 'js') ?>
|
||||
</head>
|
||||
|
||||
<body class="min-h-screen mx-auto bg-base">
|
||||
<header class="pt-8 pb-32 bg-elevated">
|
||||
<h1 class="text-lg font-semibold text-center text-skin-base"><?= lang(
|
||||
<body class="flex flex-col min-h-screen mx-auto bg-base theme-<?= service('settings')
|
||||
->get('App.theme') ?>">
|
||||
<header class="pt-8 pb-32 bg-header">
|
||||
<h1 class="text-lg font-semibold text-center text-white"><?= lang(
|
||||
'Fediverse.' . $action . '.subtitle',
|
||||
) ?></h1>
|
||||
</header>
|
||||
|
@ -47,7 +48,7 @@
|
|||
'post' => $post,
|
||||
]) ?>
|
||||
|
||||
<form action="<?= route_to('post-attempt-remote-action', $post->id, $action) ?>" method="POST" class="flex flex-col mt-8">
|
||||
<form action="<?= route_to('post-attempt-remote-action', $post->id, $action) ?>" method="POST" class="flex flex-col mt-8 gap-y-2">
|
||||
<?= csrf_field() ?>
|
||||
<?= view('_message_block') ?>
|
||||
|
||||
|
@ -60,4 +61,11 @@
|
|||
<Button variant="primary" type="submit" class="self-end" iconRight="send-plane"><?= lang('Fediverse.' . $action . '.submit') ?></Button>
|
||||
</form>
|
||||
</main>
|
||||
<footer
|
||||
class="flex-col w-full px-2 py-4 mt-auto text-xs text-center border-t text-skin-muted border-subtle">
|
||||
<?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="inline-flex font-semibold hover:underline focus:ring-accent" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
]) ?>
|
||||
</footer>
|
||||
</body>
|
||||
|
|
Loading…
Reference in New Issue