Merge branch 'themes-updates' into 'develop'
Themes updates/fixes See merge request pleroma/pleroma-fe!1962
This commit is contained in:
commit
ace6068948
19 changed files with 244 additions and 91 deletions
1
changelog.d/color-schemes.add
Normal file
1
changelog.d/color-schemes.add
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Some new default color schemes
|
||||||
|
|
@ -10,14 +10,13 @@ export default {
|
||||||
},
|
},
|
||||||
validInnerComponents: [
|
validInnerComponents: [
|
||||||
'Text',
|
'Text',
|
||||||
|
'Link',
|
||||||
'Icon',
|
'Icon',
|
||||||
'Badge'
|
'Badge'
|
||||||
],
|
],
|
||||||
defaultRules: [
|
defaultRules: [
|
||||||
{
|
{
|
||||||
directives: {
|
directives: {
|
||||||
background: '#ffffff',
|
|
||||||
opacity: 0,
|
|
||||||
shadow: []
|
shadow: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,6 @@
|
||||||
color: var(--inputTopbarText, var(--inputText));
|
color: var(--inputTopbarText, var(--inputText));
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--link);
|
|
||||||
}
|
|
||||||
|
|
||||||
.inner-nav {
|
.inner-nav {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: var(--navbar-height);
|
grid-template-rows: var(--navbar-height);
|
||||||
|
|
@ -91,10 +87,6 @@
|
||||||
width: 2em;
|
width: 2em;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
.svg-inline--fa {
|
|
||||||
color: var(--link);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sitename {
|
.sitename {
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,10 @@ const EmojiReactions = {
|
||||||
'btn',
|
'btn',
|
||||||
'button-default',
|
'button-default',
|
||||||
'emoji-reaction-count-button',
|
'emoji-reaction-count-button',
|
||||||
{ '-picked-reaction': this.reactedWith(reaction.name) }
|
{
|
||||||
|
'-picked-reaction': this.reactedWith(reaction.name),
|
||||||
|
toggled: this.reactedWith(reaction.name)
|
||||||
|
}
|
||||||
],
|
],
|
||||||
'aria-label': this.$tc('status.reaction_count_label', reaction.count, { num: reaction.count })
|
'aria-label': this.$tc('status.reaction_count_label', reaction.count, { num: reaction.count })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
v-bind="!loggedIn ? { href: remoteInteractionLink } : {}"
|
v-bind="!loggedIn ? { href: remoteInteractionLink } : {}"
|
||||||
role="button"
|
role="button"
|
||||||
class="emoji-reaction btn button-default"
|
class="emoji-reaction btn button-default"
|
||||||
:class="{ '-picked-reaction': reactedWith(reaction.name) }"
|
:class="{ '-picked-reaction': reactedWith(reaction.name), toggled: reactedWith(reaction.name) }"
|
||||||
:title="reaction.url ? reaction.name : undefined"
|
:title="reaction.url ? reaction.name : undefined"
|
||||||
:aria-pressed="reactedWith(reaction.name)"
|
:aria-pressed="reactedWith(reaction.name)"
|
||||||
@click="emojiOnClick(reaction.name, $event)"
|
@click="emojiOnClick(reaction.name, $event)"
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@
|
||||||
v-if="apply"
|
v-if="apply"
|
||||||
class="btn button-default palette-apply-button"
|
class="btn button-default palette-apply-button"
|
||||||
@click="applyPalette"
|
@click="applyPalette"
|
||||||
|
:disabled="disabled"
|
||||||
|
:class="{ disabled }"
|
||||||
>
|
>
|
||||||
{{ $t('settings.style.themes3.palette.apply') }}
|
{{ $t('settings.style.themes3.palette.apply') }}
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -67,7 +69,7 @@ const paletteKeys = [
|
||||||
'wallpaper'
|
'wallpaper'
|
||||||
]
|
]
|
||||||
|
|
||||||
const props = defineProps(['modelValue', 'compact', 'apply'])
|
const props = defineProps(['modelValue', 'compact', 'apply', 'disabled'])
|
||||||
const emit = defineEmits(['update:modelValue', 'applyPalette'])
|
const emit = defineEmits(['update:modelValue', 'applyPalette'])
|
||||||
const getExportedObject = () => paletteKeys.reduce((acc, key) => {
|
const getExportedObject = () => paletteKeys.reduce((acc, key) => {
|
||||||
const value = props.modelValue[key]
|
const value = props.modelValue[key]
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,11 @@ export default {
|
||||||
selector: ':root',
|
selector: ':root',
|
||||||
notEditable: true,
|
notEditable: true,
|
||||||
validInnerComponents: [
|
validInnerComponents: [
|
||||||
|
// These are purely for --parent--text et such to work
|
||||||
|
'Text',
|
||||||
|
'Link',
|
||||||
|
'Border',
|
||||||
|
|
||||||
'Underlay',
|
'Underlay',
|
||||||
'Modals',
|
'Modals',
|
||||||
'Popover',
|
'Popover',
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ const AppearanceTab = {
|
||||||
bundledPalettes: [],
|
bundledPalettes: [],
|
||||||
compilationCache: {},
|
compilationCache: {},
|
||||||
fileImporter: newImporter({
|
fileImporter: newImporter({
|
||||||
accept: '.json, .piss',
|
accept: '.json, .iss',
|
||||||
validator: this.importValidator,
|
validator: this.importValidator,
|
||||||
onImport: this.onImport,
|
onImport: this.onImport,
|
||||||
parser: this.importParser,
|
parser: this.importParser,
|
||||||
|
|
@ -186,6 +186,9 @@ const AppearanceTab = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
switchInProgress () {
|
||||||
|
return this.$store.state.interface.themeChangeInProgress
|
||||||
|
},
|
||||||
paletteDataUsed () {
|
paletteDataUsed () {
|
||||||
return this.$store.state.interface.paletteDataUsed
|
return this.$store.state.interface.paletteDataUsed
|
||||||
},
|
},
|
||||||
|
|
@ -302,14 +305,14 @@ const AppearanceTab = {
|
||||||
importParser (file, filename) {
|
importParser (file, filename) {
|
||||||
if (filename.endsWith('.json')) {
|
if (filename.endsWith('.json')) {
|
||||||
return JSON.parse(file)
|
return JSON.parse(file)
|
||||||
} else if (filename.endsWith('.piss')) {
|
} else if (filename.endsWith('.iss')) {
|
||||||
return deserialize(file)
|
return deserialize(file)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onImport (parsed, filename) {
|
onImport (parsed, filename) {
|
||||||
if (filename.endsWith('.json')) {
|
if (filename.endsWith('.json')) {
|
||||||
this.$store.dispatch('setThemeCustom', parsed.source || parsed.theme)
|
this.$store.dispatch('setThemeCustom', parsed.source || parsed.theme)
|
||||||
} else if (filename.endsWith('.piss')) {
|
} else if (filename.endsWith('.iss')) {
|
||||||
this.$store.dispatch('setStyleCustom', parsed)
|
this.$store.dispatch('setStyleCustom', parsed)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -321,7 +324,7 @@ const AppearanceTab = {
|
||||||
if (filename.endsWith('.json')) {
|
if (filename.endsWith('.json')) {
|
||||||
const version = parsed._pleroma_theme_version
|
const version = parsed._pleroma_theme_version
|
||||||
return version >= 1 || version <= 2
|
return version >= 1 || version <= 2
|
||||||
} else if (filename.endsWith('.piss')) {
|
} else if (filename.endsWith('.iss')) {
|
||||||
if (!Array.isArray(parsed)) return false
|
if (!Array.isArray(parsed)) return false
|
||||||
if (parsed.length < 1) return false
|
if (parsed.length < 1) return false
|
||||||
if (parsed.find(x => x.component === '@meta') == null) return false
|
if (parsed.find(x => x.component === '@meta') == null) return false
|
||||||
|
|
|
||||||
|
|
@ -20,27 +20,48 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin: 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.palettes-container {
|
||||||
|
height: 15em;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
scrollbar-gutter: stable;
|
||||||
|
border-radius: var(--roundness);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
margin: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.palettes {
|
.palettes {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
grid-gap: 0.5em;
|
grid-gap: 0.5em;
|
||||||
|
padding: 0.5em;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
h4,
|
h4 {
|
||||||
.unsupported-theme-v2,
|
margin: 0;
|
||||||
.userPalette {
|
|
||||||
grid-column: 1 / span 2;
|
grid-column: 1 / span 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.palette-entry {
|
.palette-entry {
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0 0.5em;
|
padding: 0 0.5em;
|
||||||
|
height: max-content;
|
||||||
|
|
||||||
.palette-label label {
|
.palette-label {
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
label {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.palette-square {
|
.palette-square {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
|
@ -63,23 +84,26 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-view.-mobile & {
|
.modal-view.-mobile & {
|
||||||
|
.palettes {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
.palette-entry {
|
.palette-entry {
|
||||||
flex-wrap: wrap;
|
grid-column: 1;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.palette-label {
|
.palette-label {
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
width: 100%;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.palette-preview {
|
.palette-preview {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||||
grid-template-rows: 1em 1em;
|
grid-template-rows: 1em 1em;
|
||||||
margin-bottom: 0.5em;
|
margin: 0.5em 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-list {
|
.theme-list {
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,9 @@
|
||||||
<button
|
<button
|
||||||
class="button-default theme-preview"
|
class="button-default theme-preview"
|
||||||
data-theme-key="stock"
|
data-theme-key="stock"
|
||||||
:class="{ toggled: isStyleActive('stock') }"
|
|
||||||
@click="resetTheming"
|
@click="resetTheming"
|
||||||
|
:class="{ toggled: isStyleActive('stock'), disabled: switchInProgress }"
|
||||||
|
:disabled="switchInProgress"
|
||||||
>
|
>
|
||||||
<!-- eslint-disable vue/no-v-text-v-html-on-component -->
|
<!-- eslint-disable vue/no-v-text-v-html-on-component -->
|
||||||
<!-- eslint-disable vue/no-v-html -->
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
|
|
@ -56,8 +57,9 @@
|
||||||
:key="style.key"
|
:key="style.key"
|
||||||
:data-theme-key="style.key"
|
:data-theme-key="style.key"
|
||||||
class="button-default theme-preview"
|
class="button-default theme-preview"
|
||||||
:class="{ toggled: isStyleActive(style.key) }"
|
:class="{ toggled: isStyleActive(style.key), disabled: switchInProgress }"
|
||||||
@click="style.version === 'v2' ? setTheme(style.key) : setStyle(style.key)"
|
@click="style.version === 'v2' ? setTheme(style.key) : setStyle(style.key)"
|
||||||
|
:disabled="switchInProgress"
|
||||||
>
|
>
|
||||||
<!-- eslint-disable vue/no-v-text-v-html-on-component -->
|
<!-- eslint-disable vue/no-v-text-v-html-on-component -->
|
||||||
<!-- eslint-disable vue/no-v-html -->
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
|
|
@ -80,6 +82,8 @@
|
||||||
<button
|
<button
|
||||||
class="btn button-default"
|
class="btn button-default"
|
||||||
@click="importFile"
|
@click="importFile"
|
||||||
|
:class="{ disabled: switchInProgress }"
|
||||||
|
:disabled="switchInProgress"
|
||||||
>
|
>
|
||||||
<FAIcon icon="folder-open" />
|
<FAIcon icon="folder-open" />
|
||||||
{{ $t('settings.style.themes3.editor.load_style') }}
|
{{ $t('settings.style.themes3.editor.load_style') }}
|
||||||
|
|
@ -87,38 +91,20 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.style.themes3.palette.label') }}</h2>
|
<h2>{{ $t('settings.style.themes3.palette.label') }}</h2>
|
||||||
<div class="palettes">
|
<div
|
||||||
<template v-if="customThemeVersion === 'v3'">
|
v-if="customThemeVersion === 'v3'"
|
||||||
<h4>{{ $t('settings.style.themes3.palette.bundled') }}</h4>
|
class="palettes-container"
|
||||||
<button
|
|
||||||
v-for="p in bundledPalettes"
|
|
||||||
:key="p.name"
|
|
||||||
class="btn button-default palette-entry"
|
|
||||||
:class="{ toggled: isPaletteActive(p.key) }"
|
|
||||||
@click="() => setPalette(p.key, p)"
|
|
||||||
>
|
>
|
||||||
<div class="palette-label">
|
|
||||||
<label>
|
|
||||||
{{ p.name }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="palette-preview">
|
|
||||||
<span
|
|
||||||
v-for="c in palettesKeys"
|
|
||||||
:key="c"
|
|
||||||
class="palette-square"
|
|
||||||
:style="{ backgroundColor: p[c], border: '1px solid ' + (p[c] ?? 'var(--text)') }"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<h4 v-if="stylePalettes?.length > 0">
|
<h4 v-if="stylePalettes?.length > 0">
|
||||||
{{ $t('settings.style.themes3.palette.style') }}
|
{{ $t('settings.style.themes3.palette.style') }}
|
||||||
</h4>
|
</h4>
|
||||||
|
<div class="palettes">
|
||||||
<button
|
<button
|
||||||
v-for="p in stylePalettes || []"
|
v-for="p in stylePalettes || []"
|
||||||
:key="p.name"
|
:key="p.name"
|
||||||
class="btn button-default palette-entry"
|
class="btn button-default palette-entry"
|
||||||
:class="{ toggled: isPaletteActive(p.key) }"
|
:class="{ toggled: isPaletteActive(p.key), disabled: switchInProgress }"
|
||||||
|
:disabled="switchInProgress"
|
||||||
@click="() => setPalette(p.key, p)"
|
@click="() => setPalette(p.key, p)"
|
||||||
>
|
>
|
||||||
<div class="palette-label">
|
<div class="palette-label">
|
||||||
|
|
@ -135,6 +121,33 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
<h4>{{ $t('settings.style.themes3.palette.bundled') }}</h4>
|
||||||
|
<button
|
||||||
|
v-for="p in bundledPalettes"
|
||||||
|
:key="p.name"
|
||||||
|
class="btn button-default palette-entry"
|
||||||
|
:class="{ toggled: isPaletteActive(p.key), disabled: switchInProgress }"
|
||||||
|
:disabled="switchInProgress"
|
||||||
|
@click="() => setPalette(p.key, p)"
|
||||||
|
>
|
||||||
|
<div class="palette-label">
|
||||||
|
<label>
|
||||||
|
{{ p.name }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="palette-preview">
|
||||||
|
<span
|
||||||
|
v-for="c in palettesKeys"
|
||||||
|
:key="c"
|
||||||
|
class="palette-square"
|
||||||
|
:style="{ backgroundColor: p[c], border: '1px solid ' + (p[c] ?? 'var(--text)') }"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<template v-if="customThemeVersion === 'v3'">
|
||||||
<h4 v-if="expertLevel > 0">
|
<h4 v-if="expertLevel > 0">
|
||||||
{{ $t('settings.style.themes3.palette.user') }}
|
{{ $t('settings.style.themes3.palette.user') }}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
@ -145,6 +158,7 @@
|
||||||
:compact="true"
|
:compact="true"
|
||||||
:apply="true"
|
:apply="true"
|
||||||
@applyPalette="data => setPaletteCustom(data)"
|
@applyPalette="data => setPaletteCustom(data)"
|
||||||
|
:disabled="switchInProgress"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="customThemeVersion === 'v2'">
|
<template v-else-if="customThemeVersion === 'v2'">
|
||||||
|
|
|
||||||
|
|
@ -604,7 +604,7 @@ export default {
|
||||||
const styleExporter = newExporter({
|
const styleExporter = newExporter({
|
||||||
filename: () => exports.name.value ?? 'pleroma_theme',
|
filename: () => exports.name.value ?? 'pleroma_theme',
|
||||||
mime: 'text/plain',
|
mime: 'text/plain',
|
||||||
extension: 'piss',
|
extension: 'iss',
|
||||||
getExportedObject: () => exportStyleData.value
|
getExportedObject: () => exportStyleData.value
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -636,7 +636,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
const styleImporter = newImporter({
|
const styleImporter = newImporter({
|
||||||
accept: '.piss',
|
accept: '.iss',
|
||||||
parser (string) { return deserialize(string) },
|
parser (string) { return deserialize(string) },
|
||||||
onImportFailure (result) {
|
onImportFailure (result) {
|
||||||
console.error('Failure importing style:', result)
|
console.error('Failure importing style:', result)
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,27 @@ export default {
|
||||||
alpha: 0.6
|
alpha: 0.6
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Link',
|
||||||
|
parent: {
|
||||||
|
component: 'TopBar'
|
||||||
|
},
|
||||||
|
directives: {
|
||||||
|
textColor: '--text'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Icon',
|
||||||
|
parent: {
|
||||||
|
component: 'ButtonUnstyled',
|
||||||
|
parent: {
|
||||||
|
component: 'TopBar'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
directives: {
|
||||||
|
textColor: '--parent--text'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ const toValue = (x) => JSON.parse(JSON.stringify(x === undefined ? 'null' : x))
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
localFonts: null,
|
localFonts: null,
|
||||||
themeApplied: false,
|
themeApplied: false,
|
||||||
|
themeChangeInProgress: false,
|
||||||
themeVersion: 'v3',
|
themeVersion: 'v3',
|
||||||
styleNameUsed: null,
|
styleNameUsed: null,
|
||||||
styleDataUsed: null,
|
styleDataUsed: null,
|
||||||
|
|
@ -556,11 +557,13 @@ const interfaceMod = {
|
||||||
themeDebug,
|
themeDebug,
|
||||||
theme3hacks
|
theme3hacks
|
||||||
} = rootState.config
|
} = rootState.config
|
||||||
|
state.themeChangeInProgress = true
|
||||||
// If we're not not forced to recompile try using
|
// If we're not not forced to recompile try using
|
||||||
// cache (tryLoadCache return true if load successful)
|
// cache (tryLoadCache return true if load successful)
|
||||||
|
|
||||||
const forceRecompile = forceThemeRecompilation || recompile
|
const forceRecompile = forceThemeRecompilation || recompile
|
||||||
if (!forceRecompile && !themeDebug && await tryLoadCache()) {
|
if (!forceRecompile && !themeDebug && await tryLoadCache()) {
|
||||||
|
state.themeChangeInProgress = false
|
||||||
return commit('setThemeApplied')
|
return commit('setThemeApplied')
|
||||||
}
|
}
|
||||||
window.splashUpdate('splash.theme')
|
window.splashUpdate('splash.theme')
|
||||||
|
|
@ -669,7 +672,9 @@ const interfaceMod = {
|
||||||
return applyTheme(
|
return applyTheme(
|
||||||
rulesetArray.flat(),
|
rulesetArray.flat(),
|
||||||
() => commit('setThemeApplied'),
|
() => commit('setThemeApplied'),
|
||||||
() => {},
|
() => {
|
||||||
|
state.themeChangeInProgress = false
|
||||||
|
},
|
||||||
themeDebug
|
themeDebug
|
||||||
)
|
)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { invertLightness, contrastRatio } from 'chromatism'
|
import { invertLightness, contrastRatio, convert } from 'chromatism'
|
||||||
|
|
||||||
// useful for visualizing color when debugging
|
// useful for visualizing color when debugging
|
||||||
export const consoleColor = (color) => console.log('%c##########', 'background: ' + color + '; color: ' + color)
|
export const consoleColor = (color) => console.log('%c##########', 'background: ' + color + '; color: ' + color)
|
||||||
|
|
@ -215,19 +215,37 @@ export const rgba2css = function (rgba) {
|
||||||
* @param {Boolean} preserve - try to preserve intended text color's hue/saturation (i.e. no BW)
|
* @param {Boolean} preserve - try to preserve intended text color's hue/saturation (i.e. no BW)
|
||||||
*/
|
*/
|
||||||
export const getTextColor = function (bg, text, preserve) {
|
export const getTextColor = function (bg, text, preserve) {
|
||||||
const contrast = getContrastRatio(bg, text)
|
const originalContrast = getContrastRatio(bg, text)
|
||||||
|
if (!preserve) {
|
||||||
if (contrast < 4.5) {
|
if (originalContrast < 4.5) {
|
||||||
const base = typeof text.a !== 'undefined' ? { a: text.a } : {}
|
|
||||||
const result = Object.assign(base, invertLightness(text).rgb)
|
|
||||||
if (!preserve && getContrastRatio(bg, result) < 4.5) {
|
|
||||||
// B&W
|
// B&W
|
||||||
return contrastRatio(bg, text).rgb
|
return contrastRatio(bg, text).rgb
|
||||||
}
|
}
|
||||||
// Inverted color
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
return text
|
|
||||||
|
const originalColor = convert(text).hex
|
||||||
|
const invertedColor = invertLightness(originalColor).hex
|
||||||
|
const invertedContrast = getContrastRatio(bg, convert(invertedColor).rgb)
|
||||||
|
let workColor
|
||||||
|
|
||||||
|
if (invertedContrast > originalContrast) {
|
||||||
|
workColor = invertedColor
|
||||||
|
} else {
|
||||||
|
workColor = originalColor
|
||||||
|
}
|
||||||
|
|
||||||
|
let contrast = getContrastRatio(bg, text)
|
||||||
|
const result = convert(rgb2hex(workColor)).hsl
|
||||||
|
const delta = result.l > 50 ? 1 : -1
|
||||||
|
const multiplier = 10
|
||||||
|
while (contrast < 4.5 && result.l > 20 && result.l < 80) {
|
||||||
|
result.l += delta * multiplier
|
||||||
|
result.l = Math.min(100, Math.max(0, result.l))
|
||||||
|
contrast = getContrastRatio(bg, convert(result).rgb)
|
||||||
|
}
|
||||||
|
|
||||||
|
const base = typeof text.a !== 'undefined' ? { a: text.a } : {}
|
||||||
|
return Object.assign(convert(result).rgb, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,7 @@ export const init = ({
|
||||||
const lowerLevelVirtualDirectivesRaw = computed[lowerLevelSelector]?.virtualDirectivesRaw
|
const lowerLevelVirtualDirectivesRaw = computed[lowerLevelSelector]?.virtualDirectivesRaw
|
||||||
|
|
||||||
const dynamicVars = computed[selector] || {
|
const dynamicVars = computed[selector] || {
|
||||||
|
lowerLevelSelector,
|
||||||
lowerLevelBackground,
|
lowerLevelBackground,
|
||||||
lowerLevelVirtualDirectives,
|
lowerLevelVirtualDirectives,
|
||||||
lowerLevelVirtualDirectivesRaw
|
lowerLevelVirtualDirectivesRaw
|
||||||
|
|
@ -284,6 +285,11 @@ export const init = ({
|
||||||
computed[selector].computedRule = computedRule
|
computed[selector].computedRule = computedRule
|
||||||
computed[selector].dynamicVars = dynamicVars
|
computed[selector].dynamicVars = dynamicVars
|
||||||
|
|
||||||
|
// avoid putting more stuff into actual CSS
|
||||||
|
computed[selector].virtualDirectives = {}
|
||||||
|
// but still be able to access it i.e. from --parent
|
||||||
|
computed[selector].virtualDirectivesRaw = computed[lowerLevelSelector]?.virtualDirectivesRaw || {}
|
||||||
|
|
||||||
if (virtualComponents.has(combination.component)) {
|
if (virtualComponents.has(combination.component)) {
|
||||||
const virtualName = [
|
const virtualName = [
|
||||||
'--',
|
'--',
|
||||||
|
|
@ -330,8 +336,8 @@ export const init = ({
|
||||||
intendedTextColor,
|
intendedTextColor,
|
||||||
newTextRule.directives.textAuto === 'preserve'
|
newTextRule.directives.textAuto === 'preserve'
|
||||||
)
|
)
|
||||||
const virtualDirectives = computed[lowerLevelSelector].virtualDirectives || {}
|
const virtualDirectives = { ...(computed[lowerLevelSelector].virtualDirectives || {}) }
|
||||||
const virtualDirectivesRaw = computed[lowerLevelSelector].virtualDirectivesRaw || {}
|
const virtualDirectivesRaw = { ...(computed[lowerLevelSelector].virtualDirectivesRaw || {}) }
|
||||||
|
|
||||||
// Storing color data in lower layer to use as custom css properties
|
// Storing color data in lower layer to use as custom css properties
|
||||||
virtualDirectives[virtualName] = getTextColorAlpha(newTextRule.directives, textColor, dynamicVars)
|
virtualDirectives[virtualName] = getTextColorAlpha(newTextRule.directives, textColor, dynamicVars)
|
||||||
|
|
@ -345,12 +351,8 @@ export const init = ({
|
||||||
selector: cssSelector.split(/ /g).slice(0, -1).join(' '),
|
selector: cssSelector.split(/ /g).slice(0, -1).join(' '),
|
||||||
...combination,
|
...combination,
|
||||||
directives: {},
|
directives: {},
|
||||||
virtualDirectives: {
|
virtualDirectives,
|
||||||
[virtualName]: getTextColorAlpha(newTextRule.directives, textColor, dynamicVars)
|
virtualDirectivesRaw
|
||||||
},
|
|
||||||
virtualDirectivesRaw: {
|
|
||||||
[virtualName]: textColor
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
computed[selector] = computed[selector] || {}
|
computed[selector] = computed[selector] || {}
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,53 @@
|
||||||
"cRed": "#cc6666",
|
"cRed": "#cc6666",
|
||||||
"cBlue": "#8abeb7",
|
"cBlue": "#8abeb7",
|
||||||
"cGreen": "#b5bd68",
|
"cGreen": "#b5bd68",
|
||||||
"cOrange": "#de935f",
|
"cOrange": "#de935f"
|
||||||
"_cYellow": "#f0c674",
|
},
|
||||||
"_cPurple": "#b294bb"
|
"dracula": {
|
||||||
|
"name": "Dracula",
|
||||||
|
"bg": "#282A36",
|
||||||
|
"fg": "#44475A",
|
||||||
|
"link": "#BC92F9",
|
||||||
|
"text": "#f8f8f2",
|
||||||
|
"cRed": "#FF5555",
|
||||||
|
"cBlue": "#8BE9FD",
|
||||||
|
"cGreen": "#50FA7B",
|
||||||
|
"cOrange": "#FFB86C"
|
||||||
},
|
},
|
||||||
"ir-black": [ "Ir Black", "#000000", "#242422", "#b5b3aa", "#ff6c60", "#FF6C60", "#A8FF60", "#96CBFE", "#FFFFB6" ],
|
"ir-black": [ "Ir Black", "#000000", "#242422", "#b5b3aa", "#ff6c60", "#FF6C60", "#A8FF60", "#96CBFE", "#FFFFB6" ],
|
||||||
"monokai": [ "Monokai", "#272822", "#383830", "#f8f8f2", "#f92672", "#F92672", "#a6e22e", "#66d9ef", "#f4bf75" ]
|
"monokai": [ "Monokai", "#272822", "#383830", "#f8f8f2", "#f92672", "#F92672", "#a6e22e", "#66d9ef", "#f4bf75" ],
|
||||||
|
"purple-stream": {
|
||||||
|
"name": "Purple stream",
|
||||||
|
"bg": "#17171A",
|
||||||
|
"fg": "#450F92",
|
||||||
|
"link": "#8769B4",
|
||||||
|
"text": "#C0C0C5",
|
||||||
|
"cRed": "#EB0300",
|
||||||
|
"cBlue": "#4656FF",
|
||||||
|
"cGreen": "#B0E020",
|
||||||
|
"cOrange": "#FF9046"
|
||||||
|
},
|
||||||
|
"feud": {
|
||||||
|
"name": "Feud",
|
||||||
|
"bg": "#323337",
|
||||||
|
"fg": "#1D1E21",
|
||||||
|
"link": "#18A0E3",
|
||||||
|
"accent": "#6671E2",
|
||||||
|
"text": "#DBDDE0",
|
||||||
|
"cRed": "#E05053",
|
||||||
|
"cBlue": "#6671E2",
|
||||||
|
"cGreen": "#3A8D5D",
|
||||||
|
"cOrange": "#DCAA45"
|
||||||
|
},
|
||||||
|
"constabulary": {
|
||||||
|
"name": "Constabulary",
|
||||||
|
"bg": "#FFFFFF",
|
||||||
|
"fg": "#3B5897",
|
||||||
|
"link": "#28487C",
|
||||||
|
"text": "#333333",
|
||||||
|
"cRed": "#FA3C4C",
|
||||||
|
"cBlue": "#0083FF",
|
||||||
|
"cGreen": "#44BDC6",
|
||||||
|
"cOrange": "#FFC200"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,26 @@
|
||||||
link: #1CA4F3;
|
link: #1CA4F3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@palette.Panda {
|
||||||
|
bg: #EFF0F2;
|
||||||
|
fg: #292C32;
|
||||||
|
text: #1B1F22;
|
||||||
|
link: #1CA4F3;
|
||||||
|
accent: #1CA4F3;
|
||||||
|
cRed: #f41a51;
|
||||||
|
cBlue: #1CA4F3;
|
||||||
|
cGreen: #1af46e;
|
||||||
|
cOrange: #f4af1a;
|
||||||
|
}
|
||||||
|
|
||||||
Root {
|
Root {
|
||||||
--badgeNotification: color | --cRed;
|
--badgeNotification: color | --cRed;
|
||||||
--buttonDefaultHoverGlow: shadow | inset 0 0 0 1 --accent / 1;
|
--buttonDefaultHoverGlow: shadow | inset 0 0 0 1 --accent / 1;
|
||||||
--buttonDefaultFocusGlow: shadow | inset 0 0 0 1 --accent / 1;
|
--buttonDefaultFocusGlow: shadow | inset 0 0 0 1 --accent / 1;
|
||||||
--buttonDefaultShadow: shadow | inset 0 0 0 1 --text / 0.35, 0 5 5 -5 #000000 / 0.35;
|
--buttonDefaultShadow: shadow | inset 0 0 0 1 --parent--text / 0.35, 0 5 5 -5 #000000 / 0.35;
|
||||||
--buttonDefaultBevel: shadow | inset 0 14 14 -14 #FFFFFF / 0.1;
|
--buttonDefaultBevel: shadow | inset 0 14 14 -14 #FFFFFF / 0.1;
|
||||||
--buttonPressedBevel: shadow | inset 0 -20 20 -20 #000000 / 0.05;
|
--buttonPressedBevel: shadow | inset 0 -20 20 -20 #000000 / 0.05;
|
||||||
--defaultInputBevel: shadow | inset 0 0 0 1 --text / 0.35;
|
--defaultInputBevel: shadow | inset 0 0 0 1 --parent--text / 0.35;
|
||||||
--defaultInputHoverGlow: shadow | 0 0 0 1 --accent / 1;
|
--defaultInputHoverGlow: shadow | 0 0 0 1 --accent / 1;
|
||||||
--defaultInputFocusGlow: shadow | 0 0 0 1 --link / 1;
|
--defaultInputFocusGlow: shadow | 0 0 0 1 --link / 1;
|
||||||
}
|
}
|
||||||
|
|
@ -67,8 +79,13 @@ Button:toggled:hover {
|
||||||
background: $blend(--bg 0.3 --accent)
|
background: $blend(--bg 0.3 --accent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
background: --parent;
|
||||||
|
}
|
||||||
|
|
||||||
Input {
|
Input {
|
||||||
shadow: --defaultInputBevel
|
shadow: --defaultInputBevel;
|
||||||
|
background: --parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelHeader {
|
PanelHeader {
|
||||||
|
|
@ -78,3 +95,7 @@ PanelHeader {
|
||||||
Tab:hover {
|
Tab:hover {
|
||||||
shadow: --buttonDefaultHoverGlow, --buttonDefaultBevel, --buttonDefaultShadow
|
shadow: --buttonDefaultHoverGlow, --buttonDefaultBevel, --buttonDefaultShadow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tab {
|
||||||
|
background: --parent;
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"RedmondDX": "/static/styles/Redmond DX.piss",
|
"RedmondDX": "/static/styles/Redmond DX.iss",
|
||||||
"BreezyDX": "/static/styles/Breezy DX.piss"
|
"BreezyDX": "/static/styles/Breezy DX.iss"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue