mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Update JS to show live changes and set light color values
This commit is contained in:
parent
c337439370
commit
104621841b
@ -24,7 +24,7 @@ return [
|
|||||||
'page-draft-color' => '#7e50b1',
|
'page-draft-color' => '#7e50b1',
|
||||||
'app-color-dark' => '#195785',
|
'app-color-dark' => '#195785',
|
||||||
'app-color-light-dark' => 'rgba(32,110,167,0.15)',
|
'app-color-light-dark' => 'rgba(32,110,167,0.15)',
|
||||||
'link-color-dark' => '#195785',
|
'link-color-dark' => '#429fe3',
|
||||||
'bookshelf-color-dark' => '#ff5454',
|
'bookshelf-color-dark' => '#ff5454',
|
||||||
'book-color-dark' => '#389f60',
|
'book-color-dark' => '#389f60',
|
||||||
'chapter-color-dark' => '#ee7a2d',
|
'chapter-color-dark' => '#ee7a2d',
|
||||||
|
@ -41,7 +41,7 @@ export {PagePicker} from "./page-picker.js"
|
|||||||
export {PermissionsTable} from "./permissions-table.js"
|
export {PermissionsTable} from "./permissions-table.js"
|
||||||
export {Pointer} from "./pointer.js"
|
export {Pointer} from "./pointer.js"
|
||||||
export {Popup} from "./popup.js"
|
export {Popup} from "./popup.js"
|
||||||
export {SettingAppColorPicker} from "./setting-app-color-picker.js"
|
export {SettingAppColorScheme} from "./setting-app-color-scheme.js"
|
||||||
export {SettingColorPicker} from "./setting-color-picker.js"
|
export {SettingColorPicker} from "./setting-color-picker.js"
|
||||||
export {SettingHomepageControl} from "./setting-homepage-control.js"
|
export {SettingHomepageControl} from "./setting-homepage-control.js"
|
||||||
export {ShelfSort} from "./shelf-sort.js"
|
export {ShelfSort} from "./shelf-sort.js"
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
import {Component} from "./component";
|
|
||||||
|
|
||||||
export class SettingAppColorPicker extends Component {
|
|
||||||
|
|
||||||
setup() {
|
|
||||||
// TODO
|
|
||||||
this.colorInput = this.$refs.input;
|
|
||||||
this.lightColorInput = this.$refs.lightInput;
|
|
||||||
|
|
||||||
this.colorInput.addEventListener('change', this.updateColor.bind(this));
|
|
||||||
this.colorInput.addEventListener('input', this.updateColor.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the app colors as a preview, and create a light version of the color.
|
|
||||||
*/
|
|
||||||
updateColor() {
|
|
||||||
const hexVal = this.colorInput.value;
|
|
||||||
const rgb = this.hexToRgb(hexVal);
|
|
||||||
const rgbLightVal = 'rgba('+ [rgb.r, rgb.g, rgb.b, '0.15'].join(',') +')';
|
|
||||||
|
|
||||||
this.lightColorInput.value = rgbLightVal;
|
|
||||||
|
|
||||||
const customStyles = document.getElementById('custom-styles');
|
|
||||||
const oldColor = customStyles.getAttribute('data-color');
|
|
||||||
const oldColorLight = customStyles.getAttribute('data-color-light');
|
|
||||||
|
|
||||||
customStyles.innerHTML = customStyles.innerHTML.split(oldColor).join(hexVal);
|
|
||||||
customStyles.innerHTML = customStyles.innerHTML.split(oldColorLight).join(rgbLightVal);
|
|
||||||
|
|
||||||
customStyles.setAttribute('data-color', hexVal);
|
|
||||||
customStyles.setAttribute('data-color-light', rgbLightVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Covert a hex color code to rgb components.
|
|
||||||
* @attribution https://stackoverflow.com/a/5624139
|
|
||||||
* @param {String} hex
|
|
||||||
* @returns {{r: Number, g: Number, b: Number}}
|
|
||||||
*/
|
|
||||||
hexToRgb(hex) {
|
|
||||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
||||||
return {
|
|
||||||
r: result ? parseInt(result[1], 16) : 0,
|
|
||||||
g: result ? parseInt(result[2], 16) : 0,
|
|
||||||
b: result ? parseInt(result[3], 16) : 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
82
resources/js/components/setting-app-color-scheme.js
Normal file
82
resources/js/components/setting-app-color-scheme.js
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
|
export class SettingAppColorScheme extends Component {
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
this.container = this.$el;
|
||||||
|
this.mode = this.$opts.mode;
|
||||||
|
this.lightContainer = this.$refs.lightContainer;
|
||||||
|
this.darkContainer = this.$refs.darkContainer;
|
||||||
|
|
||||||
|
this.container.addEventListener('tabs-change', event => {
|
||||||
|
const panel = event.detail.showing;
|
||||||
|
const newMode = (panel === 'color-scheme-panel-light') ? 'light' : 'dark';
|
||||||
|
this.handleModeChange(newMode);
|
||||||
|
});
|
||||||
|
|
||||||
|
const onInputChange = (event) => {
|
||||||
|
this.updateAppColorsFromInputs();
|
||||||
|
|
||||||
|
if (event.target.name.startsWith('setting-app-color')) {
|
||||||
|
this.updateLightForInput(event.target);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.container.addEventListener('change', onInputChange);
|
||||||
|
this.container.addEventListener('input', onInputChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleModeChange(newMode) {
|
||||||
|
this.mode = newMode;
|
||||||
|
const isDark = (newMode === 'dark');
|
||||||
|
|
||||||
|
document.documentElement.classList.toggle('dark-mode', isDark);
|
||||||
|
this.updateAppColorsFromInputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateAppColorsFromInputs() {
|
||||||
|
const inputContainer = this.mode === 'dark' ? this.darkContainer : this.lightContainer;
|
||||||
|
const inputs = inputContainer.querySelectorAll('input[type="color"]');
|
||||||
|
for (const input of inputs) {
|
||||||
|
const splitName = input.name.split('-');
|
||||||
|
const colorPos = splitName.indexOf('color');
|
||||||
|
let cssId = splitName.slice(1, colorPos).join('-');
|
||||||
|
if (cssId === 'app') {
|
||||||
|
cssId = 'primary';
|
||||||
|
}
|
||||||
|
|
||||||
|
const varName = '--color-' + cssId;
|
||||||
|
document.body.style.setProperty(varName, input.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the 'light' app color variant for the given input.
|
||||||
|
* @param {HTMLInputElement} input
|
||||||
|
*/
|
||||||
|
updateLightForInput(input) {
|
||||||
|
const lightName = input.name.replace('-color', '-color-light');
|
||||||
|
const hexVal = input.value;
|
||||||
|
const rgb = this.hexToRgb(hexVal);
|
||||||
|
const rgbLightVal = 'rgba('+ [rgb.r, rgb.g, rgb.b, '0.15'].join(',') +')';
|
||||||
|
|
||||||
|
console.log(input.name, lightName, hexVal, rgbLightVal)
|
||||||
|
const lightColorInput = this.container.querySelector(`input[name="${lightName}"][type="hidden"]`);
|
||||||
|
lightColorInput.value = rgbLightVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Covert a hex color code to rgb components.
|
||||||
|
* @attribution https://stackoverflow.com/a/5624139
|
||||||
|
* @param {String} hex
|
||||||
|
* @returns {{r: Number, g: Number, b: Number}}
|
||||||
|
*/
|
||||||
|
hexToRgb(hex) {
|
||||||
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||||
|
return {
|
||||||
|
r: result ? parseInt(result[1], 16) : 0,
|
||||||
|
g: result ? parseInt(result[2], 16) : 0,
|
||||||
|
b: result ? parseInt(result[3], 16) : 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,6 +15,6 @@ export class SettingColorPicker extends Component {
|
|||||||
|
|
||||||
setValue(value) {
|
setValue(value) {
|
||||||
this.colorInput.value = value;
|
this.colorInput.value = value;
|
||||||
this.colorInput.dispatchEvent(new Event('change'));
|
this.colorInput.dispatchEvent(new Event('change', {bubbles: true}));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -43,7 +43,7 @@ export class Tabs extends Component {
|
|||||||
tab.setAttribute('aria-selected', selected ? 'true' : 'false');
|
tab.setAttribute('aria-selected', selected ? 'true' : 'false');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$emit('change', {section: sectionId});
|
this.$emit('change', {showing: sectionId});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -34,7 +34,7 @@ export function scrollAndHighlightElement(element) {
|
|||||||
if (!element) return;
|
if (!element) return;
|
||||||
element.scrollIntoView({behavior: 'smooth'});
|
element.scrollIntoView({behavior: 'smooth'});
|
||||||
|
|
||||||
const color = document.getElementById('custom-styles').getAttribute('data-color-light');
|
const color = getComputedStyle(document.body).getPropertyValue('--color-primary-light');
|
||||||
const initColor = window.getComputedStyle(element).getPropertyValue('background-color');
|
const initColor = window.getComputedStyle(element).getPropertyValue('background-color');
|
||||||
element.style.backgroundColor = color;
|
element.style.backgroundColor = color;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -1,13 +1,7 @@
|
|||||||
<style id="custom-styles"
|
@php
|
||||||
data-color="{{ setting('app-color') }}"
|
$settingSuffix = setting()->getForCurrentUser('dark-mode-enabled') ? '-dark' : '';
|
||||||
data-color-dark="{{ setting('app-color-dark') }}"
|
@endphp
|
||||||
data-color-light="{{ setting('app-color-light') }}"
|
<style>
|
||||||
data-color-light-dark="{{ setting('app-color-light-dark') }}">
|
|
||||||
|
|
||||||
@php
|
|
||||||
$settingSuffix = setting()->getForCurrentUser('dark-mode-enabled') ? '-dark' : '';
|
|
||||||
@endphp
|
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--color-primary: {{ setting('app-color' . $settingSuffix) }};
|
--color-primary: {{ setting('app-color' . $settingSuffix) }};
|
||||||
--color-primary-light: {{ setting('app-color-light' . $settingSuffix) }};
|
--color-primary-light: {{ setting('app-color-light' . $settingSuffix) }};
|
||||||
|
@ -70,15 +70,17 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- App Color Scheme -->
|
<!-- App Color Scheme -->
|
||||||
<div class="pb-l">
|
@php
|
||||||
|
$darkMode = boolval(setting()->getForCurrentUser('dark-mode-enabled'));
|
||||||
|
@endphp
|
||||||
|
<div component="setting-app-color-scheme"
|
||||||
|
option:setting-app-color-scheme:mode="{{ $darkMode ? 'dark' : 'light' }}"
|
||||||
|
class="pb-l">
|
||||||
<div class="mb-l">
|
<div class="mb-l">
|
||||||
<label class="setting-list-label">{{ trans('settings.color_scheme') }}</label>
|
<label class="setting-list-label">{{ trans('settings.color_scheme') }}</label>
|
||||||
<p class="small">{{ trans('settings.color_scheme_desc') }}</p>
|
<p class="small">{{ trans('settings.color_scheme_desc') }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@php
|
|
||||||
$darkMode = boolval(setting()->getForCurrentUser('dark-mode-enabled'));
|
|
||||||
@endphp
|
|
||||||
<div component="tabs" class="tab-container">
|
<div component="tabs" class="tab-container">
|
||||||
<div role="tablist" class="controls-card">
|
<div role="tablist" class="controls-card">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
@ -94,6 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="sub-card">
|
<div class="sub-card">
|
||||||
<div id="color-scheme-panel-light"
|
<div id="color-scheme-panel-light"
|
||||||
|
refs="setting-app-color-scheme@lightContainer"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
aria-labelledby="color-scheme-tab-light"
|
aria-labelledby="color-scheme-tab-light"
|
||||||
@ -102,6 +105,7 @@
|
|||||||
@include('settings.parts.setting-color-scheme', ['mode' => 'light'])
|
@include('settings.parts.setting-color-scheme', ['mode' => 'light'])
|
||||||
</div>
|
</div>
|
||||||
<div id="color-scheme-panel-dark"
|
<div id="color-scheme-panel-dark"
|
||||||
|
refs="setting-app-color-scheme@darkContainer"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
aria-labelledby="color-scheme-tab-light"
|
aria-labelledby="color-scheme-tab-light"
|
||||||
|
@ -23,3 +23,7 @@
|
|||||||
@include('settings.parts.setting-color-picker', ['type' => 'page-draft', 'mode' => $mode])
|
@include('settings.parts.setting-color-picker', ['type' => 'page-draft', 'mode' => $mode])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<input type="hidden"
|
||||||
|
value="{{ setting('app-color-light' . ($mode === 'dark' ? '-dark' : '')) }}"
|
||||||
|
name="setting-app-color-light{{ $mode === 'dark' ? '-dark' : '' }}">
|
Loading…
Reference in New Issue
Block a user