Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 4 additions & 42 deletions src/components/Envelope.vue
Original file line number Diff line number Diff line change
Expand Up @@ -386,19 +386,8 @@
</template>
</template>
<template #tags>
<div
v-for="tag in tags"
:key="tag.id"
class="tag-group">
<div
class="tag-group__bg"
:style="{ 'background-color': tag.color }" />
<span
class="tag-group__label"
:style="{ color: tag.color }">
{{ translateTagDisplayName(tag) }}
</span>
</div>
<Tag v-for="tag in tags" :tag="tag" />

Check failure on line 389 in src/components/Envelope.vue

View workflow job for this annotation

GitHub Actions / NPM lint

Custom elements in iteration require 'v-bind:key' directives

<MoveModal
v-if="showMoveModal"
:account="account"
Expand Down Expand Up @@ -470,6 +459,7 @@
import JunkIcon from './icons/JunkIcon.vue'
import MoveModal from './MoveModal.vue'
import Icon from './quickActions/Icon.vue'
import Tag from './Tag.vue'
import TagModal from './TagModal.vue'
import TaskModal from './TaskModal.vue'
import { isPgpText } from '../crypto/pgp.js'
Expand All @@ -483,7 +473,6 @@
import useMainStore from '../store/mainStore.js'
import { mailboxHasRights } from '../util/acl.js'
import { messageDateTime, shortRelativeDatetime } from '../util/shortRelativeDatetime.js'
import { translateTagDisplayName } from '../util/tag.js'
import { hiddenTags } from './tags.js'

export default {
Expand Down Expand Up @@ -530,6 +519,7 @@
CogIcon,
IconEmailFast,
Icon,
Tag,
},

directives: {
Expand Down Expand Up @@ -877,7 +867,6 @@
},

methods: {
translateTagDisplayName,
setSelected(value) {
if (this.selected !== value) {
this.$emit('update:selected', value)
Expand Down Expand Up @@ -1452,33 +1441,6 @@
}
}

.tag-group__label {
margin: 0 7px;
z-index: 2;
font-size: calc(var(--default-font-size) * 0.8);
font-weight: bold;
padding-inline: 2px;
white-space: nowrap;
}

.tag-group__bg {
position: absolute;
width: 100%;
height: 100%;
top: 0;
inset-inline-start: 0;
opacity: 15%;
}

.tag-group {
display: inline-block;
border-radius: var(--border-radius-pill);
position: relative;
margin-inline-end: 1px;
overflow: hidden;
text-overflow: ellipsis;
}

.list-item__wrapper:deep() {
list-style: none;
}
Expand Down
39 changes: 3 additions & 36 deletions src/components/SearchMessages.vue
Original file line number Diff line number Diff line change
Expand Up @@ -209,18 +209,7 @@
:auto-limit="false">
<template #selected-option="option">
<div class="tag-group__search">
<div
class="tag-group__bg"
:style="
'background-color:'
+ (option.color !== '#fff'
? option.color
: '#333')" />
<div
class="tag-group__label"
:style="'color:' + option.color">
{{ option.displayName }}
</div>
<Tag :tag="option" />
</div>
</template>
<template #option="option">
Expand Down Expand Up @@ -336,6 +325,7 @@
import { findRecipient } from '../service/AutocompleteService.js'
import useMainStore from '../store/mainStore.js'
import { hiddenTags } from './tags.js'
import Tag from './Tag.vue'

Check failure on line 328 in src/components/SearchMessages.vue

View workflow job for this annotation

GitHub Actions / NPM lint

Expected "./Tag.vue" (internalVue) to come before "./tags.js" (unknown)

const debouncedSearch = debouncePromise(findRecipient, 500)

Expand All @@ -349,6 +339,7 @@
NcCheckboxRadioSwitch,
FilterVariantIcon,
Close,
Tag,
},

props: {
Expand Down Expand Up @@ -682,30 +673,6 @@
margin: 0 !important;
}

.tag-group__search {
box-sizing: border-box;
position: relative;
margin: 3px 3px;
padding: 0 6px;
}

.tag-group__bg {
position: absolute;
inset-inline: 0;
bottom: 0;
top: 0;
opacity: 0.4;
border-radius: 14px;
z-index: 1;
}

