docs: add more about theme providing

This commit is contained in:
Corbin Crutchley
2023-12-18 03:07:37 -08:00
parent ac5ccbd7e7
commit 5e1d2a43bc
18 changed files with 2143 additions and 1096 deletions

View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1,9 @@
<html>
<head>
<title>React Theme Cache</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
{
"name": "@unicorn-utterances/react-theme-cache",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "18.3.0-canary-0cdfef19b-20231211",
"react-dom": "18.3.0-canary-0cdfef19b-20231211"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.2.1",
"vite": "^5.0.10"
}
}

View File

@@ -0,0 +1,46 @@
function hexToRgb(hex) {
// Remove the hash character
hex = hex.replace(/^#/, "");
// Parse the hex value into separate R, G, B values
const bigint = parseInt(hex, 16);
const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
const b = bigint & 255;
return { r, g, b };
}
function rgbToHex(r, g, b) {
// Convert RGB values to a hex color code
return `#${((1 << 24) | (r << 16) | (g << 8) | b).toString(16).slice(1)}`;
}
export function generateComplimentaryColors(hexColor) {
const baseColor = hexToRgb(hexColor);
// Calculate the complementary color by inverting each RGB component
const complimentary1 = rgbToHex(
255 - baseColor.r,
255 - baseColor.g,
255 - baseColor.b,
);
// Optionally, you can adjust the following multipliers for different shades
const multiplier = 0.8;
const complimentary3 = rgbToHex(
Math.floor(baseColor.r * (1 + multiplier)),
Math.floor(baseColor.g * (1 + multiplier)),
Math.floor(baseColor.b * (1 + multiplier)),
);
return [complimentary1, complimentary3];
}
export const getReadableColor = (hexcolor) => {
const r = parseInt(hexcolor.substr(1, 2), 16);
const g = parseInt(hexcolor.substr(3, 2), 16);
const b = parseInt(hexcolor.substr(5, 2), 16);
const yiq = (r * 299 + g * 587 + b * 114) / 1000;
return yiq >= 128 ? "#000000" : "#ffffff";
};

View File

@@ -0,0 +1,81 @@
import { createRoot } from "react-dom/client";
import { cache, useState } from "react";
import { generateComplimentaryColors, getReadableColor } from "./colors.js";
import "./style.css";
const getTheme = cache((primaryColor) => {
// Theoretically, this could get very expensive to compute
// Depending on how many colors and how accurately
const [secondaryColor, tertiaryColor] =
generateComplimentaryColors(primaryColor);
return {
primaryColor,
secondaryColor,
tertiaryColor,
primaryTextColor: getReadableColor(primaryColor),
secondaryTextColor: getReadableColor(secondaryColor),
tertiaryTextColor: getReadableColor(tertiaryColor),
};
});
const capitalize = (str) => str[0].toUpperCase() + str.slice(1);
function ThemePreviewRow({ type, themeColor }) {
// The calculations to get the theme only occur once, even though this is
// called in multiple component instances.
const theme = getTheme(themeColor);
return (
<tr>
<th>{capitalize(type)}</th>
<td>
<div
className="colorBox"
style={{
backgroundColor: theme[type + "Color"],
color: theme[type + "TextColor"],
}}
>
Some Text
</div>
</td>
</tr>
);
}
function App() {
const [themeColor, setThemeColor] = useState("#7e38ff");
const [tempColor, setTempColor] = useState(themeColor);
return (
<div>
<div className="spaceBottom">
<div className="spaceBottom">
<label>
<div className="spaceBottom">Primary color</div>
<input
type="color"
id="body"
name="body"
value={tempColor}
onChange={(e) => setTempColor(e.target.value)}
/>
</label>
</div>
<div>
<button onClick={() => setThemeColor(tempColor)}>Set theme</button>
</div>
</div>
<div>
<table>
<tbody>
<ThemePreviewRow type="primary" themeColor={themeColor} />
<ThemePreviewRow type="secondary" themeColor={themeColor} />
<ThemePreviewRow type="tertiary" themeColor={themeColor} />
</tbody>
</table>
</div>
</div>
);
}
createRoot(document.getElementById("root")).render(<App />);

View File

@@ -0,0 +1,16 @@
.spaceBottom {
margin-bottom: 1rem;
}
.colorBox {
margin-left: 0.5rem;
min-height: 25px;
min-width: 100px;
text-align: center;
display: flex;
font-weight: bold;
align-items: center;
justify-content: center;
border: 2px solid #3c3c3c;
border-radius: 8px;
}

View File

@@ -0,0 +1,6 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
});