style: update background colors to use gray-50 for consistency in auth views

This commit is contained in:
Andras Bacsai 2025-11-06 08:43:43 +01:00
parent 23a3b47011
commit 239e28630f
6 changed files with 241 additions and 232 deletions

View file

@ -82,7 +82,7 @@ @keyframes lds-heart {
*/ */
html, html,
body { body {
@apply w-full min-h-full bg-neutral-50 dark:bg-base dark:text-neutral-400; @apply w-full min-h-full bg-gray-50 dark:bg-base dark:text-neutral-400;
} }
body { body {

View file

@ -61,7 +61,7 @@ class="text-sm dark:text-neutral-400 hover:text-coollabs dark:hover:text-warning
<div class="w-full border-t border-neutral-300 dark:border-coolgray-400"></div> <div class="w-full border-t border-neutral-300 dark:border-coolgray-400"></div>
</div> </div>
<div class="relative flex justify-center text-sm"> <div class="relative flex justify-center text-sm">
<span class="px-2 dark:bg-base text-neutral-500 dark:text-neutral-400"> <span class="px-2 bg-gray-50 dark:bg-base text-neutral-500 dark:text-neutral-400 ">
Don't have an account? Don't have an account?
</span> </span>
</div> </div>
@ -82,7 +82,7 @@ class="block w-full text-center py-3 px-4 rounded-lg border border-neutral-300 d
<div class="w-full border-t border-neutral-300 dark:border-coolgray-400"></div> <div class="w-full border-t border-neutral-300 dark:border-coolgray-400"></div>
</div> </div>
<div class="relative flex justify-center text-sm"> <div class="relative flex justify-center text-sm">
<span class="px-2 dark:bg-base text-neutral-500 dark:text-neutral-400">or <span class="px-2 bg-gray-50 dark:bg-base text-neutral-500 dark:text-neutral-400">or
continue with</span> continue with</span>
</div> </div>
</div> </div>

View file

@ -33,7 +33,8 @@ function getOldOrLocal($key, $localValue)
</svg> </svg>
<div> <div>
<p class="font-bold text-warning">Root User Setup</p> <p class="font-bold text-warning">Root User Setup</p>
<p class="text-sm dark:text-white text-black">This user will be the root user with full admin access.</p> <p class="text-sm dark:text-white text-black">This user will be the root user with full
admin access.</p>
</div> </div>
</div> </div>
</div> </div>
@ -58,13 +59,16 @@ function getOldOrLocal($key, $localValue)
<x-forms.input id="password_confirmation" required type="password" name="password_confirmation" <x-forms.input id="password_confirmation" required type="password" name="password_confirmation"
label="{{ __('input.password.again') }}" /> label="{{ __('input.password.again') }}" />
<div class="p-4 bg-neutral-50 dark:bg-coolgray-200 rounded-lg border border-neutral-200 dark:border-coolgray-400"> <div
class="p-4 bg-neutral-50 dark:bg-coolgray-200 rounded-lg border border-neutral-200 dark:border-coolgray-400">
<p class="text-xs dark:text-neutral-400"> <p class="text-xs dark:text-neutral-400">
Your password should be min 8 characters long and contain at least one uppercase letter, one lowercase letter, one number, and one symbol. Your password should be min 8 characters long and contain at least one uppercase letter,
one lowercase letter, one number, and one symbol.
</p> </p>
</div> </div>
<x-forms.button class="w-full justify-center py-3 box-boarding mt-2" type="submit" isHighlighted> <x-forms.button class="w-full justify-center py-3 box-boarding mt-2" type="submit"
isHighlighted>
Create Account Create Account
</x-forms.button> </x-forms.button>
</form> </form>
@ -74,13 +78,14 @@ function getOldOrLocal($key, $localValue)
<div class="w-full border-t border-neutral-300 dark:border-coolgray-400"></div> <div class="w-full border-t border-neutral-300 dark:border-coolgray-400"></div>
</div> </div>
<div class="relative flex justify-center text-sm"> <div class="relative flex justify-center text-sm">
<span class="px-2 dark:bg-base text-neutral-500 dark:text-neutral-400"> <span class="px-2 bg-gray-50 dark:bg-base text-neutral-500 dark:text-neutral-400">
Already have an account? Already have an account?
</span> </span>
</div> </div>
</div> </div>
<a href="/login" class="block w-full text-center py-3 px-4 rounded-lg border border-neutral-300 dark:border-coolgray-400 font-medium hover:border-coollabs dark:hover:border-warning transition-colors"> <a href="/login"
class="block w-full text-center py-3 px-4 rounded-lg border border-neutral-300 dark:border-coolgray-400 font-medium hover:border-coollabs dark:hover:border-warning transition-colors">
{{ __('auth.already_registered') }} {{ __('auth.already_registered') }}
</a> </a>
</div> </div>

View file

@ -47,16 +47,19 @@
label="{{ __('input.email') }}" /> label="{{ __('input.email') }}" />
<x-forms.input required type="password" id="password" name="password" <x-forms.input required type="password" id="password" name="password"
label="{{ __('input.password') }}" /> label="{{ __('input.password') }}" />
<x-forms.input required type="password" id="password_confirmation" <x-forms.input required type="password" id="password_confirmation" name="password_confirmation"
name="password_confirmation" label="{{ __('input.password.again') }}" /> label="{{ __('input.password.again') }}" />
<div class="p-4 bg-neutral-50 dark:bg-coolgray-200 rounded-lg border border-neutral-200 dark:border-coolgray-400"> <div
class="p-4 bg-neutral-50 dark:bg-coolgray-200 rounded-lg border border-neutral-200 dark:border-coolgray-400">
<p class="text-xs dark:text-neutral-400"> <p class="text-xs dark:text-neutral-400">
Your password should be min 8 characters long and contain at least one uppercase letter, one lowercase letter, one number, and one symbol. Your password should be min 8 characters long and contain at least one uppercase letter,
one lowercase letter, one number, and one symbol.
</p> </p>
</div> </div>
<x-forms.button class="w-full justify-center py-3 box-boarding mt-2" type="submit" isHighlighted> <x-forms.button class="w-full justify-center py-3 box-boarding mt-2" type="submit"
isHighlighted>
{{ __('auth.reset_password') }} {{ __('auth.reset_password') }}
</x-forms.button> </x-forms.button>
</form> </form>
@ -66,13 +69,14 @@
<div class="w-full border-t border-neutral-300 dark:border-coolgray-400"></div> <div class="w-full border-t border-neutral-300 dark:border-coolgray-400"></div>
</div> </div>
<div class="relative flex justify-center text-sm"> <div class="relative flex justify-center text-sm">
<span class="px-2 dark:bg-base text-neutral-500 dark:text-neutral-400"> <span class="px-2 bg-gray-50 dark:bg-base text-neutral-500 dark:text-neutral-400">
Remember your password? Remember your password?
</span> </span>
</div> </div>
</div> </div>
<a href="/login" class="block w-full text-center py-3 px-4 rounded-lg border border-neutral-300 dark:border-coolgray-400 font-medium hover:border-coollabs dark:hover:border-warning transition-colors"> <a href="/login"
class="block w-full text-center py-3 px-4 rounded-lg border border-neutral-300 dark:border-coolgray-400 font-medium hover:border-coollabs dark:hover:border-warning transition-colors">
Back to Login Back to Login
</a> </a>
</div> </div>

View file

@ -120,7 +120,7 @@ class="mt-2 text-sm dark:text-neutral-400 hover:text-black dark:hover:text-white
<div class="w-full border-t border-neutral-300 dark:border-coolgray-400"></div> <div class="w-full border-t border-neutral-300 dark:border-coolgray-400"></div>
</div> </div>
<div class="relative flex justify-center text-sm"> <div class="relative flex justify-center text-sm">
<span class="px-2 dark:bg-base text-neutral-500 dark:text-neutral-400"> <span class="px-2 bg-gray-50 dark:bg-base text-neutral-500 dark:text-neutral-400">
Need help? Need help?
</span> </span>
</div> </div>

View file

@ -2,7 +2,7 @@
<html data-theme="dark" lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <html data-theme="dark" lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<script> <script>
// Immediate theme application - runs before any rendering // Immediate theme application - runs before any rendering
(function() { (function () {
const t = localStorage.theme || 'dark'; const t = localStorage.theme || 'dark';
const d = t === 'dark' || (t === 'system' && matchMedia('(prefers-color-scheme: dark)').matches); const d = t === 'dark' || (t === 'system' && matchMedia('(prefers-color-scheme: dark)').matches);
document.documentElement.classList[d ? 'add' : 'remove']('dark'); document.documentElement.classList[d ? 'add' : 'remove']('dark');
@ -75,102 +75,102 @@
</head> </head>
@section('body') @section('body')
<body> <body class="dark:text-inherit text-black">
<x-toast /> <x-toast />
<script data-navigate-once> <script data-navigate-once>
// Global HTML sanitization function using DOMPurify // Global HTML sanitization function using DOMPurify
window.sanitizeHTML = function(html) { window.sanitizeHTML = function (html) {
if (!html) return ''; if (!html) return '';
const URL_RE = /^(https?:|mailto:)/i; const URL_RE = /^(https?:|mailto:)/i;
const config = { const config = {
ALLOWED_TAGS: ['a', 'b', 'br', 'code', 'del', 'div', 'em', 'i', 'p', 'pre', 's', 'span', 'strong', ALLOWED_TAGS: ['a', 'b', 'br', 'code', 'del', 'div', 'em', 'i', 'p', 'pre', 's', 'span', 'strong',
'u' 'u'
], ],
ALLOWED_ATTR: ['class', 'href', 'target', 'title', 'rel'], ALLOWED_ATTR: ['class', 'href', 'target', 'title', 'rel'],
ALLOW_DATA_ATTR: false, ALLOW_DATA_ATTR: false,
FORBID_TAGS: ['script', 'object', 'embed', 'applet', 'iframe', 'form', 'input', 'button', 'select', FORBID_TAGS: ['script', 'object', 'embed', 'applet', 'iframe', 'form', 'input', 'button', 'select',
'textarea', 'details', 'summary', 'dialog', 'style' 'textarea', 'details', 'summary', 'dialog', 'style'
], ],
FORBID_ATTR: ['onerror', 'onload', 'onclick', 'onmouseover', 'onfocus', 'onblur', 'onchange', FORBID_ATTR: ['onerror', 'onload', 'onclick', 'onmouseover', 'onfocus', 'onblur', 'onchange',
'onsubmit', 'ontoggle', 'style' 'onsubmit', 'ontoggle', 'style'
], ],
KEEP_CONTENT: true, KEEP_CONTENT: true,
RETURN_DOM: false, RETURN_DOM: false,
RETURN_DOM_FRAGMENT: false, RETURN_DOM_FRAGMENT: false,
SANITIZE_DOM: true, SANITIZE_DOM: true,
SANITIZE_NAMED_PROPS: true, SANITIZE_NAMED_PROPS: true,
SAFE_FOR_TEMPLATES: true, SAFE_FOR_TEMPLATES: true,
ALLOWED_URI_REGEXP: URL_RE ALLOWED_URI_REGEXP: URL_RE
};
// One-time hook registration (idempotent pattern)
if (!window.__dpLinkHook) {
DOMPurify.addHook('afterSanitizeAttributes', node => {
// Remove Alpine.js directives to prevent XSS
if (node.hasAttributes && node.hasAttributes()) {
const attrs = Array.from(node.attributes);
attrs.forEach(attr => {
// Remove x-* attributes (Alpine directives)
if (attr.name.startsWith('x-')) {
node.removeAttribute(attr.name);
}
// Remove @* attributes (Alpine event shorthand)
if (attr.name.startsWith('@')) {
node.removeAttribute(attr.name);
}
// Remove :* attributes (Alpine binding shorthand)
if (attr.name.startsWith(':')) {
node.removeAttribute(attr.name);
}
});
}
// Existing link sanitization
if (node.nodeName === 'A' && node.hasAttribute('href')) {
const href = node.getAttribute('href') || '';
if (!URL_RE.test(href)) node.removeAttribute('href');
if (node.getAttribute('target') === '_blank') {
node.setAttribute('rel', 'noopener noreferrer');
}
}
});
window.__dpLinkHook = true;
}
return DOMPurify.sanitize(html, config);
}; };
// Initialize theme if not set // One-time hook registration (idempotent pattern)
if (!('theme' in localStorage)) { if (!window.__dpLinkHook) {
localStorage.theme = 'dark'; DOMPurify.addHook('afterSanitizeAttributes', node => {
} // Remove Alpine.js directives to prevent XSS
if (node.hasAttributes && node.hasAttributes()) {
const attrs = Array.from(node.attributes);
attrs.forEach(attr => {
// Remove x-* attributes (Alpine directives)
if (attr.name.startsWith('x-')) {
node.removeAttribute(attr.name);
}
// Remove @* attributes (Alpine event shorthand)
if (attr.name.startsWith('@')) {
node.removeAttribute(attr.name);
}
// Remove :* attributes (Alpine binding shorthand)
if (attr.name.startsWith(':')) {
node.removeAttribute(attr.name);
}
});
}
let theme = localStorage.theme // Existing link sanitization
let cpuColor = '#1e90ff' if (node.nodeName === 'A' && node.hasAttribute('href')) {
let ramColor = '#00ced1' const href = node.getAttribute('href') || '';
let textColor = '#ffffff' if (!URL_RE.test(href)) node.removeAttribute('href');
let editorBackground = '#181818' if (node.getAttribute('target') === '_blank') {
let editorTheme = 'blackboard' node.setAttribute('rel', 'noopener noreferrer');
}
function checkTheme() { }
theme = localStorage.theme });
if (theme == 'system') { window.__dpLinkHook = true;
theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
if (theme == 'dark') {
cpuColor = '#1e90ff'
ramColor = '#00ced1'
textColor = '#ffffff'
editorBackground = '#181818'
editorTheme = 'blackboard'
} else {
cpuColor = '#1e90ff'
ramColor = '#00ced1'
textColor = '#000000'
editorBackground = '#ffffff'
editorTheme = null
}
} }
@auth return DOMPurify.sanitize(html, config);
};
// Initialize theme if not set
if (!('theme' in localStorage)) {
localStorage.theme = 'dark';
}
let theme = localStorage.theme
let cpuColor = '#1e90ff'
let ramColor = '#00ced1'
let textColor = '#ffffff'
let editorBackground = '#181818'
let editorTheme = 'blackboard'
function checkTheme() {
theme = localStorage.theme
if (theme == 'system') {
theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
if (theme == 'dark') {
cpuColor = '#1e90ff'
ramColor = '#00ced1'
textColor = '#ffffff'
editorBackground = '#181818'
editorTheme = 'blackboard'
} else {
cpuColor = '#1e90ff'
ramColor = '#00ced1'
textColor = '#000000'
editorBackground = '#ffffff'
editorTheme = null
}
}
@auth
window.Pusher = Pusher; window.Pusher = Pusher;
window.Echo = new Echo({ window.Echo = new Echo({
broadcaster: 'pusher', broadcaster: 'pusher',
@ -199,131 +199,131 @@ function checkTheme() {
// Maximum number of reconnection attempts // Maximum number of reconnection attempts
maxAttempts: 15 maxAttempts: 15
}); });
@endauth @endauth
let checkHealthInterval = null; let checkHealthInterval = null;
let checkIfIamDeadInterval = null; let checkIfIamDeadInterval = null;
function changePasswordFieldType(event) { function changePasswordFieldType(event) {
let element = event.target let element = event.target
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
if (element.className === "relative") { if (element.className === "relative") {
break; break;
}
element = element.parentElement;
} }
element = element.children[1]; element = element.parentElement;
if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') { }
if (element.type === 'password') { element = element.children[1];
element.type = 'text'; if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
if (element.disabled) return; if (element.type === 'password') {
element.classList.add('truncate'); element.type = 'text';
this.type = 'text'; if (element.disabled) return;
} else { element.classList.add('truncate');
element.type = 'password'; this.type = 'text';
if (element.disabled) return; } else {
element.classList.remove('truncate'); element.type = 'password';
this.type = 'password'; if (element.disabled) return;
} element.classList.remove('truncate');
this.type = 'password';
} }
} }
}
function copyToClipboard(text) { function copyToClipboard(text) {
navigator?.clipboard?.writeText(text) && window.Livewire.dispatch('success', 'Copied to clipboard.'); navigator?.clipboard?.writeText(text) && window.Livewire.dispatch('success', 'Copied to clipboard.');
} }
document.addEventListener('livewire:init', () => { document.addEventListener('livewire:init', () => {
window.Livewire.on('reloadWindow', (timeout) => { window.Livewire.on('reloadWindow', (timeout) => {
if (timeout) { if (timeout) {
setTimeout(() => { setTimeout(() => {
window.location.reload();
}, timeout);
return;
} else {
window.location.reload(); window.location.reload();
} }, timeout);
}) return;
window.Livewire.on('info', (message) => { } else {
if (typeof message === 'string') { window.location.reload();
window.toast('Info', { }
type: 'info', })
description: message, window.Livewire.on('info', (message) => {
}) if (typeof message === 'string') {
return; window.toast('Info', {
} type: 'info',
if (message.length == 1) { description: message,
window.toast('Info', { })
type: 'info', return;
description: message[0], }
}) if (message.length == 1) {
} else if (message.length == 2) { window.toast('Info', {
window.toast(message[0], { type: 'info',
type: 'info', description: message[0],
description: message[1], })
}) } else if (message.length == 2) {
} window.toast(message[0], {
}) type: 'info',
window.Livewire.on('error', (message) => { description: message[1],
if (typeof message === 'string') { })
window.toast('Error', { }
type: 'danger', })
description: message, window.Livewire.on('error', (message) => {
}) if (typeof message === 'string') {
return; window.toast('Error', {
} type: 'danger',
if (message.length == 1) { description: message,
window.toast('Error', { })
type: 'danger', return;
description: message[0], }
}) if (message.length == 1) {
} else if (message.length == 2) { window.toast('Error', {
window.toast(message[0], { type: 'danger',
type: 'danger', description: message[0],
description: message[1], })
}) } else if (message.length == 2) {
} window.toast(message[0], {
}) type: 'danger',
window.Livewire.on('warning', (message) => { description: message[1],
if (typeof message === 'string') { })
window.toast('Warning', { }
type: 'warning', })
description: message, window.Livewire.on('warning', (message) => {
}) if (typeof message === 'string') {
return; window.toast('Warning', {
} type: 'warning',
if (message.length == 1) { description: message,
window.toast('Warning', { })
type: 'warning', return;
description: message[0], }
}) if (message.length == 1) {
} else if (message.length == 2) { window.toast('Warning', {
window.toast(message[0], { type: 'warning',
type: 'warning', description: message[0],
description: message[1], })
}) } else if (message.length == 2) {
} window.toast(message[0], {
}) type: 'warning',
window.Livewire.on('success', (message) => { description: message[1],
if (typeof message === 'string') { })
window.toast('Success', { }
type: 'success', })
description: message, window.Livewire.on('success', (message) => {
}) if (typeof message === 'string') {
return; window.toast('Success', {
} type: 'success',
if (message.length == 1) { description: message,
window.toast('Success', { })
type: 'success', return;
description: message[0], }
}) if (message.length == 1) {
} else if (message.length == 2) { window.toast('Success', {
window.toast(message[0], { type: 'success',
type: 'success', description: message[0],
description: message[1], })
}) } else if (message.length == 2) {
} window.toast(message[0], {
}) type: 'success',
}); description: message[1],
</script> })
</body> }
})
});
</script>
</body>
@show @show
</html> </html>