Skip to content

Commit af36601

Browse files
feat: auto-generate accent global color from team settings, or use default
1 parent d78a1ed commit af36601

File tree

13 files changed

+254
-29
lines changed

13 files changed

+254
-29
lines changed

package-lock.json

+47-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
"crisp-countries-languages": "0.8.0",
4343
"crypto-js": "4.1.1",
4444
"escape-html": "1.0.3",
45+
"hex-rgb": "5.0.0",
46+
"mix-css-color": "0.2.0",
4547
"js-file-downloader": "1.1.25",
4648
"keycode": "2.2.1",
4749
"lodash.camelcase": "4.3.0",

src/App.vue

+32
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
@contextmenu.prevent
1414
@dragover.prevent
1515
@drop.prevent.stop
16+
:style="appStyle"
1617
:class=`[
1718
"s-app",
1819
"u-appearance",
@@ -51,6 +52,9 @@ import {
5152
translucent as runtimeTranslucent
5253
} from "@/utilities/runtime";
5354

55+
// CONSTANTS
56+
const COLOR_ACCENT_BACKGROUND_DARKEN_RATIO = 0.08; // 8%
57+
5458
export default {
5559
name: "App",
5660

@@ -68,10 +72,38 @@ export default {
6872
},
6973

7074
computed: {
75+
appStyle(): { [property: string]: string } {
76+
// Acquire all accent colors (team-wide or default)
77+
const accentBackground =
78+
this.account.team.accent.background ||
79+
this.$styles.colors.defaultAccentBackground,
80+
accentText =
81+
this.account.team.accent.text ||
82+
this.$styles.colors.defaultAccentText;
83+
84+
// Generate actual style
85+
return {
86+
// Accent color (background)
87+
"--color-accent-background-normal":
88+
this.$filters.color.hexVar(accentBackground),
89+
"--color-accent-background-dark": this.$filters.color.darkenVar(
90+
accentBackground,
91+
COLOR_ACCENT_BACKGROUND_DARKEN_RATIO
92+
),
93+
94+
// Accent color (text)
95+
"--color-accent-text": this.$filters.color.hexVar(accentText)
96+
};
97+
},
98+
7199
session(): typeof Store.$session {
72100
return Store.$session;
73101
},
74102

103+
account(): typeof Store.$account {
104+
return Store.$account;
105+
},
106+
75107
settings(): typeof Store.$settings {
76108
return Store.$settings;
77109
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* This file is part of prose-app-web
3+
*
4+
* Copyright 2025, Prose Foundation
5+
*/
6+
7+
/* *************************************************************************
8+
* EXPORTS > COLORS
9+
* **************************************************************************/
10+
11+
:export {
12+
// Important: only export what is needed here!
13+
14+
// Defaults
15+
16+
defaultAccentBackground: $color-default-accent-background;
17+
defaultAccentText: $color-default-accent-text;
18+
}

src/assets/stylesheets/utilities/_utilities.appearance.scss

-16
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,6 @@
4848
--color-text-tertiary: #{hex-var($color-text-tertiary)};
4949
--color-text-reverse: #{hex-var($color-text-reverse)};
5050

51-
// Accents
52-
--color-accent-background-normal: #{hex-var($color-accent-background)};
53-
--color-accent-background-dark: #{hex-var(
54-
darken($color-accent-background, 8%)
55-
)};
56-
--color-accent-text: #{hex-var($color-accent-text)};
57-
5851
&--dark {
5952
// Black
6053
--color-black: #{hex-var(invert($color-black))};
@@ -107,14 +100,5 @@
107100
--color-text-secondary: #{hex-var(invert($color-text-secondary))};
108101
--color-text-tertiary: #{hex-var(invert($color-text-tertiary))};
109102
--color-text-reverse: #{hex-var(invert($color-text-reverse))};
110-
111-
// Accents
112-
--color-accent-background-normal: #{hex-var(
113-
lighten($color-accent-background, 4%)
114-
)};
115-
--color-accent-background-dark: #{hex-var(
116-
lighten($color-accent-background, 6%)
117-
)};
118-
--color-accent-text: #{hex-var(invert($color-accent-text))};
119103
}
120104
}

src/assets/stylesheets/variables/_variables.colors.scss

+4-3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ $color-text-secondary: #828993;
5454
$color-text-tertiary: #999fa7;
5555
$color-text-reverse: #ffffff;
5656

57-
// Accents
58-
$color-accent-background: $color-base-blue-normal;
59-
$color-accent-text: $color-text-reverse;
57+
// Defaults
58+
59+
$color-default-accent-background: $color-base-blue-normal;
60+
$color-default-accent-text: $color-text-reverse;

src/bootstrap/config.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,26 @@ import { App } from "vue";
1414
// PROJECT: COMMONS
1515
import CONFIG from "@/commons/config";
1616

17+
/**************************************************************************
18+
* TYPES
19+
* ************************************************************************* */
20+
21+
type Config = typeof CONFIG;
22+
1723
/**************************************************************************
1824
* CONFIG
1925
* ************************************************************************* */
2026

2127
class BootstrapConfig {
2228
init(app: App): void {
2329
// Global configuration
24-
app.config.globalProperties.$CONFIG = CONFIG;
30+
app.config.globalProperties.$config = CONFIG as Config;
2531
}
2632
}
2733

2834
/**************************************************************************
2935
* EXPORTS
3036
* ************************************************************************* */
3137

38+
export type { Config };
3239
export default new BootstrapConfig();

src/bootstrap/filters.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { App } from "vue";
1414
// PROJECT: FILTERS
1515
import dateFilters from "@/filters/date";
1616
import stringFilters from "@/filters/string";
17+
import colorFilters from "@/filters/color";
1718

1819
/**************************************************************************
1920
* INTERFACES
@@ -22,6 +23,7 @@ import stringFilters from "@/filters/string";
2223
interface Filters {
2324
date: typeof dateFilters;
2425
string: typeof stringFilters;
26+
color: typeof colorFilters;
2527
}
2628

2729
/**************************************************************************
@@ -32,7 +34,8 @@ class BootstrapFilters {
3234
init(app: App): void {
3335
app.config.globalProperties.$filters = {
3436
date: dateFilters,
35-
string: stringFilters
37+
string: stringFilters,
38+
color: colorFilters
3639
} as Filters;
3740
}
3841
}

src/bootstrap/styles.ts

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* This file is part of prose-app-web
3+
*
4+
* Copyright 2025, Prose Foundation
5+
*/
6+
7+
/**************************************************************************
8+
* IMPORTS
9+
* ************************************************************************* */
10+
11+
// NPM
12+
import { App } from "vue";
13+
14+
// PROJECT: STYLES
15+
import styleExportsColors from "@/assets/stylesheets/exports/_exports.colors.module.scss";
16+
17+
/**************************************************************************
18+
* INTERFACES
19+
* ************************************************************************* */
20+
21+
interface Styles {
22+
colors: typeof styleExportsColors;
23+
}
24+
25+
/**************************************************************************
26+
* CONFIG
27+
* ************************************************************************* */
28+
29+
class BootstrapStyles {
30+
init(app: App): void {
31+
// Global configuration
32+
app.config.globalProperties.$styles = {
33+
colors: styleExportsColors
34+
} as Styles;
35+
}
36+
}
37+
38+
/**************************************************************************
39+
* EXPORTS
40+
* ************************************************************************* */
41+
42+
export type { Styles };
43+
export default new BootstrapStyles();

src/filters/color.ts

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* This file is part of prose-app-web
3+
*
4+
* Copyright 2025, Prose Foundation
5+
*/
6+
7+
/**************************************************************************
8+
* IMPORTS
9+
* ************************************************************************* */
10+
11+
// NPM
12+
import hexRgb from "hex-rgb";
13+
import colorMix from "mix-css-color";
14+
15+
/**************************************************************************
16+
* TYPES
17+
* ************************************************************************* */
18+
19+
type ColorHex = string;
20+
type ColorVar = string;
21+
22+
/**************************************************************************
23+
* CONSTANTS
24+
* ************************************************************************* */
25+
26+
const RATIO_TO_PERCENT = 100; // 100%
27+
28+
const COLOR_MIX_COLOR_BLACK = "black";
29+
const COLOR_MIX_CORRECTIVE_FACTOR = 1.75;
30+
31+
/**************************************************************************
32+
* FILTERS
33+
***************************************************************************/
34+
35+
class FilterColor {
36+
hexVar(hex: ColorHex): ColorVar {
37+
// Convert hexadecimal to RGB, and return CSS-compatible 'R, G, B' \
38+
// format, equivalent to the return value of the 'hex-var()' global \
39+
// SCSS function.
40+
return hexRgb(hex, {
41+
format: "array"
42+
})
43+
.slice(0, 3)
44+
.join(", ");
45+
}
46+
47+
darkenVar(hex: ColorHex, ratio: number): ColorVar {
48+
// Convert hexadecimal to darkened RGB, and return CSS-compatible \
49+
// 'R, G, B' format, equivalent to the return value of the \
50+
// 'darken-var()' global SCSS function.
51+
// Notice: apply a corrective factor to the percent so that it looks \
52+
// almost like SCSS darken() function.
53+
const mixedColor = colorMix(
54+
COLOR_MIX_COLOR_BLACK,
55+
hex,
56+
ratio * RATIO_TO_PERCENT * COLOR_MIX_CORRECTIVE_FACTOR
57+
);
58+
59+
return this.hexVar(mixedColor.hex);
60+
}
61+
}
62+
63+
/**************************************************************************
64+
* EXPORTS
65+
***************************************************************************/
66+
67+
export default new FilterColor();

0 commit comments

Comments
 (0)