mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-28 21:01:22 +00:00
Update the theme
This commit is contained in:
@@ -176,7 +176,7 @@ class ProfileController extends BasePageController
|
||||
// Update color scheme
|
||||
if ($request->has('color_scheme')) {
|
||||
$schemeValue = $request->input('color_scheme');
|
||||
if (in_array($schemeValue, ['blue', 'emerald', 'violet'], true)) {
|
||||
if (in_array($schemeValue, ['blue', 'indigo', 'cyan', 'teal', 'emerald', 'violet', 'pink', 'rose', 'red', 'orange', 'amber'], true)) {
|
||||
User::where('id', $userid)->update(['color_scheme' => $schemeValue]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class UpdateProfileRequest extends FormRequest
|
||||
'email' => ['nullable', 'string', 'email', 'max:255', 'unique:users,email,'.$userId, new ValidEmailDomain],
|
||||
'password' => ['nullable', 'string', 'min:8', 'confirmed', 'regex:/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/'],
|
||||
'theme_preference' => ['sometimes', 'in:light,dark,system'],
|
||||
'color_scheme' => ['sometimes', 'in:blue,emerald,violet'],
|
||||
'color_scheme' => ['sometimes', 'in:blue,indigo,cyan,teal,emerald,violet,pink,rose,red,orange,amber'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ class UpdateThemeRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'theme_preference' => ['sometimes', 'in:light,dark,system'],
|
||||
'color_scheme' => ['sometimes', 'in:blue,emerald,violet'],
|
||||
'color_scheme' => ['sometimes', 'in:blue,indigo,cyan,teal,emerald,violet,pink,rose,red,orange,amber'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,294 @@
|
||||
--color-primary-950: #2e1065;
|
||||
}
|
||||
|
||||
[data-color-scheme="rose"] {
|
||||
--surface-body: #fff1f2;
|
||||
--surface-body-dark: #1f0a12;
|
||||
--surface-sidebar: #3b1825;
|
||||
--surface-sidebar-dark: #13050a;
|
||||
--surface-header: #3b1825;
|
||||
--surface-header-dark: #13050a;
|
||||
--surface-card: #ffffff;
|
||||
--surface-card-dark: #32131e;
|
||||
--surface-dropdown: #2b1019;
|
||||
--surface-dropdown-dark: #13050a;
|
||||
--surface-footer: #3b1825;
|
||||
--surface-footer-dark: #13050a;
|
||||
--surface-hover: #fff1f2;
|
||||
--surface-hover-dark: #4c0519;
|
||||
--border-default: #fecdd3;
|
||||
--border-default-dark: #9f1239;
|
||||
--text-muted: #be123c;
|
||||
--text-muted-dark: #fda4af;
|
||||
--surface-panel-alt: #fff1f2;
|
||||
--surface-panel-alt-dark: #3b1825;
|
||||
--surface-chrome-border: rgba(255,255,255,0.08);
|
||||
--surface-chrome-border-dark: rgba(255,255,255,0.05);
|
||||
--color-primary-50: #fff1f2;
|
||||
--color-primary-100: #ffe4e6;
|
||||
--color-primary-200: #fecdd3;
|
||||
--color-primary-300: #fda4af;
|
||||
--color-primary-400: #fb7185;
|
||||
--color-primary-500: #f43f5e;
|
||||
--color-primary-600: #e11d48;
|
||||
--color-primary-700: #be123c;
|
||||
--color-primary-800: #9f1239;
|
||||
--color-primary-900: #881337;
|
||||
--color-primary-950: #4c0519;
|
||||
}
|
||||
|
||||
[data-color-scheme="amber"] {
|
||||
--surface-body: #fffbeb;
|
||||
--surface-body-dark: #1c1304;
|
||||
--surface-sidebar: #3b2a0e;
|
||||
--surface-sidebar-dark: #120b02;
|
||||
--surface-header: #3b2a0e;
|
||||
--surface-header-dark: #120b02;
|
||||
--surface-card: #ffffff;
|
||||
--surface-card-dark: #33240d;
|
||||
--surface-dropdown: #2c1d08;
|
||||
--surface-dropdown-dark: #120b02;
|
||||
--surface-footer: #3b2a0e;
|
||||
--surface-footer-dark: #120b02;
|
||||
--surface-hover: #fffbeb;
|
||||
--surface-hover-dark: #78350f;
|
||||
--border-default: #fde68a;
|
||||
--border-default-dark: #92400e;
|
||||
--text-muted: #b45309;
|
||||
--text-muted-dark: #fcd34d;
|
||||
--surface-panel-alt: #fffbeb;
|
||||
--surface-panel-alt-dark: #3b2a0e;
|
||||
--surface-chrome-border: rgba(255,255,255,0.08);
|
||||
--surface-chrome-border-dark: rgba(255,255,255,0.05);
|
||||
--color-primary-50: #fffbeb;
|
||||
--color-primary-100: #fef3c7;
|
||||
--color-primary-200: #fde68a;
|
||||
--color-primary-300: #fcd34d;
|
||||
--color-primary-400: #fbbf24;
|
||||
--color-primary-500: #f59e0b;
|
||||
--color-primary-600: #d97706;
|
||||
--color-primary-700: #b45309;
|
||||
--color-primary-800: #92400e;
|
||||
--color-primary-900: #78350f;
|
||||
--color-primary-950: #451a03;
|
||||
}
|
||||
|
||||
[data-color-scheme="cyan"] {
|
||||
--surface-body: #ecfeff;
|
||||
--surface-body-dark: #06191d;
|
||||
--surface-sidebar: #12343c;
|
||||
--surface-sidebar-dark: #031014;
|
||||
--surface-header: #12343c;
|
||||
--surface-header-dark: #031014;
|
||||
--surface-card: #ffffff;
|
||||
--surface-card-dark: #10313a;
|
||||
--surface-dropdown: #0b2a32;
|
||||
--surface-dropdown-dark: #031014;
|
||||
--surface-footer: #12343c;
|
||||
--surface-footer-dark: #031014;
|
||||
--surface-hover: #ecfeff;
|
||||
--surface-hover-dark: #164e63;
|
||||
--border-default: #a5f3fc;
|
||||
--border-default-dark: #155e75;
|
||||
--text-muted: #0e7490;
|
||||
--text-muted-dark: #67e8f9;
|
||||
--surface-panel-alt: #ecfeff;
|
||||
--surface-panel-alt-dark: #12343c;
|
||||
--surface-chrome-border: rgba(255,255,255,0.08);
|
||||
--surface-chrome-border-dark: rgba(255,255,255,0.05);
|
||||
--color-primary-50: #ecfeff;
|
||||
--color-primary-100: #cffafe;
|
||||
--color-primary-200: #a5f3fc;
|
||||
--color-primary-300: #67e8f9;
|
||||
--color-primary-400: #22d3ee;
|
||||
--color-primary-500: #06b6d4;
|
||||
--color-primary-600: #0891b2;
|
||||
--color-primary-700: #0e7490;
|
||||
--color-primary-800: #155e75;
|
||||
--color-primary-900: #164e63;
|
||||
--color-primary-950: #083344;
|
||||
}
|
||||
|
||||
[data-color-scheme="indigo"] {
|
||||
--surface-body: #eef2ff;
|
||||
--surface-body-dark: #0b1024;
|
||||
--surface-sidebar: #1e2850;
|
||||
--surface-sidebar-dark: #070b1b;
|
||||
--surface-header: #1e2850;
|
||||
--surface-header-dark: #070b1b;
|
||||
--surface-card: #ffffff;
|
||||
--surface-card-dark: #182143;
|
||||
--surface-dropdown: #141c39;
|
||||
--surface-dropdown-dark: #070b1b;
|
||||
--surface-footer: #1e2850;
|
||||
--surface-footer-dark: #070b1b;
|
||||
--surface-hover: #eef2ff;
|
||||
--surface-hover-dark: #312e81;
|
||||
--border-default: #c7d2fe;
|
||||
--border-default-dark: #3730a3;
|
||||
--text-muted: #4338ca;
|
||||
--text-muted-dark: #a5b4fc;
|
||||
--surface-panel-alt: #eef2ff;
|
||||
--surface-panel-alt-dark: #1e2850;
|
||||
--surface-chrome-border: rgba(255,255,255,0.08);
|
||||
--surface-chrome-border-dark: rgba(255,255,255,0.05);
|
||||
--color-primary-50: #eef2ff;
|
||||
--color-primary-100: #e0e7ff;
|
||||
--color-primary-200: #c7d2fe;
|
||||
--color-primary-300: #a5b4fc;
|
||||
--color-primary-400: #818cf8;
|
||||
--color-primary-500: #6366f1;
|
||||
--color-primary-600: #4f46e5;
|
||||
--color-primary-700: #4338ca;
|
||||
--color-primary-800: #3730a3;
|
||||
--color-primary-900: #312e81;
|
||||
--color-primary-950: #1e1b4b;
|
||||
}
|
||||
|
||||
[data-color-scheme="teal"] {
|
||||
--surface-body: #f0fdfa;
|
||||
--surface-body-dark: #061a18;
|
||||
--surface-sidebar: #123b36;
|
||||
--surface-sidebar-dark: #021412;
|
||||
--surface-header: #123b36;
|
||||
--surface-header-dark: #021412;
|
||||
--surface-card: #ffffff;
|
||||
--surface-card-dark: #10332f;
|
||||
--surface-dropdown: #0b2b27;
|
||||
--surface-dropdown-dark: #021412;
|
||||
--surface-footer: #123b36;
|
||||
--surface-footer-dark: #021412;
|
||||
--surface-hover: #f0fdfa;
|
||||
--surface-hover-dark: #134e4a;
|
||||
--border-default: #99f6e4;
|
||||
--border-default-dark: #115e59;
|
||||
--text-muted: #0f766e;
|
||||
--text-muted-dark: #5eead4;
|
||||
--surface-panel-alt: #f0fdfa;
|
||||
--surface-panel-alt-dark: #123b36;
|
||||
--surface-chrome-border: rgba(255,255,255,0.08);
|
||||
--surface-chrome-border-dark: rgba(255,255,255,0.05);
|
||||
--color-primary-50: #f0fdfa;
|
||||
--color-primary-100: #ccfbf1;
|
||||
--color-primary-200: #99f6e4;
|
||||
--color-primary-300: #5eead4;
|
||||
--color-primary-400: #2dd4bf;
|
||||
--color-primary-500: #14b8a6;
|
||||
--color-primary-600: #0d9488;
|
||||
--color-primary-700: #0f766e;
|
||||
--color-primary-800: #115e59;
|
||||
--color-primary-900: #134e4a;
|
||||
--color-primary-950: #042f2e;
|
||||
}
|
||||
|
||||
[data-color-scheme="orange"] {
|
||||
--surface-body: #fff7ed;
|
||||
--surface-body-dark: #1f1007;
|
||||
--surface-sidebar: #452515;
|
||||
--surface-sidebar-dark: #160a03;
|
||||
--surface-header: #452515;
|
||||
--surface-header-dark: #160a03;
|
||||
--surface-card: #ffffff;
|
||||
--surface-card-dark: #3a2012;
|
||||
--surface-dropdown: #32190b;
|
||||
--surface-dropdown-dark: #160a03;
|
||||
--surface-footer: #452515;
|
||||
--surface-footer-dark: #160a03;
|
||||
--surface-hover: #fff7ed;
|
||||
--surface-hover-dark: #7c2d12;
|
||||
--border-default: #fed7aa;
|
||||
--border-default-dark: #9a3412;
|
||||
--text-muted: #c2410c;
|
||||
--text-muted-dark: #fdba74;
|
||||
--surface-panel-alt: #fff7ed;
|
||||
--surface-panel-alt-dark: #452515;
|
||||
--surface-chrome-border: rgba(255,255,255,0.08);
|
||||
--surface-chrome-border-dark: rgba(255,255,255,0.05);
|
||||
--color-primary-50: #fff7ed;
|
||||
--color-primary-100: #ffedd5;
|
||||
--color-primary-200: #fed7aa;
|
||||
--color-primary-300: #fdba74;
|
||||
--color-primary-400: #fb923c;
|
||||
--color-primary-500: #f97316;
|
||||
--color-primary-600: #ea580c;
|
||||
--color-primary-700: #c2410c;
|
||||
--color-primary-800: #9a3412;
|
||||
--color-primary-900: #7c2d12;
|
||||
--color-primary-950: #431407;
|
||||
}
|
||||
|
||||
[data-color-scheme="red"] {
|
||||
--surface-body: #fef2f2;
|
||||
--surface-body-dark: #200a0a;
|
||||
--surface-sidebar: #461818;
|
||||
--surface-sidebar-dark: #170505;
|
||||
--surface-header: #461818;
|
||||
--surface-header-dark: #170505;
|
||||
--surface-card: #ffffff;
|
||||
--surface-card-dark: #3a1414;
|
||||
--surface-dropdown: #310f0f;
|
||||
--surface-dropdown-dark: #170505;
|
||||
--surface-footer: #461818;
|
||||
--surface-footer-dark: #170505;
|
||||
--surface-hover: #fef2f2;
|
||||
--surface-hover-dark: #7f1d1d;
|
||||
--border-default: #fecaca;
|
||||
--border-default-dark: #991b1b;
|
||||
--text-muted: #b91c1c;
|
||||
--text-muted-dark: #fca5a5;
|
||||
--surface-panel-alt: #fef2f2;
|
||||
--surface-panel-alt-dark: #461818;
|
||||
--surface-chrome-border: rgba(255,255,255,0.08);
|
||||
--surface-chrome-border-dark: rgba(255,255,255,0.05);
|
||||
--color-primary-50: #fef2f2;
|
||||
--color-primary-100: #fee2e2;
|
||||
--color-primary-200: #fecaca;
|
||||
--color-primary-300: #fca5a5;
|
||||
--color-primary-400: #f87171;
|
||||
--color-primary-500: #ef4444;
|
||||
--color-primary-600: #dc2626;
|
||||
--color-primary-700: #b91c1c;
|
||||
--color-primary-800: #991b1b;
|
||||
--color-primary-900: #7f1d1d;
|
||||
--color-primary-950: #450a0a;
|
||||
}
|
||||
|
||||
[data-color-scheme="pink"] {
|
||||
--surface-body: #fdf2f8;
|
||||
--surface-body-dark: #200a17;
|
||||
--surface-sidebar: #45172f;
|
||||
--surface-sidebar-dark: #17040f;
|
||||
--surface-header: #45172f;
|
||||
--surface-header-dark: #17040f;
|
||||
--surface-card: #ffffff;
|
||||
--surface-card-dark: #391326;
|
||||
--surface-dropdown: #310f20;
|
||||
--surface-dropdown-dark: #17040f;
|
||||
--surface-footer: #45172f;
|
||||
--surface-footer-dark: #17040f;
|
||||
--surface-hover: #fdf2f8;
|
||||
--surface-hover-dark: #831843;
|
||||
--border-default: #fbcfe8;
|
||||
--border-default-dark: #9d174d;
|
||||
--text-muted: #be185d;
|
||||
--text-muted-dark: #f9a8d4;
|
||||
--surface-panel-alt: #fdf2f8;
|
||||
--surface-panel-alt-dark: #45172f;
|
||||
--surface-chrome-border: rgba(255,255,255,0.08);
|
||||
--surface-chrome-border-dark: rgba(255,255,255,0.05);
|
||||
--color-primary-50: #fdf2f8;
|
||||
--color-primary-100: #fce7f3;
|
||||
--color-primary-200: #fbcfe8;
|
||||
--color-primary-300: #f9a8d4;
|
||||
--color-primary-400: #f472b6;
|
||||
--color-primary-500: #ec4899;
|
||||
--color-primary-600: #db2777;
|
||||
--color-primary-700: #be185d;
|
||||
--color-primary-800: #9d174d;
|
||||
--color-primary-900: #831843;
|
||||
--color-primary-950: #500724;
|
||||
}
|
||||
|
||||
/* Theme customization (replaces theme.extend in tailwind.config.js) */
|
||||
@theme {
|
||||
--font-sans: "Figtree", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import Alpine from '@alpinejs/csp';
|
||||
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const colorSchemes = ['blue', 'indigo', 'cyan', 'teal', 'emerald', 'violet', 'pink', 'rose', 'red', 'orange', 'amber'];
|
||||
|
||||
Alpine.store('theme', {
|
||||
current: 'light',
|
||||
@@ -19,18 +20,19 @@ Alpine.store('theme', {
|
||||
|
||||
const schemeMeta = document.querySelector('meta[name="color-scheme-preference"]');
|
||||
const schemeData = document.getElementById('current-theme-data');
|
||||
this.colorScheme = (isAuth && isAuth.content === 'true')
|
||||
const preferredScheme = (isAuth && isAuth.content === 'true')
|
||||
? (schemeMeta ? schemeMeta.content : (schemeData?.dataset?.colorScheme || 'blue'))
|
||||
: (localStorage.getItem('color_scheme') || 'blue');
|
||||
this.colorScheme = colorSchemes.includes(preferredScheme) ? preferredScheme : 'blue';
|
||||
|
||||
this.apply();
|
||||
this.applyScheme();
|
||||
this._listenOS();
|
||||
},
|
||||
|
||||
/** Set and persist color scheme (blue, emerald, violet) */
|
||||
/** Set and persist a supported color scheme. */
|
||||
setScheme(scheme) {
|
||||
if (!['blue', 'emerald', 'violet'].includes(scheme)) return;
|
||||
if (!colorSchemes.includes(scheme)) return;
|
||||
this.colorScheme = scheme;
|
||||
this.applyScheme();
|
||||
this._save();
|
||||
@@ -114,6 +116,7 @@ Alpine.store('theme', {
|
||||
// Update color scheme swatch buttons
|
||||
document.querySelectorAll('.dropdown-scheme-btn, .mobile-scheme-btn').forEach(function(btn) {
|
||||
var isActive = btn.dataset.scheme === self.colorScheme;
|
||||
btn.setAttribute('aria-pressed', isActive ? 'true' : 'false');
|
||||
btn.classList.remove('ring-2', 'ring-offset-2', 'ring-offset-gray-900', 'ring-primary-500', 'ring-white');
|
||||
if (isActive) {
|
||||
btn.classList.add('ring-2', 'ring-offset-2', 'ring-offset-gray-900', 'ring-primary-500', 'dark:ring-offset-gray-950');
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
'current' => null,
|
||||
])
|
||||
|
||||
<header {{ $attributes->merge(['class' => 'app-page-header workspace-hero relative mb-6 overflow-hidden rounded-2xl px-5 py-6 text-white shadow-lg sm:px-7 sm:py-8']) }}>
|
||||
<header {{ $attributes->merge(['class' => 'app-page-header workspace-hero relative mb-6 overflow-hidden rounded-2xl px-5 py-4 text-white shadow-lg sm:px-7 sm:py-5']) }}>
|
||||
<div class="workspace-hero__glow workspace-hero__glow--one" aria-hidden="true"></div>
|
||||
<div class="workspace-hero__glow workspace-hero__glow--two" aria-hidden="true"></div>
|
||||
|
||||
<div class="relative z-10 flex flex-col gap-6 xl:flex-row xl:items-end xl:justify-between">
|
||||
<div class="min-w-0 max-w-3xl">
|
||||
<nav aria-label="Breadcrumb" class="mb-4 text-sm text-white/70">
|
||||
<div class="relative z-10 flex flex-col gap-4 xl:flex-row xl:items-end xl:justify-between">
|
||||
<div class="min-w-0 max-w-3xl xl:flex-1">
|
||||
<nav aria-label="Breadcrumb" class="mb-2 text-sm text-white/70">
|
||||
<ol class="flex flex-wrap items-center gap-2">
|
||||
<li><a href="{{ url('/') }}" class="rounded hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/70">Home</a></li>
|
||||
<li aria-hidden="true"><i class="fas fa-chevron-right text-[0.65rem]"></i></li>
|
||||
@@ -33,20 +33,25 @@
|
||||
</div>
|
||||
|
||||
@if($description)
|
||||
<p class="mt-4 max-w-2xl text-sm leading-6 text-white/75 sm:text-base">{{ $description }}</p>
|
||||
<p class="mt-2 max-w-2xl text-sm leading-5 text-white/75 sm:text-base">{{ $description }}</p>
|
||||
@endif
|
||||
|
||||
@isset($stats)
|
||||
<div class="mt-5 flex flex-wrap gap-2 text-sm">
|
||||
{{ $stats }}
|
||||
</div>
|
||||
@endisset
|
||||
</div>
|
||||
|
||||
@isset($actions)
|
||||
<div class="app-page-header__actions flex shrink-0 flex-wrap items-center gap-3">
|
||||
{{ $actions }}
|
||||
@if(isset($stats) || isset($actions))
|
||||
<div class="app-page-header__meta flex min-w-0 flex-wrap items-center gap-3 xl:max-w-[48%] xl:justify-end">
|
||||
@isset($stats)
|
||||
<div class="flex flex-wrap gap-2 text-sm xl:justify-end">
|
||||
{{ $stats }}
|
||||
</div>
|
||||
@endisset
|
||||
|
||||
@isset($actions)
|
||||
<div class="app-page-header__actions flex flex-wrap items-center gap-3">
|
||||
{{ $actions }}
|
||||
</div>
|
||||
@endisset
|
||||
</div>
|
||||
@endisset
|
||||
@endif
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
@endphp
|
||||
|
||||
<div class="space-y-5" x-data="moviesPage" data-movie-layout="{{ $movie_layout ?? 2 }}">
|
||||
<section class="movies-hero relative overflow-hidden rounded-2xl px-5 py-6 text-white shadow-lg sm:px-7 sm:py-8" aria-labelledby="movies-heading">
|
||||
<section class="movies-hero relative overflow-hidden rounded-2xl px-5 py-4 text-white shadow-lg sm:px-7 sm:py-5" aria-labelledby="movies-heading">
|
||||
<div class="movies-hero__glow movies-hero__glow--one" aria-hidden="true"></div>
|
||||
<div class="movies-hero__glow movies-hero__glow--two" aria-hidden="true"></div>
|
||||
|
||||
<div class="relative z-10 flex flex-col gap-6 xl:flex-row xl:items-end xl:justify-between">
|
||||
<div class="max-w-3xl">
|
||||
<nav aria-label="Breadcrumb" class="mb-4 text-sm text-white/70">
|
||||
<div class="relative z-10 flex flex-col gap-4 xl:flex-row xl:items-end xl:justify-between">
|
||||
<div class="min-w-0 max-w-3xl xl:flex-1">
|
||||
<nav aria-label="Breadcrumb" class="mb-2 text-sm text-white/70">
|
||||
<ol class="flex flex-wrap items-center gap-2">
|
||||
<li><a href="{{ url($site['home_link'] ?? '/') }}" class="rounded hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/70">Home</a></li>
|
||||
<li aria-hidden="true"><i class="fas fa-chevron-right text-[0.65rem]"></i></li>
|
||||
@@ -38,11 +38,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="mt-4 max-w-2xl text-sm leading-6 text-white/75 sm:text-base">
|
||||
<p class="mt-2 max-w-2xl text-sm leading-5 text-white/75 sm:text-base">
|
||||
Browse available movies, compare recent releases, and narrow the catalog by title, genre, year, or rating.
|
||||
</p>
|
||||
|
||||
<div class="mt-5 flex flex-wrap gap-2 text-sm">
|
||||
</div>
|
||||
|
||||
<div class="movies-hero__meta flex min-w-0 flex-wrap items-center gap-3 xl:max-w-[48%] xl:justify-end">
|
||||
<div class="flex flex-wrap gap-2 text-sm xl:justify-end">
|
||||
<span class="movies-hero__stat">
|
||||
<i class="fas fa-film" aria-hidden="true"></i>
|
||||
{{ isset($results) ? number_format($results->total()) : 0 }} movies
|
||||
@@ -58,22 +61,22 @@
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<button type="button"
|
||||
@click="toggleLayout()"
|
||||
class="movies-hero__action"
|
||||
:aria-label="layout === 1 ? 'Switch to two-column movie grid' : 'Switch to one-column movie list'"
|
||||
title="Change movie layout">
|
||||
<i :class="layoutIcon" aria-hidden="true"></i>
|
||||
<span x-text="layoutLabel"></span>
|
||||
</button>
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<button type="button"
|
||||
@click="toggleLayout()"
|
||||
class="movies-hero__action"
|
||||
:aria-label="layout === 1 ? 'Switch to two-column movie grid' : 'Switch to one-column movie list'"
|
||||
title="Change movie layout">
|
||||
<i :class="layoutIcon" aria-hidden="true"></i>
|
||||
<span x-text="layoutLabel"></span>
|
||||
</button>
|
||||
|
||||
<a href="{{ route('trending-movies') }}" class="movies-hero__action movies-hero__action--accent">
|
||||
<i class="fas fa-fire" aria-hidden="true"></i>
|
||||
Trending now
|
||||
</a>
|
||||
<a href="{{ route('trending-movies') }}" class="movies-hero__action movies-hero__action--accent">
|
||||
<i class="fas fa-fire" aria-hidden="true"></i>
|
||||
Trending now
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,16 +1,28 @@
|
||||
{{-- Shared color scheme switcher. JS hooks by button class (see alpine/stores/theme.js). Expects: $switcherId, $btnClass, $mobile (bool) --}}
|
||||
@php $currentScheme = $userColorScheme ?? 'blue'; @endphp
|
||||
<div class="flex items-center justify-center {{ $mobile ? 'gap-3' : 'gap-2' }}" id="{{ $switcherId }}">
|
||||
<button type="button" data-scheme="blue" title="Blue"
|
||||
class="{{ $btnClass }} {{ $mobile ? 'w-9 h-9' : 'w-8 h-8' }} rounded-full bg-blue-600 transition {{ $mobile ? 'touch-target ' : '' }}ring-offset-2 ring-offset-gray-900 {{ $currentScheme === 'blue' ? 'ring-2 ring-primary-500' : '' }}">
|
||||
<span class="sr-only">Blue</span>
|
||||
</button>
|
||||
<button type="button" data-scheme="emerald" title="Emerald"
|
||||
class="{{ $btnClass }} {{ $mobile ? 'w-9 h-9' : 'w-8 h-8' }} rounded-full bg-emerald-600 transition {{ $mobile ? 'touch-target ' : '' }}ring-offset-2 ring-offset-gray-900 {{ $currentScheme === 'emerald' ? 'ring-2 ring-primary-500' : '' }}">
|
||||
<span class="sr-only">Emerald</span>
|
||||
</button>
|
||||
<button type="button" data-scheme="violet" title="Violet"
|
||||
class="{{ $btnClass }} {{ $mobile ? 'w-9 h-9' : 'w-8 h-8' }} rounded-full bg-violet-600 transition {{ $mobile ? 'touch-target ' : '' }}ring-offset-2 ring-offset-gray-900 {{ $currentScheme === 'violet' ? 'ring-2 ring-primary-500' : '' }}">
|
||||
<span class="sr-only">Violet</span>
|
||||
</button>
|
||||
@php
|
||||
$currentScheme = $userColorScheme ?? 'blue';
|
||||
$colorSchemes = [
|
||||
['value' => 'blue', 'label' => 'Blue', 'swatch' => 'bg-blue-600'],
|
||||
['value' => 'indigo', 'label' => 'Indigo', 'swatch' => 'bg-indigo-600'],
|
||||
['value' => 'cyan', 'label' => 'Cyan', 'swatch' => 'bg-cyan-600'],
|
||||
['value' => 'teal', 'label' => 'Teal', 'swatch' => 'bg-teal-600'],
|
||||
['value' => 'emerald', 'label' => 'Emerald', 'swatch' => 'bg-emerald-600'],
|
||||
['value' => 'violet', 'label' => 'Violet', 'swatch' => 'bg-violet-600'],
|
||||
['value' => 'pink', 'label' => 'Pink', 'swatch' => 'bg-pink-600'],
|
||||
['value' => 'rose', 'label' => 'Rose', 'swatch' => 'bg-rose-600'],
|
||||
['value' => 'red', 'label' => 'Red', 'swatch' => 'bg-red-600'],
|
||||
['value' => 'orange', 'label' => 'Orange', 'swatch' => 'bg-orange-600'],
|
||||
['value' => 'amber', 'label' => 'Amber', 'swatch' => 'bg-amber-600'],
|
||||
];
|
||||
@endphp
|
||||
<div class="grid grid-cols-4 place-items-center {{ $mobile ? 'gap-3' : 'gap-2' }}" id="{{ $switcherId }}">
|
||||
@foreach($colorSchemes as $scheme)
|
||||
<button type="button"
|
||||
data-scheme="{{ $scheme['value'] }}"
|
||||
title="{{ $scheme['label'] }}"
|
||||
aria-pressed="{{ $currentScheme === $scheme['value'] ? 'true' : 'false' }}"
|
||||
class="{{ $btnClass }} {{ $mobile ? 'w-9 h-9' : 'w-8 h-8' }} rounded-full {{ $scheme['swatch'] }} transition {{ $mobile ? 'touch-target ' : '' }}ring-offset-2 ring-offset-gray-900 {{ $currentScheme === $scheme['value'] ? 'ring-2 ring-primary-500' : '' }}">
|
||||
<span class="sr-only">{{ $scheme['label'] }}</span>
|
||||
</button>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
var t = localStorage.getItem('theme') || 'light';
|
||||
var scheme = localStorage.getItem('color_scheme') || 'blue';
|
||||
@endauth
|
||||
var allowedSchemes = ['blue', 'indigo', 'cyan', 'teal', 'emerald', 'violet', 'pink', 'rose', 'red', 'orange', 'amber'];
|
||||
if (allowedSchemes.indexOf(scheme) === -1) {
|
||||
scheme = 'blue';
|
||||
}
|
||||
var isDark = t === 'dark' || (t === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||
if (isDark) {
|
||||
d.classList.add('dark');
|
||||
@@ -34,4 +38,20 @@ html[data-color-scheme="emerald"], html[data-color-scheme="emerald"] body { back
|
||||
html.dark[data-color-scheme="emerald"], html.dark[data-color-scheme="emerald"] body { background-color: #071a12; color: #d1fae5; }
|
||||
html[data-color-scheme="violet"], html[data-color-scheme="violet"] body { background-color: #faf5ff; color: #1e293b; }
|
||||
html.dark[data-color-scheme="violet"], html.dark[data-color-scheme="violet"] body { background-color: #120b20; color: #e9d5ff; }
|
||||
html[data-color-scheme="rose"], html[data-color-scheme="rose"] body { background-color: #fff1f2; color: #1e293b; }
|
||||
html.dark[data-color-scheme="rose"], html.dark[data-color-scheme="rose"] body { background-color: #1f0a12; color: #fecdd3; }
|
||||
html[data-color-scheme="amber"], html[data-color-scheme="amber"] body { background-color: #fffbeb; color: #1e293b; }
|
||||
html.dark[data-color-scheme="amber"], html.dark[data-color-scheme="amber"] body { background-color: #1c1304; color: #fde68a; }
|
||||
html[data-color-scheme="cyan"], html[data-color-scheme="cyan"] body { background-color: #ecfeff; color: #1e293b; }
|
||||
html.dark[data-color-scheme="cyan"], html.dark[data-color-scheme="cyan"] body { background-color: #06191d; color: #cffafe; }
|
||||
html[data-color-scheme="indigo"], html[data-color-scheme="indigo"] body { background-color: #eef2ff; color: #1e293b; }
|
||||
html.dark[data-color-scheme="indigo"], html.dark[data-color-scheme="indigo"] body { background-color: #0b1024; color: #c7d2fe; }
|
||||
html[data-color-scheme="teal"], html[data-color-scheme="teal"] body { background-color: #f0fdfa; color: #1e293b; }
|
||||
html.dark[data-color-scheme="teal"], html.dark[data-color-scheme="teal"] body { background-color: #061a18; color: #ccfbf1; }
|
||||
html[data-color-scheme="orange"], html[data-color-scheme="orange"] body { background-color: #fff7ed; color: #1e293b; }
|
||||
html.dark[data-color-scheme="orange"], html.dark[data-color-scheme="orange"] body { background-color: #1f1007; color: #ffedd5; }
|
||||
html[data-color-scheme="red"], html[data-color-scheme="red"] body { background-color: #fef2f2; color: #1e293b; }
|
||||
html.dark[data-color-scheme="red"], html.dark[data-color-scheme="red"] body { background-color: #200a0a; color: #fee2e2; }
|
||||
html[data-color-scheme="pink"], html[data-color-scheme="pink"] body { background-color: #fdf2f8; color: #1e293b; }
|
||||
html.dark[data-color-scheme="pink"], html.dark[data-color-scheme="pink"] body { background-color: #200a17; color: #fce7f3; }
|
||||
</style>
|
||||
|
||||
@@ -128,26 +128,35 @@
|
||||
<i class="fas fa-swatchbook mr-2 text-primary-600"></i>Color Scheme
|
||||
</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-3">Choose the main color scheme for the site (sidebar, header, buttons, and accents).</p>
|
||||
<div class="flex flex-wrap items-center gap-4">
|
||||
@php $currentScheme = $user->color_scheme ?? 'blue'; @endphp
|
||||
<label class="flex items-center gap-2 cursor-pointer">
|
||||
<input type="radio" name="color_scheme" value="blue" {{ $currentScheme === 'blue' ? 'checked' : '' }}
|
||||
class="sr-only profile-scheme-radio" data-scheme="blue">
|
||||
<span class="w-10 h-10 rounded-full bg-blue-600 ring-2 ring-offset-2 transition {{ $currentScheme === 'blue' ? 'ring-primary-500 ring-offset-gray-100 dark:ring-offset-gray-800' : 'ring-transparent ring-offset-gray-100 dark:ring-offset-gray-800 hover:ring-gray-300' }}" aria-hidden="true"></span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">Blue</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-2 cursor-pointer">
|
||||
<input type="radio" name="color_scheme" value="emerald" {{ $currentScheme === 'emerald' ? 'checked' : '' }}
|
||||
class="sr-only profile-scheme-radio" data-scheme="emerald">
|
||||
<span class="w-10 h-10 rounded-full bg-emerald-600 ring-2 ring-offset-2 transition {{ $currentScheme === 'emerald' ? 'ring-primary-500 ring-offset-gray-100 dark:ring-offset-gray-800' : 'ring-transparent ring-offset-gray-100 dark:ring-offset-gray-800 hover:ring-gray-300' }}" aria-hidden="true"></span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">Emerald</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-2 cursor-pointer">
|
||||
<input type="radio" name="color_scheme" value="violet" {{ $currentScheme === 'violet' ? 'checked' : '' }}
|
||||
class="sr-only profile-scheme-radio" data-scheme="violet">
|
||||
<span class="w-10 h-10 rounded-full bg-violet-600 ring-2 ring-offset-2 transition {{ $currentScheme === 'violet' ? 'ring-primary-500 ring-offset-gray-100 dark:ring-offset-gray-800' : 'ring-transparent ring-offset-gray-100 dark:ring-offset-gray-800 hover:ring-gray-300' }}" aria-hidden="true"></span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">Violet</span>
|
||||
</label>
|
||||
@php
|
||||
$currentScheme = $user->color_scheme ?? 'blue';
|
||||
$colorSchemes = [
|
||||
['value' => 'blue', 'label' => 'Blue', 'swatch' => 'bg-blue-600'],
|
||||
['value' => 'indigo', 'label' => 'Indigo', 'swatch' => 'bg-indigo-600'],
|
||||
['value' => 'cyan', 'label' => 'Cyan', 'swatch' => 'bg-cyan-600'],
|
||||
['value' => 'teal', 'label' => 'Teal', 'swatch' => 'bg-teal-600'],
|
||||
['value' => 'emerald', 'label' => 'Emerald', 'swatch' => 'bg-emerald-600'],
|
||||
['value' => 'violet', 'label' => 'Violet', 'swatch' => 'bg-violet-600'],
|
||||
['value' => 'pink', 'label' => 'Pink', 'swatch' => 'bg-pink-600'],
|
||||
['value' => 'rose', 'label' => 'Rose', 'swatch' => 'bg-rose-600'],
|
||||
['value' => 'red', 'label' => 'Red', 'swatch' => 'bg-red-600'],
|
||||
['value' => 'orange', 'label' => 'Orange', 'swatch' => 'bg-orange-600'],
|
||||
['value' => 'amber', 'label' => 'Amber', 'swatch' => 'bg-amber-600'],
|
||||
];
|
||||
@endphp
|
||||
<div class="grid grid-cols-2 gap-3 sm:grid-cols-3 xl:grid-cols-4">
|
||||
@foreach($colorSchemes as $scheme)
|
||||
<label class="flex cursor-pointer items-center gap-3 rounded-xl border border-gray-200 p-3 transition hover:border-primary-300 hover:bg-primary-50 dark:border-gray-700 dark:hover:border-primary-700 dark:hover:bg-primary-950/30">
|
||||
<input type="radio"
|
||||
name="color_scheme"
|
||||
value="{{ $scheme['value'] }}"
|
||||
{{ $currentScheme === $scheme['value'] ? 'checked' : '' }}
|
||||
class="sr-only profile-scheme-radio"
|
||||
data-scheme="{{ $scheme['value'] }}">
|
||||
<span class="h-10 w-10 shrink-0 rounded-full {{ $scheme['swatch'] }} ring-2 ring-offset-2 transition {{ $currentScheme === $scheme['value'] ? 'ring-primary-500 ring-offset-gray-100 dark:ring-offset-gray-800' : 'ring-transparent ring-offset-gray-100 hover:ring-gray-300 dark:ring-offset-gray-800' }}" aria-hidden="true"></span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">{{ $scheme['label'] }}</span>
|
||||
</label>
|
||||
@endforeach
|
||||
</div>
|
||||
<p class="mt-3 text-xs text-gray-500 dark:text-gray-400">
|
||||
<i class="fas fa-info-circle mr-1"></i>Save your profile to apply the color scheme. You can also change it from the user menu in the header.
|
||||
|
||||
@@ -96,6 +96,21 @@ class LayoutShellMarkupTest extends TestCase
|
||||
$this->assertStringContainsString('aria-label="Pagination"', $this->view('components/admin/pagination.blade.php'));
|
||||
}
|
||||
|
||||
public function test_shared_user_hero_uses_compact_vertical_spacing(): void
|
||||
{
|
||||
$hero = $this->view('components/page-header.blade.php');
|
||||
|
||||
$this->assertStringContainsString('px-5 py-4', $hero);
|
||||
$this->assertStringContainsString('sm:px-7 sm:py-5', $hero);
|
||||
$this->assertStringContainsString('flex flex-col gap-4', $hero);
|
||||
$this->assertStringContainsString('aria-label="Breadcrumb" class="mb-2', $hero);
|
||||
$this->assertStringContainsString('class="mt-2 max-w-2xl text-sm leading-5', $hero);
|
||||
$this->assertStringContainsString('app-page-header__meta flex min-w-0 flex-wrap', $hero);
|
||||
$this->assertStringContainsString('@if(isset($stats) || isset($actions))', $hero);
|
||||
$this->assertStringNotContainsString('mt-3 flex flex-wrap gap-2 text-sm', $hero);
|
||||
$this->assertStringNotContainsString('sm:py-8', $hero);
|
||||
}
|
||||
|
||||
public function test_shared_view_styles_cover_application_admin_and_guest_surfaces(): void
|
||||
{
|
||||
$stylesheet = $this->resource('css/app.css');
|
||||
|
||||
@@ -23,6 +23,20 @@ class MoviesPageMarkupTest extends TestCase
|
||||
$this->assertStringContainsString(':aria-label="layout === 1', $markup);
|
||||
}
|
||||
|
||||
public function test_movie_hero_matches_the_compact_shared_hero_spacing(): void
|
||||
{
|
||||
$markup = $this->resource('views/movies/index.blade.php');
|
||||
|
||||
$this->assertStringContainsString('movies-hero relative overflow-hidden rounded-2xl px-5 py-4', $markup);
|
||||
$this->assertStringContainsString('sm:px-7 sm:py-5', $markup);
|
||||
$this->assertStringContainsString('relative z-10 flex flex-col gap-4', $markup);
|
||||
$this->assertStringContainsString('aria-label="Breadcrumb" class="mb-2', $markup);
|
||||
$this->assertStringContainsString('class="mt-2 max-w-2xl text-sm leading-5', $markup);
|
||||
$this->assertStringContainsString('movies-hero__meta flex min-w-0 flex-wrap', $markup);
|
||||
$this->assertStringNotContainsString('mt-3 flex flex-wrap gap-2 text-sm', $markup);
|
||||
$this->assertStringNotContainsString('sm:py-8', $markup);
|
||||
}
|
||||
|
||||
public function test_movie_cards_reserve_poster_space_and_reuse_release_rows(): void
|
||||
{
|
||||
$card = $this->resource('views/movies/partials/movie-card.blade.php');
|
||||
|
||||
@@ -2,10 +2,19 @@
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Http\Requests\UpdateThemeRequest;
|
||||
use Illuminate\Translation\ArrayLoader;
|
||||
use Illuminate\Translation\Translator;
|
||||
use Illuminate\Validation\Factory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ThemeTableStylesTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private const COLOR_SCHEMES = ['blue', 'indigo', 'cyan', 'teal', 'emerald', 'violet', 'pink', 'rose', 'red', 'orange', 'amber'];
|
||||
|
||||
public function test_light_color_schemes_use_pale_table_hover_surfaces(): void
|
||||
{
|
||||
$stylesheet = (string) file_get_contents(__DIR__.'/../../resources/css/app.css');
|
||||
@@ -13,6 +22,14 @@ class ThemeTableStylesTest extends TestCase
|
||||
$this->assertStringContainsString('--surface-hover: #f1f5f9;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover: #ecfdf5;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover: #f5f3ff;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover: #fff1f2;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover: #fffbeb;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover: #ecfeff;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover: #eef2ff;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover: #f0fdfa;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover: #fff7ed;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover: #fef2f2;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover: #fdf2f8;', $stylesheet);
|
||||
$this->assertMatchesRegularExpression(
|
||||
'/main tbody tr:hover\s*\{\s*background-color: var\(--surface-hover\) !important;\s*\}/',
|
||||
$stylesheet,
|
||||
@@ -26,9 +43,77 @@ class ThemeTableStylesTest extends TestCase
|
||||
$this->assertStringContainsString('--surface-hover-dark: #1e293b;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover-dark: #14532d;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover-dark: #3b0764;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover-dark: #4c0519;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover-dark: #78350f;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover-dark: #164e63;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover-dark: #312e81;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover-dark: #134e4a;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover-dark: #7c2d12;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover-dark: #7f1d1d;', $stylesheet);
|
||||
$this->assertStringContainsString('--surface-hover-dark: #831843;', $stylesheet);
|
||||
$this->assertMatchesRegularExpression(
|
||||
'/\.dark main tbody tr:hover\s*\{\s*background-color: var\(--surface-hover-dark\) !important;\s*\}/',
|
||||
$stylesheet,
|
||||
);
|
||||
}
|
||||
|
||||
public function test_every_color_scheme_defines_complete_surface_and_accent_tokens(): void
|
||||
{
|
||||
$stylesheet = (string) file_get_contents(__DIR__.'/../../resources/css/app.css');
|
||||
|
||||
foreach (self::COLOR_SCHEMES as $scheme) {
|
||||
$matched = preg_match(
|
||||
'/\[data-color-scheme="'.preg_quote($scheme, '/').'"\]\s*\{(?<tokens>.*?)\}/s',
|
||||
$stylesheet,
|
||||
$matches,
|
||||
);
|
||||
|
||||
$this->assertSame(1, $matched, "{$scheme} must define a color-scheme token block.");
|
||||
|
||||
foreach (['--surface-body:', '--surface-body-dark:', '--surface-hover:', '--surface-hover-dark:', '--color-primary-50:', '--color-primary-500:', '--color-primary-950:'] as $token) {
|
||||
$this->assertStringContainsString($token, $matches['tokens'], "{$scheme} must define {$token}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function test_color_scheme_options_stay_in_sync_across_the_ui_and_persistence_layers(): void
|
||||
{
|
||||
$switcher = (string) file_get_contents(__DIR__.'/../../resources/views/partials/scheme-switcher.blade.php');
|
||||
$profile = (string) file_get_contents(__DIR__.'/../../resources/views/profile/edit.blade.php');
|
||||
$themeInit = (string) file_get_contents(__DIR__.'/../../resources/views/partials/theme-init.blade.php');
|
||||
$themeStore = (string) file_get_contents(__DIR__.'/../../resources/js/alpine/stores/theme.js');
|
||||
$profileRequest = (string) file_get_contents(__DIR__.'/../../app/Http/Requests/UpdateProfileRequest.php');
|
||||
$profileController = (string) file_get_contents(__DIR__.'/../../app/Http/Controllers/ProfileController.php');
|
||||
$schemeList = implode(',', self::COLOR_SCHEMES);
|
||||
$javascriptSchemeList = "'".implode("', '", self::COLOR_SCHEMES)."'";
|
||||
|
||||
$this->assertStringContainsString("const colorSchemes = [{$javascriptSchemeList}]", $themeStore);
|
||||
$this->assertStringContainsString("in:{$schemeList}", $profileRequest);
|
||||
$this->assertStringContainsString($javascriptSchemeList, $themeInit);
|
||||
$this->assertStringContainsString($javascriptSchemeList, $profileController);
|
||||
|
||||
foreach (self::COLOR_SCHEMES as $scheme) {
|
||||
$this->assertStringContainsString("'value' => '{$scheme}'", $switcher);
|
||||
$this->assertStringContainsString("'value' => '{$scheme}'", $profile);
|
||||
|
||||
if ($scheme !== 'blue') {
|
||||
$this->assertStringContainsString("data-color-scheme=\"{$scheme}\"", $themeInit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function test_theme_update_validation_accepts_each_supported_scheme_and_rejects_unknown_values(): void
|
||||
{
|
||||
$validator = new Factory(new Translator(new ArrayLoader, 'en'));
|
||||
$rules = (new UpdateThemeRequest)->rules();
|
||||
|
||||
foreach (self::COLOR_SCHEMES as $scheme) {
|
||||
$this->assertFalse(
|
||||
$validator->make(['color_scheme' => $scheme], $rules)->fails(),
|
||||
"{$scheme} should be accepted as a color scheme.",
|
||||
);
|
||||
}
|
||||
|
||||
$this->assertTrue($validator->make(['color_scheme' => 'unknown'], $rules)->fails());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user