proper fallbacks and contrast ratio for component style editor

This commit is contained in:
Henry Jameson 2024-10-22 17:06:22 +03:00
parent 7e4fe93c7f
commit 030a2127ee
7 changed files with 101 additions and 42 deletions

View file

@ -11,7 +11,7 @@
{{ label }}
</label>
<Checkbox
v-if="typeof fallback !== 'undefined' && showOptionalTickbox"
v-if="typeof fallback !== 'undefined' && showOptionalCheckbox && !hideOptionalCheckbox"
:model-value="present"
:disabled="disabled"
class="opt"
@ -112,10 +112,16 @@ export default {
default: false
},
// Show "optional" tickbox, for when value might become mandatory
showOptionalTickbox: {
showOptionalCheckbox: {
required: false,
type: Boolean,
default: true
},
// Force "optional" tickbox to hide
hideOptionalCheckbox: {
required: false,
type: Boolean,
default: false
}
},
emits: ['update:modelValue'],

View file

@ -3,39 +3,44 @@
v-if="contrast"
class="contrast-ratio"
>
<span
:title="hint"
<span v-if="showRatio">
{{ contrast.text }}
</span>
<Tooltip
:text="hint"
class="rating"
>
<span v-if="contrast.aaa">
<FAIcon icon="thumbs-up" />
<FAIcon icon="thumbs-up" :size="showRatio ? 'lg' : ''" />
</span>
<span v-if="!contrast.aaa && contrast.aa">
<FAIcon icon="adjust" />
<FAIcon icon="adjust" :size="showRatio ? 'lg' : ''" />
</span>
<span v-if="!contrast.aaa && !contrast.aa">
<FAIcon icon="exclamation-triangle" />
<FAIcon icon="exclamation-triangle" :size="showRatio ? 'lg' : ''" />
</span>
</span>
<span
</Tooltip>
<Tooltip
v-if="contrast && large"
:text="hint_18pt"
class="rating"
:title="hint_18pt"
>
<span v-if="contrast.laaa">
<FAIcon icon="thumbs-up" />
<FAIcon icon="thumbs-up" :size="showRatio ? 'large' : ''" />
</span>
<span v-if="!contrast.laaa && contrast.laa">
<FAIcon icon="adjust" />
<FAIcon icon="adjust" :size="showRatio ? 'lg' : ''" />
</span>
<span v-if="!contrast.laaa && !contrast.laa">
<FAIcon icon="exclamation-triangle" />
</span>
<FAIcon icon="exclamation-triangle" :size="showRatio ? 'lg' : ''" />
</span>
</Tooltip>
</span>
</template>
<script>
import Tooltip from 'src/components/tooltip/tooltip.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faAdjust,
@ -62,8 +67,16 @@ export default {
required: false,
type: Object,
default: () => ({})
},
showRatio: {
required: false,
type: Boolean,
default: false
}
},
components: {
Tooltip
},
computed: {
hint () {
const levelVal = this.contrast.aaa ? 'aaa' : (this.contrast.aa ? 'aa' : 'bad')
@ -87,8 +100,7 @@ export default {
.contrast-ratio {
display: flex;
justify-content: flex-end;
margin-top: -4px;
margin-bottom: 5px;
align-items: baseline;
.label {
margin-right: 1em;
@ -96,7 +108,6 @@ export default {
.rating {
display: inline-block;
text-align: center;
margin-left: 0.5em;
}
}

View file

@ -340,9 +340,7 @@ export default {
exports.editedBorderColor = getEditedElement('Border', 'textColor')
exports.isBorderColorPresent = isElementPresent('Border', 'textColor', '#909090')
// TODO this is VERY primitive right now, need to make it
// support variables, fallbacks etc.
exports.getContrast = (bg, text) => {
const getContrast = (bg, text) => {
try {
const bgRgb = hex2rgb(bg)
const textRgb = hex2rgb(text)
@ -464,6 +462,24 @@ export default {
return null
}
})
const applicablePreviewRules = computed(() => {
return previewRules.filter(rule => {
const filterable = rule.parent ? rule.parent : rule
const variantMatches = filterable.variant === selectedVariant.value
const stateMatches = filterable.state.filter(x => x !== 'normal').every(x => selectedState.has(x))
return variantMatches && stateMatches
})
})
const previewColors = computed(() => ({
text: applicablePreviewRules.value.find(r => r.component === 'Text').virtualDirectives['--text'],
link: applicablePreviewRules.value.find(r => r.component === 'Link').virtualDirectives['--link'],
border: applicablePreviewRules.value.find(r => r.component === 'Border').virtualDirectives['--border'],
icon: applicablePreviewRules.value.find(r => r.component === 'Icon').virtualDirectives['--icon'],
background: applicablePreviewRules.value.find(r => r.parent == null).dynamicVars.stacked
}))
exports.previewColors = previewColors
const editorFriendlyToOriginal = computed(() => {
const resultRules = []
@ -678,6 +694,14 @@ export default {
return null
}
exports.contrast = computed(() => {
console.log('APR', applicablePreviewRules.value)
return getContrast(
exports.computeColor(previewColors.value.background),
exports.computeColor(previewColors.value.text)
)
})
const overallPreviewRules = ref()
exports.overallPreviewRules = overallPreviewRules
exports.updateOverallPreview = () => {

View file

@ -166,27 +166,21 @@
>
<ColorInput
v-model="editedBackgroundColor"
:fallback="computeColor(editedBackgroundColor)"
:fallback="computeColor(editedBackgroundColor) ?? previewColors.background"
:disabled="!isBackgroundColorPresent"
:label="$t('settings.style.themes3.editor.background')"
:hide-optional-checkbox="true"
/>
<Tooltip :text="$t('settings.style.themes3.editor.include_in_rule')">
<Checkbox v-model="isBackgroundColorPresent" />
</Tooltip>
<OpacityInput
v-model="editedOpacity"
:disabled="!isOpacityPresent"
:label="$t('settings.style.themes3.editor.opacity')"
/>
<Tooltip :text="$t('settings.style.themes3.editor.include_in_rule')">
<Checkbox v-model="isOpacityPresent" />
</Tooltip>
<ColorInput
v-if="componentHas('Text')"
v-model="editedTextColor"
:fallback="computeColor(editedTextColor)"
:fallback="computeColor(editedTextColor) ?? previewColors.text"
:label="$t('settings.style.themes3.editor.text_color')"
:disabled="!isTextColorPresent"
:hide-optional-checkbox="true"
/>
<Tooltip
v-if="componentHas('Text')"
@ -194,7 +188,10 @@
>
<Checkbox v-model="isTextColorPresent" />
</Tooltip>
<div class="style-control suboption">
<div
v-if="componentHas('Text')"
class="style-control suboption"
>
<label
for="textAuto"
class="label"
@ -224,18 +221,27 @@
>
<Checkbox v-model="isTextAutoPresent" />
</Tooltip>
<div>
<ContrastRatio :contrast="getContrast(editedBackgroundColor, editedTextColor)" />
<div
class="style-control suboption"
v-if="componentHas('Text')"
>
<label class="label">
{{$t('settings.style.themes3.editor.contrast') }}
</label>
<ContrastRatio
:show-ratio="true"
:contrast="contrast"
/>
</div>
<div>
<!-- spacer for missing checkbox -->
<div v-if="componentHas('Text')">
</div>
<ColorInput
v-if="componentHas('Link')"
v-model="editedLinkColor"
:fallback="computeColor(editedLinkColor)"
:fallback="computeColor(editedLinkColor) ?? previewColors.link"
:label="$t('settings.style.themes3.editor.link_color')"
:disabled="!isLinkColorPresent"
:hide-optional-checkbox="true"
/>
<Tooltip
v-if="componentHas('Link')"
@ -246,9 +252,10 @@
<ColorInput
v-if="componentHas('Icon')"
v-model="editedIconColor"
:fallback="computeColor(editedIconColor)"
:fallback="computeColor(editedIconColor) ?? previewColors.icon"
:label="$t('settings.style.themes3.editor.icon_color')"
:disabled="!isIconColorPresent"
:hide-optional-checkbox="true"
/>
<Tooltip
v-if="componentHas('Icon')"
@ -259,9 +266,10 @@
<ColorInput
v-if="componentHas('Border')"
v-model="editedBorderColor"
:fallback="computeColor(editedBorderColor)"
:label="$t('settings.style.themes3.editor.Border_color')"
:fallback="computeColor(editedBorderColor) ?? previewColors.border"
:label="$t('settings.style.themes3.editor.border_color')"
:disabled="!isBorderColorPresent"
:hide-optional-checkbox="true"
/>
<Tooltip
v-if="componentHas('Border')"
@ -269,6 +277,14 @@
>
<Checkbox v-model="isBorderColorPresent" />
</Tooltip>
<OpacityInput
v-model="editedOpacity"
:disabled="!isOpacityPresent"
:label="$t('settings.style.themes3.editor.opacity')"
/>
<Tooltip :text="$t('settings.style.themes3.editor.include_in_rule')">
<Checkbox v-model="isOpacityPresent" />
</Tooltip>
</div>
<div
key="shadow"
@ -418,6 +434,7 @@
v-model="draftVirtualDirective"
:fallback="computeColor(draftVirtualDirective)"
:label="$t('settings.style.themes3.editor.variables.virtual_color')"
:hide-optional-checkbox="true"
/>
</div>
</div>

View file

@ -187,14 +187,14 @@
name="accentColor"
:fallback="previewTheme.colors?.link"
:label="$t('settings.accent')"
:show-optional-tickbox="typeof linkColorLocal !== 'undefined'"
:show-optional-checkbox="typeof linkColorLocal !== 'undefined'"
/>
<ColorInput
v-model="linkColorLocal"
name="linkColor"
:fallback="previewTheme.colors?.accent"
:label="$t('settings.links')"
:show-optional-tickbox="typeof accentColorLocal !== 'undefined'"
:show-optional-checkbox="typeof accentColorLocal !== 'undefined'"
/>
<ContrastRatio :contrast="previewContrast.bgLink" />
</div>

View file

@ -168,7 +168,7 @@
:disabled="disabled || !present"
:label="$t('settings.style.common.color')"
:fallback="getColorFallback"
:show-optional-tickbox="false"
:show-optional-checkbox="false"
name="shadow"
@update:modelValue="e => updateProperty('color', e)"
/>

View file

@ -793,6 +793,7 @@
"text_color": "Text color",
"icon_color": "Icon color",
"link_color": "Link color",
"contrast": "Text contrast",
"border_color": "Border color",
"include_in_rule": "Add to rule",
"test_string": "TEST",