.tag-group__label {
font-weight: bold;
font-size: 12px;
position: relative;
z-index: 2;
}

.search-modal {
.modal-inner--content {
padding: 16px 0 36px 0;
Expand Down
106 changes: 106 additions & 0 deletions src/components/Tag.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<!--
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->

<template>
<div class="tag-group" :class="{ 'tag-group--dark': isDark, 'tag-group--bright': !isDark }">
<div
class="tag-group__bg"
:style="{ 'background-color': tag.color }" />
<span
class="tag-group__label">
{{ translateTagDisplayName(tag) }}
</span>
</div>
</template>

<script setup>
import { defineProps } from 'vue'
import { translateTagDisplayName } from '../util/tag.js'

const props = defineProps({
tag: {
type: Object,
required: true,
},
})

// Source - https://stackoverflow.com/a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Source - https://stackoverflow.com/a
// Source - https://stackoverflow.com/a/9733420

// Posted by kirilloid, modified by community. See post 'Timeline' for change history
// Retrieved 2025-11-19, License - CC BY-SA 4.0

const RED = 0.2126;

Check failure on line 33 in src/components/Tag.vue

View workflow job for this annotation

GitHub Actions / NPM lint

Extra semicolon
const GREEN = 0.7152;

Check failure on line 34 in src/components/Tag.vue

View workflow job for this annotation

GitHub Actions / NPM lint

Extra semicolon
const BLUE = 0.0722;

Check failure on line 35 in src/components/Tag.vue

View workflow job for this annotation

GitHub Actions / NPM lint

Extra semicolon

const GAMMA = 2.4;

Check failure on line 37 in src/components/Tag.vue

View workflow job for this annotation

GitHub Actions / NPM lint

Extra semicolon

function luminance(r, g, b) {
const a = [r, g, b].map(function (v) {

Check failure on line 40 in src/components/Tag.vue

View workflow job for this annotation

GitHub Actions / NPM lint

Unexpected space before function parentheses
v /= 255
return v <= 0.03928
? v / 12.92
: Math.pow((v + 0.055) / 1.055, GAMMA)
})
return a[0] * RED + a[1] * GREEN + a[2] * BLUE
}

function contrast(rgb1, rgb2) {
const lum1 = luminance(...rgb1)
const lum2 = luminance(...rgb2)
const brightest = Math.max(lum1, lum2)
const darkest = Math.min(lum1, lum2)
return (brightest + 0.05) / (darkest + 0.05)
}

const match = /^\#([\da-fA-F]{1,2})([\da-fA-F]{1,2})([\da-fA-F]{1,2})$/.exec(props.tag.color);

Check failure on line 57 in src/components/Tag.vue

View workflow job for this annotation

GitHub Actions / NPM lint

Extra semicolon

Check failure on line 57 in src/components/Tag.vue

View workflow job for this annotation

GitHub Actions / NPM lint

Unnecessary escape character: \#
if (!match) {
throw new Error('Could not parse tag colour: ' + props.tag.color)
}
const rgbColor = {
r: Number(match[1]),
g: Number(match[2]),
b: Number(match[3]),
}

const contrastWithWhite = contrast([255, 255, 255], [rgbColor.r, rgbColor.g, rgbColor.b]);

Check failure on line 67 in src/components/Tag.vue

View workflow job for this annotation

GitHub Actions / NPM lint

Extra semicolon
const contrastWithBlack = contrast([0, 0, 0], [rgbColor.r, rgbColor.g, rgbColor.b]);

const isDark = contrastWithBlack < contrastWithWhite
</script>

<style scoped lang="scss">
.tag-group {
display: inline-block;
border-radius: var(--border-radius-pill);
position: relative;
margin-inline-end: 1px;
overflow: hidden;
text-overflow: ellipsis;

&__label {
margin: 0 7px;
z-index: 2;
font-size: calc(var(--default-font-size) * 0.8);
font-weight: bold;
padding-inline: 2px;
white-space: nowrap;
filter: brightness(90%);
}
&--dark &__label {
color: white;
}
&--bright &__label {
color: black;
}

&__bg {
position: absolute;
width: 100%;
height: 100%;
top: 0;
inset-inline-start: 0;
}
}
</style>
Loading
Loading