Skip to content

Commit b31aea5

Browse files
authored
Add Catppuccin theme (#17)
1 parent 6bf06ab commit b31aea5

3 files changed

Lines changed: 168 additions & 56 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6+
"@catppuccin/palette": "^1.7.1",
67
"@monaco-editor/react": "^4.6.0",
78
"copy-to-clipboard": "^3.3.3",
89
"history": "^5.3.0",

src/style/themes.ts

Lines changed: 134 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import type { editor } from 'monaco-editor';
22

3+
import { CatppuccinFlavor, ColorFormat, flavors } from '@catppuccin/palette';
34
import dracula from 'monaco-themes/themes/Dracula.json';
45
import monokai from 'monaco-themes/themes/Monokai.json';
56
import solarizedDark from 'monaco-themes/themes/Solarized-dark.json';
67
import solarizedLight from 'monaco-themes/themes/Solarized-light.json';
78

89
type Color = `#${string}`;
10+
type ColorRecord = Record<string, Color>;
911

1012
export interface Theme {
1113
id: string;
@@ -28,6 +30,10 @@ export interface Themes {
2830
'monokai': Theme;
2931
'solarized': Theme;
3032
'solarized-light': Theme;
33+
'latte': Theme;
34+
'frappe': Theme;
35+
'macchiato': Theme;
36+
'mocha': Theme;
3137
}
3238

3339
const themes: Themes = {
@@ -44,31 +50,34 @@ const themes: Themes = {
4450
backgroundColor: '#161b22', // canvas.overlay
4551
},
4652

47-
editor: makeMonacoTheme({
48-
base: 'vs-dark',
49-
colors: {
50-
primary: '#c9d1d9', // fg.default
51-
background: '#0d1117', // canvas.default
52-
comment: '#8b949e',
53-
delimiter: '#d2a8ff',
54-
annotation: '#a5d6ff',
55-
constant: '#ff7b72',
56-
number: '#f2cc60',
57-
string: '#79c0ff',
58-
operator: '#ff7b72',
59-
keyword: '#ff7b72',
60-
type: '#ffa657',
61-
variable: '#ffa657',
62-
logInfo: '#3fb950', // green.3
63-
logError: '#f85149', // red.4
64-
logWarning: '#d29922', // yellow.3
65-
logDate: '#33B3AE', // teal.3
66-
logException: '#f8e3a1', // yellow.0
67-
diffMeta: '#33B3AE', // teal.3
68-
diffAddition: '#3fb950', // green.3
69-
diffDeletion: '#f85149', // red.4
53+
editor: makeMonacoTheme(
54+
{
55+
base: 'vs-dark',
56+
colors: {
57+
primary: '#c9d1d9', // fg.default
58+
background: '#0d1117', // canvas.default
59+
comment: '#8b949e',
60+
delimiter: '#d2a8ff',
61+
annotation: '#a5d6ff',
62+
constant: '#ff7b72',
63+
number: '#f2cc60',
64+
string: '#79c0ff',
65+
operator: '#ff7b72',
66+
keyword: '#ff7b72',
67+
type: '#ffa657',
68+
variable: '#ffa657',
69+
logInfo: '#3fb950', // green.3
70+
logError: '#f85149', // red.4
71+
logWarning: '#d29922', // yellow.3
72+
logDate: '#33B3AE', // teal.3
73+
logException: '#f8e3a1', // yellow.0
74+
diffMeta: '#33B3AE', // teal.3
75+
diffAddition: '#3fb950', // green.3
76+
diffDeletion: '#f85149', // red.4
77+
},
7078
},
71-
}),
79+
{}
80+
),
7281
},
7382
'light': {
7483
id: 'light',
@@ -83,31 +92,34 @@ const themes: Themes = {
8392
backgroundColor: '#e0f6ff',
8493
},
8594

86-
editor: makeMonacoTheme({
87-
base: 'vs',
88-
colors: {
89-
primary: '#000000',
90-
background: '#ffffff',
91-
comment: '#708090',
92-
delimiter: '#999999',
93-
annotation: '#999999',
94-
constant: '#990055',
95-
number: '#990055',
96-
string: '#669900',
97-
operator: '#9a6e3a',
98-
keyword: '#0077aa',
99-
type: '#DD4A68',
100-
variable: '#ee9900',
101-
logInfo: '#2da44e', // green.4
102-
logError: '#cf222e', // red.5
103-
logWarning: '#d4a72c', // yellow.3
104-
logDate: '#136061', // teal.6
105-
logException: '#7d4e00', // yellow.6
106-
diffMeta: '#136061', // teal.6
107-
diffAddition: '#2da44e', // green.4
108-
diffDeletion: '#cf222e', // red.5
95+
editor: makeMonacoTheme(
96+
{
97+
base: 'vs',
98+
colors: {
99+
primary: '#000000',
100+
background: '#ffffff',
101+
comment: '#708090',
102+
delimiter: '#999999',
103+
annotation: '#999999',
104+
constant: '#990055',
105+
number: '#990055',
106+
string: '#669900',
107+
operator: '#9a6e3a',
108+
keyword: '#0077aa',
109+
type: '#DD4A68',
110+
variable: '#ee9900',
111+
logInfo: '#2da44e', // green.4
112+
logError: '#cf222e', // red.5
113+
logWarning: '#d4a72c', // yellow.3
114+
logDate: '#136061', // teal.6
115+
logException: '#7d4e00', // yellow.6
116+
diffMeta: '#136061', // teal.6
117+
diffAddition: '#2da44e', // green.4
118+
diffDeletion: '#cf222e', // red.5
119+
},
109120
},
110-
}),
121+
{}
122+
),
111123
},
112124
'dracula': {
113125
id: 'dracula',
@@ -197,6 +209,10 @@ const themes: Themes = {
197209
diffDeletion: '#dc322f', // red
198210
}),
199211
},
212+
'latte': createCatppuccinTheme(flavors.latte),
213+
'frappe': createCatppuccinTheme(flavors.frappe),
214+
'macchiato': createCatppuccinTheme(flavors.macchiato),
215+
'mocha': createCatppuccinTheme(flavors.mocha),
200216
};
201217

202218
export default themes;
@@ -231,7 +247,8 @@ interface MonacoThemeProps {
231247
}
232248

233249
export function makeMonacoTheme(
234-
props: MonacoThemeProps
250+
props: MonacoThemeProps,
251+
extraColors: ColorRecord
235252
): editor.IStandaloneThemeData {
236253
const colors = Object.fromEntries(
237254
Object.entries(props.colors).map(([key, color]) => [
@@ -240,6 +257,11 @@ export function makeMonacoTheme(
240257
])
241258
) as Record<keyof MonacoThemeProps['colors'], string>;
242259

260+
const editorColors: ColorRecord = {
261+
'editor.background': `#${colors.background}`,
262+
'editor.foreground': `#${colors.primary}`,
263+
};
264+
243265
return {
244266
base: props.base,
245267
inherit: true,
@@ -274,10 +296,7 @@ export function makeMonacoTheme(
274296
{ token: 'addition.diff', foreground: colors.diffAddition },
275297
{ token: 'deletion.diff', foreground: colors.diffDeletion },
276298
],
277-
colors: {
278-
'editor.background': `#${colors.background}`,
279-
'editor.foreground': `#${colors.primary}`,
280-
},
299+
colors: { ...editorColors, ...extraColors },
281300
};
282301
}
283302

@@ -302,3 +321,65 @@ export function addExtraColors(
302321
);
303322
return theme;
304323
}
324+
325+
export function createCatppuccinTheme(flavor: CatppuccinFlavor): Theme {
326+
const color = (color: ColorFormat) => color.hex as Color;
327+
const nameToId: Record<string, string> = {
328+
[flavors.latte.name]: 'latte',
329+
[flavors.frappe.name]: 'frappe',
330+
[flavors.macchiato.name]: 'macchiato',
331+
[flavors.mocha.name]: 'mocha',
332+
};
333+
334+
const editorTheme = makeMonacoTheme(
335+
{
336+
base: flavor.dark ? 'vs-dark' : 'vs',
337+
colors: {
338+
// Monaco
339+
primary: color(flavor.colors.text),
340+
background: color(flavor.colors.mantle),
341+
string: color(flavor.colors.green),
342+
comment: color(flavor.colors.overlay2),
343+
delimiter: color(flavor.colors.overlay2),
344+
annotation: color(flavor.colors.yellow),
345+
constant: color(flavor.colors.peach),
346+
number: color(flavor.colors.peach),
347+
operator: color(flavor.colors.sky),
348+
keyword: color(flavor.colors.mauve),
349+
type: color(flavor.colors.yellow),
350+
variable: color(flavor.colors.text),
351+
352+
// Log Files
353+
logDate: color(flavor.colors.mauve),
354+
logInfo: color(flavor.colors.green),
355+
logWarning: color(flavor.colors.yellow),
356+
logError: color(flavor.colors.red),
357+
logException: color(flavor.colors.yellow),
358+
359+
// Diff Files
360+
diffMeta: color(flavor.colors.sky),
361+
diffAddition: color(flavor.colors.green),
362+
diffDeletion: color(flavor.colors.red),
363+
},
364+
},
365+
{
366+
'editorBracketHighlight.foreground1': color(flavor.colors.overlay2),
367+
'editorBracketHighlight.foreground2': color(flavor.colors.overlay2),
368+
'editorBracketHighlight.foreground3': color(flavor.colors.overlay2),
369+
}
370+
);
371+
372+
return {
373+
id: nameToId[flavor.name],
374+
lightOrDark: flavor.dark ? 'dark' : 'light',
375+
primary: color(flavor.colors.text),
376+
secondary: color(flavor.colors.base),
377+
highlight: color(flavor.colors.surface0),
378+
background: color(flavor.colors.mantle),
379+
highlightedLine: {
380+
color: color(flavor.colors.rosewater),
381+
backgroundColor: color(flavor.colors.surface2),
382+
},
383+
editor: editorTheme,
384+
};
385+
}

yarn.lock

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,11 @@
10861086
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
10871087
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
10881088

1089+
"@catppuccin/palette@^1.7.1":
1090+
version "1.7.1"
1091+
resolved "https://registry.yarnpkg.com/@catppuccin/palette/-/palette-1.7.1.tgz#c7cd165dcc1fc025a05ac138a4749b2279cf115e"
1092+
integrity sha512-aRc1tbzrevOTV7nFTT9SRdF26w/MIwT4Jwt4fDMc9itRZUDXCuEDBLyz4TQMlqO9ZP8mf5Hu4Jr6D03NLFc6Gw==
1093+
10891094
"@csstools/normalize.css@*":
10901095
version "12.1.1"
10911096
resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-12.1.1.tgz#f0ad221b7280f3fc814689786fd9ee092776ef8f"
@@ -8727,7 +8732,16 @@ string-natural-compare@^3.0.1:
87278732
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
87288733
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
87298734

8730-
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0:
8735+
"string-width-cjs@npm:string-width@^4.2.0":
8736+
version "4.2.3"
8737+
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
8738+
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
8739+
dependencies:
8740+
emoji-regex "^8.0.0"
8741+
is-fullwidth-code-point "^3.0.0"
8742+
strip-ansi "^6.0.1"
8743+
8744+
string-width@^4.1.0, string-width@^4.2.0:
87318745
version "4.2.3"
87328746
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
87338747
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -8831,7 +8845,14 @@ stringify-object@^3.3.0:
88318845
is-obj "^1.0.1"
88328846
is-regexp "^1.0.0"
88338847

8834-
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
8848+
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
8849+
version "6.0.1"
8850+
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
8851+
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
8852+
dependencies:
8853+
ansi-regex "^5.0.1"
8854+
8855+
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
88358856
version "6.0.1"
88368857
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
88378858
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -9907,7 +9928,16 @@ workbox-window@6.6.1:
99079928
"@types/trusted-types" "^2.0.2"
99089929
workbox-core "6.6.1"
99099930

9910-
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
9931+
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
9932+
version "7.0.0"
9933+
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
9934+
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
9935+
dependencies:
9936+
ansi-styles "^4.0.0"
9937+
string-width "^4.1.0"
9938+
strip-ansi "^6.0.0"
9939+
9940+
wrap-ansi@^7.0.0:
99119941
version "7.0.0"
99129942
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
99139943
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==

0 commit comments

Comments
 (0)