Add a new packages @gitbook/colors (#2854)

Co-authored-by: Zeno Kapitein <zenomilan@me.com>
This commit is contained in:
Valentino Hudhra
2025-02-19 17:17:39 +01:00
committed by GitHub
parent 7419ee7dba
commit 445baaaa61
14 changed files with 145 additions and 28 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/colors': minor
---
Initial release
+10
View File
@@ -22,6 +22,13 @@
"wrangler": "3.82.0",
},
},
"packages/colors": {
"name": "@gitbook/colors",
"version": "0.1.0",
"devDependencies": {
"typescript": "^5.5.3",
},
},
"packages/emoji-codepoints": {
"name": "@gitbook/emoji-codepoints",
"version": "0.2.0",
@@ -35,6 +42,7 @@
"dependencies": {
"@gitbook/api": "^0.93.0",
"@gitbook/cache-do": "workspace:*",
"@gitbook/colors": "workspace:*",
"@gitbook/emoji-codepoints": "workspace:*",
"@gitbook/icons": "workspace:*",
"@gitbook/openapi-parser": "workspace:*",
@@ -594,6 +602,8 @@
"@gitbook/cache-do": ["@gitbook/cache-do@workspace:packages/cache-do"],
"@gitbook/colors": ["@gitbook/colors@workspace:packages/colors"],
"@gitbook/emoji-codepoints": ["@gitbook/emoji-codepoints@workspace:packages/emoji-codepoints"],
"@gitbook/fontawesome-pro": ["@gitbook/fontawesome-pro@1.0.8", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "^6.6.0" } }, "sha512-i4PgiuGyUb52Muhc52kK3aMJIMfMkA2RbPW30tre8a6M8T6mWTfYo6gafSgjNvF1vH29zcuB8oBYnF0gO4XcHA=="],
+1
View File
@@ -0,0 +1 @@
dist/
+3
View File
@@ -0,0 +1,3 @@
# `@gitbook/colors`
A set of default colors and transformation functions used throughout the GitBook Open and app.
+26
View File
@@ -0,0 +1,26 @@
{
"name": "@gitbook/colors",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"development": "./src/index.ts",
"default": "./dist/index.js"
}
},
"version": "0.1.0",
"devDependencies": {
"typescript": "^5.5.3"
},
"scripts": {
"build": "tsc",
"typecheck": "tsc --noEmit",
"dev": "tsc -w"
},
"files": [
"dist",
"src",
"README.md",
"CHANGELOG.md"
]
}
+39
View File
@@ -0,0 +1,39 @@
/**
* Default primary color throughout the GitBook ecosystem.
*/
export const DEFAULT_PRIMARY_COLOR = '#346DDB';
/**
* The darkest color that exists in GitBook, used as the relative minimum of every generated color scale.
*/
export const DARK_BASE = '#1D1D1D';
/**
* The lightest color that exists in GitBook, used as the relative maximum of every generated color scale.
*/
export const LIGHT_BASE = '#FFFFFF';
/**
* Used as the basis of all UI elements that are not colored by the primary color. Neutral gray by default, overridden by site customization.
*/
export const DEFAULT_TINT_COLOR = '#787878';
/**
* Used for informational messages and neutral alerts.
*/
export const DEFAULT_HINT_INFO_COLOR = '#787878';
/**
* Used for showing important information or non-critical warnings.
*/
export const DEFAULT_HINT_WARNING_COLOR = '#FE9A00';
/**
* Used for destructive actions or raising attention to critical information.
*/
export const DEFAULT_HINT_DANGER_COLOR = '#FB2C36';
/**
* Used for showing positive actions or achievements.
*/
export const DEFAULT_HINT_SUCCESS_COLOR = '#00C950';
+2
View File
@@ -0,0 +1,2 @@
export * from './colors';
export * from './transformations';
@@ -1,3 +1,5 @@
import { DARK_BASE, LIGHT_BASE, DEFAULT_TINT_COLOR } from './colors';
type ColorShades = {
[key: string]: string;
};
@@ -6,9 +8,6 @@ type RGBColor = [number, number, number];
type OKLABColor = { L: number; A: number; B: number };
type OKLCHColor = { L: number; C: number; H: number };
export const DARK_BASE = '#1d1d1d';
export const LIGHT_BASE = '#ffffff';
export const DEFAULT_TINT_COLOR = '#787878';
const D65 = [95.047, 100.0, 108.883]; // Reference white (D65)
export enum ColorCategory {
@@ -226,7 +225,7 @@ export function colorScale(
/**
* Convert a hex color to an RGB color set.
*/
function hexToRgbArray(hex: string): RGBColor {
export function hexToRgbArray(hex: string): RGBColor {
const originalHex = hex;
let value = hex.replace('#', '');
@@ -252,7 +251,7 @@ function hexToRgbArray(hex: string): RGBColor {
/**
* Convert a RGB color set to a hex color.
*/
function rgbArrayToHex(rgb: RGBColor): string {
export function rgbArrayToHex(rgb: RGBColor): string {
return `#${rgb
.map((channel) => {
const component = channel.toString(16);
@@ -262,7 +261,7 @@ function rgbArrayToHex(rgb: RGBColor): string {
.join('')}`;
}
function getColor(percentage: number, start: RGBColor, end: RGBColor) {
export function getColor(percentage: number, start: RGBColor, end: RGBColor) {
const rgb = end.map((channel, index) => {
return Math.round(channel + percentage * (start[index] - channel));
});
@@ -271,21 +270,21 @@ function getColor(percentage: number, start: RGBColor, end: RGBColor) {
}
// Utility constants and helper functions
function rgbToLinear(rgb: RGBColor): [number, number, number] {
export function rgbToLinear(rgb: RGBColor): [number, number, number] {
return rgb.map((v) => {
const scaled = v / 255;
return scaled <= 0.04045 ? scaled / 12.92 : ((scaled + 0.055) / 1.055) ** 2.4;
}) as [number, number, number];
}
function linearToRgb(linear: [number, number, number]): RGBColor {
export function linearToRgb(linear: [number, number, number]): RGBColor {
return linear.map((v) => {
const scaled = v <= 0.0031308 ? 12.92 * v : 1.055 * v ** (1 / 2.4) - 0.055;
return Math.round(Math.max(0, Math.min(1, scaled)) * 255);
}) as RGBColor;
}
function rgbToOklab(rgb: RGBColor): OKLABColor {
export function rgbToOklab(rgb: RGBColor): OKLABColor {
const [r, g, b] = rgbToLinear(rgb);
const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
@@ -303,7 +302,7 @@ function rgbToOklab(rgb: RGBColor): OKLABColor {
};
}
function oklabToRgb(oklab: OKLABColor): RGBColor {
export function oklabToRgb(oklab: OKLABColor): RGBColor {
const { L, A, B } = oklab;
const lRoot = L + 0.3963377774 * A + 0.2158037573 * B;
@@ -321,14 +320,14 @@ function oklabToRgb(oklab: OKLABColor): RGBColor {
return linearToRgb([r, g, b]);
}
function oklabToOklch(oklab: OKLABColor): OKLCHColor {
export function oklabToOklch(oklab: OKLABColor): OKLCHColor {
const { L, A, B } = oklab;
const C = Math.sqrt(A ** 2 + B ** 2);
const H = (Math.atan2(B, A) * 180) / Math.PI;
return { L, C, H: H < 0 ? H + 360 : H };
}
function oklchToOklab(oklch: OKLCHColor): OKLABColor {
export function oklchToOklab(oklch: OKLCHColor): OKLABColor {
const { L, C, H } = oklch;
const rad = (H * Math.PI) / 180;
return {
@@ -338,15 +337,15 @@ function oklchToOklab(oklch: OKLCHColor): OKLABColor {
};
}
function rgbToOklch(rgb: RGBColor): OKLCHColor {
export function rgbToOklch(rgb: RGBColor): OKLCHColor {
return oklabToOklch(rgbToOklab(rgb));
}
function oklchToRgb(oklch: OKLCHColor): RGBColor {
export function oklchToRgb(oklch: OKLCHColor): RGBColor {
return oklabToRgb(oklchToOklab(oklch));
}
function rgbToXyz(rgb: RGBColor): [number, number, number] {
export function rgbToXyz(rgb: RGBColor): [number, number, number] {
const [r, g, b] = rgbToLinear(rgb);
return [
(r * 0.4124564 + g * 0.3575761 + b * 0.1804375) * 100,
@@ -355,7 +354,11 @@ function rgbToXyz(rgb: RGBColor): [number, number, number] {
];
}
function xyzToLab65(xyz: [number, number, number]): { L: number; A: number; B: number } {
export function xyzToLab65(xyz: [number, number, number]): {
L: number;
A: number;
B: number;
} {
const [x, y, z] = xyz.map((v, i) => {
const scaled = v / D65[i];
return scaled > 0.008856 ? Math.cbrt(scaled) : 7.787 * scaled + 16 / 116;
@@ -368,7 +371,7 @@ function xyzToLab65(xyz: [number, number, number]): { L: number; A: number; B: n
};
}
function rgbTolab65(rgb: RGBColor): { L: number; A: number; B: number } {
export function rgbTolab65(rgb: RGBColor): { L: number; A: number; B: number } {
return xyzToLab65(rgbToXyz(rgb));
}
@@ -376,7 +379,7 @@ function rgbTolab65(rgb: RGBColor): { L: number; A: number; B: number } {
Delta Phi Star perceptual lightness contrast by Andrew Somers:
https://github.com/Myndex/deltaphistar
*/
const PHI = 0.5 + Math.sqrt(1.25);
export const PHI = 0.5 + Math.sqrt(1.25);
export function dpsContrast(a: RGBColor, b: RGBColor) {
const dps = Math.abs(rgbTolab65(a).L ** PHI - rgbTolab65(b).L ** PHI);
@@ -387,7 +390,10 @@ export function dpsContrast(a: RGBColor, b: RGBColor) {
export function colorContrast(background: string, foreground: string[] = [LIGHT_BASE, DARK_BASE]) {
const bg = hexToRgbArray(background);
const best: { color?: RGBColor; contrast: number } = { color: undefined, contrast: 0 };
const best: { color?: RGBColor; contrast: number } = {
color: undefined,
contrast: 0,
};
for (const color of foreground) {
const c = hexToRgbArray(color);
+24
View File
@@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": false,
"declaration": true,
"outDir": "dist",
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react",
"incremental": true,
"types": [
"bun-types" // add Bun global
]
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
}
+1
View File
@@ -19,6 +19,7 @@
"dependencies": {
"@gitbook/api": "^0.93.0",
"@gitbook/cache-do": "workspace:*",
"@gitbook/colors": "workspace:*",
"@gitbook/emoji-codepoints": "workspace:*",
"@gitbook/icons": "workspace:*",
"@gitbook/openapi-parser": "workspace:*",
@@ -1,11 +1,11 @@
import { CustomizationHeaderPreset } from '@gitbook/api';
import { colorContrast } from '@gitbook/colors';
import { redirect } from 'next/navigation';
import { ImageResponse } from 'next/og';
import { NextRequest } from 'next/server';
import React from 'react';
import { googleFontsMap } from '@/fonts';
import { colorContrast } from '@/lib/colors';
import { getAbsoluteHref } from '@/lib/links';
import { filterOutNullable } from '@/lib/typescript';
import { getContentTitle } from '@/lib/utils';
@@ -1,7 +1,7 @@
import { SiteInsightsAd } from '@gitbook/api';
import { hexToRgba } from '@gitbook/colors';
import * as React from 'react';
import { hexToRgba } from '@/lib/colors';
import { getResizedImageURL } from '@/lib/images';
import { tcls } from '@/lib/tailwind';
@@ -9,18 +9,18 @@ import {
type CustomizationTint,
type SiteCustomizationSettings,
} from '@gitbook/api';
import { IconsProvider, IconStyle } from '@gitbook/icons';
import { fontNotoColorEmoji, fonts, ibmPlexMono } from '@/fonts';
import { getSpaceLanguage } from '@/intl/server';
import { getStaticFileURL } from '@/lib/assets';
import {
colorContrast,
colorScale,
type ColorScaleOptions,
DEFAULT_TINT_COLOR,
hexToRgb,
} from '@/lib/colors';
} from '@gitbook/colors';
import { IconsProvider, IconStyle } from '@gitbook/icons';
import { fontNotoColorEmoji, fonts, ibmPlexMono } from '@/fonts';
import { getSpaceLanguage } from '@/intl/server';
import { getStaticFileURL } from '@/lib/assets';
import { tcls } from '@/lib/tailwind';
import { ClientContexts } from './ClientContexts';
+1 -1
View File
@@ -3,7 +3,7 @@ import typography from '@tailwindcss/typography';
import type { Config } from 'tailwindcss';
import plugin from 'tailwindcss/plugin';
import { ColorCategory, hexToRgb, scale, shadesOfColor } from './src/lib/colors';
import { ColorCategory, hexToRgb, scale, shadesOfColor } from '@gitbook/colors';
export const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900];
export const opacities = [0, 4, 8, 12, 16, 24, 40, 64, 72, 88, 96, 100];