diff --git a/app/javascript/dashboard/components/ui/Label.vue b/app/javascript/dashboard/components/ui/Label.vue index 83e55b040..eaacebe55 100644 --- a/app/javascript/dashboard/components/ui/Label.vue +++ b/app/javascript/dashboard/components/ui/Label.vue @@ -48,6 +48,10 @@ export default { type: String, default: '', }, + color: { + type: String, + default: '', + }, colorScheme: { type: String, default: '', @@ -55,7 +59,7 @@ export default { }, computed: { textColor() { - return getContrastingTextColor(this.bgColor); + return this.color || getContrastingTextColor(this.bgColor); }, labelClass() { return `label ${this.colorScheme} ${this.small ? 'small' : ''}`; @@ -97,6 +101,9 @@ export default { &.small { font-size: var(--font-size-micro); + padding: var(--space-micro) var(--space-smaller); + line-height: 1.2; + letter-spacing: 0.15px; } .label--icon { diff --git a/app/javascript/dashboard/routes/dashboard/conversation/labels/LabelBox.vue b/app/javascript/dashboard/routes/dashboard/conversation/labels/LabelBox.vue index bf0bd3692..795917180 100644 --- a/app/javascript/dashboard/routes/dashboard/conversation/labels/LabelBox.vue +++ b/app/javascript/dashboard/routes/dashboard/conversation/labels/LabelBox.vue @@ -16,7 +16,8 @@ :title="label.title" :description="label.description" :show-close="true" - :bg-color="label.color" + :bg-color="getBleachBgOfHexColor(label.color)" + :color="getShadeOfHexColor(label.color)" @click="removeLabelFromConversation" /> @@ -47,6 +48,10 @@ import LabelDropdown from 'shared/components/ui/label/LabelDropdown'; import AddLabel from 'shared/components/ui/dropdown/AddLabel'; import { mixin as clickaway } from 'vue-clickaway'; import conversationLabelMixin from 'dashboard/mixins/conversation/labelMixin'; +import { + getShadeOfHexColor, + getBleachBgOfHexColor, +} from 'shared/helpers/ColorHelper'; export default { components: { @@ -77,6 +82,8 @@ export default { }), }, methods: { + getShadeOfHexColor, + getBleachBgOfHexColor, toggleLabels() { this.showSearchDropdownLabel = !this.showSearchDropdownLabel; }, diff --git a/app/javascript/shared/assets/stylesheets/colors.scss b/app/javascript/shared/assets/stylesheets/colors.scss index 5784bb6bf..5fcf14754 100644 --- a/app/javascript/shared/assets/stylesheets/colors.scss +++ b/app/javascript/shared/assets/stylesheets/colors.scss @@ -7,7 +7,7 @@ --w-75: #D6EBFF; --w-100: #C2E1FF; --w-200: #99CEFF; - --w-300: ##70BAFF; + --w-300: #70BAFF; --w-400: #47A6FF; --w-500: #1F93FF; --w-600: #1976CC; diff --git a/app/javascript/shared/helpers/ColorHelper.js b/app/javascript/shared/helpers/ColorHelper.js new file mode 100644 index 000000000..315a63913 --- /dev/null +++ b/app/javascript/shared/helpers/ColorHelper.js @@ -0,0 +1,59 @@ +export const hexToHSLAsArray = H => { + // Convert hex to RGB first + let r = 0; + let g = 0; + let b = 0; + if (H.length === 4) { + r = '0x' + H[1] + H[1]; + g = '0x' + H[2] + H[2]; + b = '0x' + H[3] + H[3]; + } else if (H.length === 7) { + r = '0x' + H[1] + H[2]; + g = '0x' + H[3] + H[4]; + b = '0x' + H[5] + H[6]; + } + // Then to HSL + r /= 255; + g /= 255; + b /= 255; + let cmin = Math.min(r, g, b); + let cmax = Math.max(r, g, b); + let delta = cmax - cmin; + let h = 0; + let s = 0; + let l = 0; + + if (delta === 0) h = 0; + else if (cmax === r) h = ((g - b) / delta) % 6; + else if (cmax === g) h = (b - r) / delta + 2; + else h = (r - g) / delta + 4; + + h = Math.round(h * 60); + + if (h < 0) h += 360; + + l = (cmax + cmin) / 2; + s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1)); + s = +(s * 100).toFixed(1); + l = +(l * 100).toFixed(1); + + return [h, s, l]; +}; + +export const hexToHSL = hex => { + const [h, s, l] = hexToHSLAsArray(hex); + return 'hsl(' + h + ',' + s + '%,' + l + '%)'; +}; + +export const getTextShadeOfHexColor = (hex, shade = 40) => { + const [h, s, l] = hexToHSLAsArray(hex); + const newL = Math.min(22, Math.max(l - shade, 28)); + + return 'hsl(' + h + ',' + s + '%,' + newL + '%)'; +}; + +export const getBleachBgOfHexColor = (hex, bleach = 35) => { + const [h, s, l] = hexToHSLAsArray(hex); + const newL = Math.max(94, Math.min(l + bleach, 96)); + return 'hsl(' + h + ',' + s + '%,' + newL + '%)'; +}; diff --git a/app/javascript/shared/helpers/specs/ColorHelper.spec.js b/app/javascript/shared/helpers/specs/ColorHelper.spec.js new file mode 100644 index 000000000..acd67a638 --- /dev/null +++ b/app/javascript/shared/helpers/specs/ColorHelper.spec.js @@ -0,0 +1,34 @@ +import { + hexToHSLAsArray, + hexToHSL, + getTextShadeOfHexColor, + getBleachBgOfHexColor, +} from '../ColorHelper'; + +describe('#hexToHSLAsArray', () => { + it('should return correct color conversion for 6 digit hex', () => { + expect(hexToHSLAsArray('#ffffff')).toEqual([0, 0, 100]); + }); + + it('should return correct color conversion for 3 digit hex', () => { + expect(hexToHSLAsArray('#fff')).toEqual([0, 0, 100]); + }); +}); + +describe('#hexToHSL', () => { + it('should return correct color conversion for 6 digit hex to hsl string', () => { + expect(hexToHSL('#ffffff')).toEqual('hsl(0,0%,100%)'); + }); +}); + +describe('#getTextShadeOfHexColor', () => { + it('should return correct color shade for 6 digit hex to hsl string', () => { + expect(getTextShadeOfHexColor('#ffffff')).toEqual('hsl(0,0%,22%)'); + }); +}); + +describe('#getBleachBgOfHexColor', () => { + it('should return correct color shade for 6 digit hex to hsl string', () => { + expect(getBleachBgOfHexColor('#ffffff')).toEqual('hsl(0,0%,96%)'); + }); +});