mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-16 15:45:13 +00:00
Add a new packages @gitbook/colors (#2854)
Co-authored-by: Zeno Kapitein <zenomilan@me.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@gitbook/colors': minor
|
||||
---
|
||||
|
||||
Initial release
|
||||
@@ -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=="],
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
dist/
|
||||
@@ -0,0 +1,3 @@
|
||||
# `@gitbook/colors`
|
||||
|
||||
A set of default colors and transformation functions used throughout the GitBook Open and app.
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
@@ -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';
|
||||
@@ -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);
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -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
-1
@@ -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';
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user