-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
452 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import Color from "colorjs.io"; | ||
|
||
// TODO: Restrict type of color utils to make sure they are in the right color space | ||
|
||
export const stringColorToOklch = (color: string): Color => { | ||
const parsedColor = new Color(color); | ||
parsedColor; | ||
return parsedColor.to("oklch"); | ||
}; | ||
|
||
export const colorToHex = (color: Color): string => { | ||
return color.to("srgb").toString({ format: "hex" }); | ||
}; | ||
|
||
export const colorToShade = (color: Color, shade: number): Color => { | ||
const newColor = color.clone(); | ||
newColor.l += shade; | ||
return newColor; | ||
}; | ||
|
||
export const hasEnoughContrast = (color1: Color, color2: Color): boolean => { | ||
const contrast = color1.contrast(color2, "WCAG21"); | ||
const hasEnoughContrast = contrast > 4.5; | ||
return hasEnoughContrast; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
export const one = 1 | ||
export const two = 2 | ||
export { omeguiThemeGenerator } from "./themeGenerator"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
export const presetThemes = { | ||
emerald: { | ||
primary: "#66cc8a", | ||
primaryContent: "#223D30", | ||
secondary: "#377cfb", | ||
secondaryContent: "#fff", | ||
accent: "#f68067", | ||
accentContent: "#000", | ||
neutral: "#333c4d", | ||
neutralContent: "#f9fafb", | ||
background: "oklch(100% 0 0)", | ||
foreground: "#333c4d", | ||
info: "#00d3ee", | ||
infoContent: "#ffffff", | ||
success: "#39DA8A", | ||
successContent: "#ffffff", | ||
warning: "#ffaa00", | ||
warningContent: "#ffffff", | ||
error: "#f44336", | ||
errorContent: "#ffffff", | ||
}, | ||
retro: { | ||
primary: "#ef9995", | ||
primaryContent: "#282425", | ||
secondary: "#a4cbb4", | ||
secondaryContent: "#282425", | ||
accent: "#DC8850", | ||
accentContent: "#282425", | ||
neutral: "#2E282A", | ||
neutralContent: "#EDE6D4", | ||
background: "#ece3ca", | ||
background2: "#e4d8b4", | ||
background3: "#DBCA9A", | ||
foreground: "#282425", | ||
info: "#2563eb", | ||
success: "#16a34a", | ||
warning: "#d97706", | ||
error: "oklch(65.72% 0.199 27.33)", | ||
}, | ||
cyberpunk: { | ||
primary: "oklch(74.22% 0.209 6.35)", | ||
secondary: "oklch(83.33% 0.184 204.72)", | ||
accent: "oklch(71.86% 0.2176 310.43)", | ||
neutral: "oklch(23.04% 0.065 269.31)", | ||
neutralContent: "oklch(94.51% 0.179 104.32)", | ||
background: "oklch(94.51% 0.179 104.32)", | ||
}, | ||
pastel: { | ||
primary: "#d1c1d7", | ||
secondary: "#f6cbd1", | ||
accent: "#b4e9d6", | ||
neutral: "#70acc7", | ||
background: "oklch(100% 0 0)", | ||
background2: "#f9fafb", | ||
background3: "#d1d5db", | ||
}, | ||
nord: { | ||
primary: "#5E81AC", | ||
secondary: "#81A1C1", | ||
accent: "#88C0D0", | ||
neutral: "#4C566A", | ||
neutralContent: "#D8DEE9", | ||
background: "#ECEFF4", | ||
background2: "#E5E9F0", | ||
background3: "#D8DEE9", | ||
foreground: "#2E3440", | ||
info: "#B48EAD", | ||
success: "#A3BE8C", | ||
warning: "#EBCB8B", | ||
error: "#BF616A", | ||
}, | ||
autumn: { | ||
primary: "#8C0327", | ||
secondary: "#D85251", | ||
accent: "#D59B6A", | ||
neutral: "#826A5C", | ||
background: "#f1f1f1", | ||
info: "#42ADBB", | ||
success: "#499380", | ||
warning: "#E97F14", | ||
error: "oklch(53.07% 0.241 24.16)", | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { presetThemes } from "./presetThemes"; | ||
import { InputTheme } from "./themeTypes"; | ||
import { partialThemeToFullTheme, themeColorsToHexTheme } from "./themeUtils"; | ||
|
||
const inputThemeToTamaguiTheme = (inputTheme: InputTheme) => { | ||
const convertedFullTheme = themeColorsToHexTheme( | ||
partialThemeToFullTheme(inputTheme) | ||
); | ||
return { | ||
...convertedFullTheme, | ||
background: convertedFullTheme.background, | ||
backgroundHover: convertedFullTheme.background3, | ||
backgroundPress: convertedFullTheme.background3, | ||
backgroundFocus: convertedFullTheme.background3, | ||
borderColor: convertedFullTheme.background3, | ||
borderColorPress: convertedFullTheme.background3, | ||
borderColorFocus: convertedFullTheme.background3, | ||
borderColorHover: convertedFullTheme.neutral, | ||
color: convertedFullTheme.foreground, | ||
colorHover: convertedFullTheme.foreground, | ||
colorPress: convertedFullTheme.foreground, | ||
colorFocus: convertedFullTheme.foreground, | ||
shadowColor: "#363A3F1A", | ||
shadowColorHover: "#363A3F26", | ||
shadowColorPress: "#363A3F26", | ||
shadowColorFocus: "#363A3F26", | ||
placeholderColor: convertedFullTheme.neutral, | ||
}; | ||
}; | ||
|
||
type ThemeGeneratorInput = keyof typeof presetThemes | InputTheme; | ||
|
||
/** | ||
* Generate a Tamagui theme from the provided input theme. | ||
* @param light - The light theme, either a string corresponding to a preset theme or a custom theme object. | ||
* @param dark - The dark theme, either a string corresponding to a preset theme or a custom theme object. | ||
*/ | ||
export const omeguiThemeGenerator = ({ | ||
light, | ||
dark, | ||
}: { | ||
light: ThemeGeneratorInput; | ||
dark: ThemeGeneratorInput; | ||
}) => { | ||
const lightTheme = typeof light === "string" ? presetThemes[light] : light; | ||
const darkTheme = typeof dark === "string" ? presetThemes[dark] : dark; | ||
return { | ||
light: inputThemeToTamaguiTheme(lightTheme), | ||
dark: inputThemeToTamaguiTheme(darkTheme), | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
export type InputTheme = { | ||
// colorScheme: 'light' | 'dark' | ||
primary: string; | ||
primaryContent?: string; | ||
secondary: string; | ||
secondaryContent?: string; | ||
accent: string; | ||
accentContent?: string; | ||
neutral: string; | ||
neutralContent?: string; | ||
background?: string; | ||
background2?: string; | ||
background3?: string; | ||
foreground?: string; | ||
info?: string; | ||
infoContent?: string; | ||
success?: string; | ||
successContent?: string; | ||
warning?: string; | ||
warningContent?: string; | ||
error?: string; | ||
errorContent?: string; | ||
}; | ||
|
||
export type FullTheme = Required<InputTheme> & { | ||
primary2: string; | ||
secondary2: string; | ||
accent2: string; | ||
neutral2: string; | ||
info2: string; | ||
success2: string; | ||
warning2: string; | ||
error2: string; | ||
// tamagui | ||
// background: string; | ||
// backgroundHover: string; | ||
// backgroundPress: string; | ||
// backgroundFocus: string; | ||
// borderColor: string; | ||
// borderColorPress: string; | ||
// borderColorFocus: string; | ||
// borderColorHover: string; | ||
// color: string; | ||
// colorHover: string; | ||
// colorPress: string; | ||
// colorFocus: string; | ||
// shadowColor: string; | ||
// shadowColorHover: string; | ||
// shadowColorPress: string; | ||
// shadowColorFocus: string; | ||
// placeholderColor: string; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import type { FullTheme, InputTheme } from "./themeTypes"; | ||
import { | ||
colorToHex, | ||
colorToShade, | ||
hasEnoughContrast, | ||
stringColorToOklch, | ||
} from "./colorUtils"; | ||
|
||
export const themeColorsToHexTheme = (theme: InputTheme): any => { | ||
return Object.keys(theme).reduce((acc, key) => { | ||
return { | ||
...acc, | ||
// @ts-ignore - TODO typescript magic to make this work | ||
[key]: colorToHex(stringColorToOklch(theme[key])), | ||
}; | ||
}, {}); | ||
}; | ||
|
||
const colorToContent = ( | ||
color: string, | ||
foreground: string, | ||
background: string | ||
): string => { | ||
const goodContrast = hasEnoughContrast( | ||
stringColorToOklch(color), | ||
stringColorToOklch(foreground) | ||
); | ||
if (goodContrast) { | ||
return foreground; | ||
} | ||
return background; | ||
}; | ||
|
||
// TODO check for darkness to set shade correctly | ||
// TODO support dark themes | ||
export const partialThemeToFullTheme = ( | ||
partialTheme: InputTheme | ||
): FullTheme => { | ||
const background = partialTheme.background ?? "#FFF"; | ||
const foreground = partialTheme.foreground ?? "#000"; | ||
const info = partialTheme.info ?? "oklch(0.7206 0.191 231.6)"; | ||
const success = partialTheme.success ?? "oklch(0.648 0.15 160)"; | ||
const warning = partialTheme.warning ?? "oklch(0.8471 0.199 83.87)"; | ||
const error = partialTheme.error ?? "oklch(0.7176 0.221 22.18)"; | ||
return { | ||
...partialTheme, | ||
background, | ||
foreground, | ||
neutralContent: | ||
partialTheme.neutralContent ?? | ||
colorToContent(partialTheme.neutral, foreground, background), | ||
primaryContent: | ||
partialTheme.primaryContent ?? | ||
colorToContent(partialTheme.primary, foreground, background), | ||
secondaryContent: | ||
partialTheme.secondaryContent ?? | ||
colorToContent(partialTheme.secondary, foreground, background), | ||
accentContent: | ||
partialTheme.accentContent ?? | ||
colorToContent(partialTheme.accent, foreground, background), | ||
background2: | ||
partialTheme.background2 ?? | ||
colorToShade(stringColorToOklch(background), -0.1).toString(), | ||
background3: | ||
partialTheme.background3 ?? | ||
colorToShade(stringColorToOklch(background), -0.2).toString(), | ||
primary2: colorToShade( | ||
stringColorToOklch(partialTheme.primary), | ||
-0.1 | ||
).toString(), | ||
secondary2: colorToShade( | ||
stringColorToOklch(partialTheme.secondary), | ||
-0.1 | ||
).toString(), | ||
accent2: colorToShade( | ||
stringColorToOklch(partialTheme.accent), | ||
-0.1 | ||
).toString(), | ||
neutral2: colorToShade( | ||
stringColorToOklch(partialTheme.neutral), | ||
-0.1 | ||
).toString(), | ||
info, | ||
info2: colorToShade(stringColorToOklch(info), -0.1).toString(), | ||
infoContent: | ||
partialTheme.infoContent ?? colorToContent(info, foreground, background), | ||
success, | ||
success2: colorToShade(stringColorToOklch(success), -0.1).toString(), | ||
successContent: | ||
partialTheme.successContent ?? | ||
colorToContent(success, foreground, background), | ||
warning, | ||
warning2: colorToShade(stringColorToOklch(warning), -0.1).toString(), | ||
warningContent: | ||
partialTheme.warningContent ?? | ||
colorToContent(warning, foreground, background), | ||
error, | ||
error2: colorToShade(stringColorToOklch(error), -0.1).toString(), | ||
errorContent: | ||
partialTheme.errorContent ?? | ||
colorToContent(error, foreground, background), | ||
}; | ||
}; |
Oops, something went wrong.