initial commit
Some checks failed
ci / go (push) Has been cancelled
ci / admin-ui (push) Has been cancelled
ci / runtime-sdk (push) Has been cancelled
ci / helm (push) Has been cancelled
ci / openapi (push) Has been cancelled
ci / container (push) Has been cancelled
ci / release-config (push) Has been cancelled
ci / shared styling (push) Has been cancelled
ci / security (push) Has been cancelled
ci / all green (push) Has been cancelled
Some checks failed
ci / go (push) Has been cancelled
ci / admin-ui (push) Has been cancelled
ci / runtime-sdk (push) Has been cancelled
ci / helm (push) Has been cancelled
ci / openapi (push) Has been cancelled
ci / container (push) Has been cancelled
ci / release-config (push) Has been cancelled
ci / shared styling (push) Has been cancelled
ci / security (push) Has been cancelled
ci / all green (push) Has been cancelled
This commit is contained in:
commit
951dd8d26b
175 changed files with 50041 additions and 0 deletions
605
internal/seed/consolidated.go
Normal file
605
internal/seed/consolidated.go
Normal file
|
|
@ -0,0 +1,605 @@
|
|||
package seed
|
||||
|
||||
import (
|
||||
"github.com/urpi/go-bananas/internal/domain"
|
||||
"github.com/urpi/go-bananas/internal/tokenengine"
|
||||
)
|
||||
|
||||
// Palettes consolidated from the sibling applications.
|
||||
//
|
||||
// Each of these is a real palette lifted from an application that is already running
|
||||
// with it, rather than a generated ramp. That is the point of consolidating them: the
|
||||
// applications can adopt the shared contract and keep the look their users already
|
||||
// have, instead of being handed a new design.
|
||||
//
|
||||
// The colours are the roles those applications actually use, mapped onto the contract's
|
||||
// roles. A source application had only one appearance for some roles and a different
|
||||
// one for others, so both schemes are filled in here and the contract supplies the
|
||||
// second axis.
|
||||
//
|
||||
// Provenance is recorded in the description. A palette nobody can trace back to the
|
||||
// screen it came from becomes an orphan within a year.
|
||||
|
||||
// Colours and values repeated across the palettes below.
|
||||
//
|
||||
// A consolidated palette set is mostly repetition by nature — every dark scheme has
|
||||
// the same white for reversed text, every go-loose theme has the same card radius —
|
||||
// so these are named rather than repeated inline. That makes a change to "what white
|
||||
// means here" a one-line edit instead of a search.
|
||||
const (
|
||||
white = "#ffffff"
|
||||
paperLight = "#fffaf0"
|
||||
cardRadius = "16px"
|
||||
// tightRadius is the corner radius of the two palettes whose source application
|
||||
// uses tighter geometry than go-loose's 16px cards.
|
||||
tightRadius = "10px"
|
||||
|
||||
// interStack is the sans stack four of the six applications ask for by name. None
|
||||
// of them load the file, so in practice this resolves to the system UI font; it
|
||||
// is kept because it is what the applications declare, and a future font load
|
||||
// should not have to touch six stylesheets.
|
||||
interStack = "'Inter', ui-sans-serif, system-ui, sans-serif"
|
||||
)
|
||||
|
||||
// scheme is one appearance's worth of literal colours.
|
||||
type scheme struct {
|
||||
Background string
|
||||
Surface string
|
||||
SurfaceRaised string
|
||||
SurfaceSunken string
|
||||
Border string
|
||||
BorderStrong string
|
||||
Text string
|
||||
TextMuted string
|
||||
TextSubtle string
|
||||
TextInverted string
|
||||
Primary string
|
||||
PrimaryHover string
|
||||
PrimaryActive string
|
||||
OnPrimary string
|
||||
Secondary string
|
||||
OnSecondary string
|
||||
Success string
|
||||
Warning string
|
||||
Danger string
|
||||
Info string
|
||||
FocusRing string
|
||||
Overlay string
|
||||
Ramp tokenengine.RampOptions
|
||||
FontSans string
|
||||
RadiusCard string
|
||||
}
|
||||
|
||||
// consolidate assembles a seeded theme from two literal schemes.
|
||||
//
|
||||
// Ramps are still generated, for the palette and status families the contract exposes
|
||||
// as scales (`--bn-palette-*`). The semantic roles are literal, because those are the
|
||||
// values the source applications actually render and inventing a ramp here would
|
||||
// change the appearance the consolidation is meant to preserve.
|
||||
func consolidate(
|
||||
slug, name, description string,
|
||||
defaultAppearance domain.Appearance,
|
||||
tags []string,
|
||||
light, dark scheme,
|
||||
) SeededTheme {
|
||||
palettes := map[string]any{
|
||||
roleBrand: tokenengine.GenerateRamp(light.Ramp),
|
||||
roleNeutral: tokenengine.GenerateRamp(neutralRamp(light.Ramp)),
|
||||
roleSuccess: tokenengine.GenerateRamp(tokenengine.RampOptions{Hue: 142, Saturation: 55, Lightness: 42, HueSpread: 10}),
|
||||
roleWarning: tokenengine.GenerateRamp(tokenengine.RampOptions{Hue: 38, Saturation: 88, Lightness: 50, HueSpread: 8}),
|
||||
roleDanger: tokenengine.GenerateRamp(tokenengine.RampOptions{Hue: 358, Saturation: 68, Lightness: 50, HueSpread: 8}),
|
||||
}
|
||||
|
||||
fontSans := light.FontSans
|
||||
if fontSans == "" {
|
||||
fontSans = interStack
|
||||
}
|
||||
typography := typeScale(fontSans, 0.875, 1.25, 1.625)
|
||||
typography["family"] = map[string]any{
|
||||
"sans": family(fontSans),
|
||||
"mono": family("ui-monospace, SFMono-Regular, Menlo, monospace"),
|
||||
"display": family(fontSans),
|
||||
}
|
||||
|
||||
shadowSet := map[string]any{
|
||||
"none": shadow("none"),
|
||||
"sm": shadow("0 1px 2px rgba(0,0,0,0.06)"),
|
||||
"md": shadow("0 6px 20px rgba(0,0,0,0.08)"),
|
||||
"lg": shadow("0 18px 48px rgba(0,0,0,0.14)"),
|
||||
"xl": shadow("0 28px 80px rgba(0,0,0,0.20)"),
|
||||
"border": shadow("inset 0 0 0 1px rgba(0,0,0,0.08)"),
|
||||
}
|
||||
|
||||
doc := assemble(palettes,
|
||||
literalSemantics(light),
|
||||
literalSemantics(dark),
|
||||
typography,
|
||||
shadowSet,
|
||||
)
|
||||
|
||||
// The transcribed corner radius becomes a real token rather than a note in a
|
||||
// struct field. A consumer writing `border-radius: var(--radius-md)` then gets
|
||||
// the source application's actual radius, which is the whole reason for copying
|
||||
// its palette rather than approximating one.
|
||||
applyCardRadius(doc, light.RadiusCard)
|
||||
|
||||
return SeededTheme{
|
||||
Slug: slug,
|
||||
Name: name,
|
||||
Description: description,
|
||||
Appearance: defaultAppearance,
|
||||
Tags: tags,
|
||||
Tokens: doc,
|
||||
}
|
||||
}
|
||||
|
||||
// applyCardRadius sets the radius scale so that its `md` step is the source
|
||||
// application's card radius, with the surrounding steps kept in proportion.
|
||||
//
|
||||
// A palette whose corners are visibly rounder or squarer than the application it came
|
||||
// from does not read as that application, and the radius is one of the first things a
|
||||
// user notices.
|
||||
func applyCardRadius(doc domain.TokenDoc, card string) {
|
||||
if card == "" {
|
||||
return
|
||||
}
|
||||
group, ok := doc["radius"].(map[string]any)
|
||||
if !ok {
|
||||
group = map[string]any{}
|
||||
doc["radius"] = group
|
||||
}
|
||||
// Proportions taken from the scale the other built-in themes use, so a
|
||||
// consolidated palette and an original one are the same shape.
|
||||
for step, factor := range map[string]string{
|
||||
"sm": "0.5",
|
||||
"md": "1",
|
||||
"lg": "1.5",
|
||||
"xl": "2",
|
||||
} {
|
||||
if step == "md" {
|
||||
group[step] = dim(card)
|
||||
continue
|
||||
}
|
||||
group[step] = dim("calc(" + card + " * " + factor + ")")
|
||||
}
|
||||
}
|
||||
|
||||
// neutralRamp derives a low-saturation neutral from a brand ramp, so a palette and its
|
||||
// greys come from one description rather than two guesses.
|
||||
func neutralRamp(brand tokenengine.RampOptions) tokenengine.RampOptions {
|
||||
return tokenengine.RampOptions{
|
||||
Hue: brand.Hue,
|
||||
Saturation: minFloat(brand.Saturation*0.18, 22),
|
||||
Lightness: minFloat(brand.Lightness*0.72, 52),
|
||||
HueSpread: 4,
|
||||
}
|
||||
}
|
||||
|
||||
// minFloat returns the smaller of two values.
|
||||
func minFloat(a, b float64) float64 {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// literalSemantics turns a scheme into the contract's semantic colour roles.
|
||||
//
|
||||
// Every role is filled explicitly. A missing role would fall back to the engine's
|
||||
// light-mode default, which for a dark-first palette is a pale colour in the middle of
|
||||
// a dark interface — a bug that is easy to miss and impossible to debug from a
|
||||
// screenshot.
|
||||
func literalSemantics(s scheme) map[string]any {
|
||||
out := map[string]any{
|
||||
"background": color(s.Background),
|
||||
"surface": color(s.Surface),
|
||||
"surface-raised": color(s.SurfaceRaised),
|
||||
"surface-sunken": color(s.SurfaceSunken),
|
||||
"border": color(s.Border),
|
||||
"border-strong": color(s.BorderStrong),
|
||||
"text": color(s.Text),
|
||||
"text-muted": color(s.TextMuted),
|
||||
"text-subtle": color(s.TextSubtle),
|
||||
"text-inverted": color(s.TextInverted),
|
||||
"primary": color(s.Primary),
|
||||
"primary-hover": color(s.PrimaryHover),
|
||||
"primary-active": color(s.PrimaryActive),
|
||||
"on-primary": color(s.OnPrimary),
|
||||
"secondary": color(s.Secondary),
|
||||
"on-secondary": color(s.OnSecondary),
|
||||
"success": color(s.Success),
|
||||
"warning": color(s.Warning),
|
||||
"danger": color(s.Danger),
|
||||
"info": color(s.Info),
|
||||
"focus-ring": color(s.FocusRing),
|
||||
"overlay": color(s.Overlay),
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// The four palettes below come from four different applications. The colours are
|
||||
// theirs, transcribed; where an application had only one appearance, the other is
|
||||
// derived by inverting the surface and text roles and keeping the accent family, which
|
||||
// is what its own stylesheet effectively does.
|
||||
|
||||
// tokyoNight is go-loose's default palette, the one its switcher opens on.
|
||||
//
|
||||
// The slug is `tokyo`, not `tokyo-night`, because that is the value go-loose already
|
||||
// writes into its data-theme attribute. Matching it is the whole point: adopting the
|
||||
// contract must not require the adopting application to change a single stored value.
|
||||
func tokyoNight() SeededTheme {
|
||||
blue := tokenengine.RampOptions{Hue: 224, Saturation: 60, Lightness: 58, HueSpread: 10}
|
||||
|
||||
return consolidate(
|
||||
"tokyo", "Tokyo Night",
|
||||
"go-loose's default palette. Low-contrast blue-grey with a bright accent; "+
|
||||
"chosen for long sessions against a terminal.",
|
||||
domain.AppearanceDark,
|
||||
[]string{appearanceDark, tagDefault, "blue", "go-loose"},
|
||||
scheme{
|
||||
Background: "#e6e7ed", Surface: white, SurfaceRaised: white,
|
||||
SurfaceSunken: "#dfe2ed", Border: "#b4b5c3", BorderStrong: "#8b8da1",
|
||||
Text: "#343b58", TextMuted: "#34548a", TextSubtle: "#4a5a80",
|
||||
TextInverted: white,
|
||||
Primary: "#0f4b6e", PrimaryHover: "#0c3d5a", PrimaryActive: "#093249",
|
||||
OnPrimary: white,
|
||||
Secondary: "#5a4a78", OnSecondary: white,
|
||||
Success: "#485e30", Warning: "#8a6a1f", Danger: "#8c4351", Info: "#2f6b8f",
|
||||
FocusRing: "#0f4b6e", Overlay: "rgba(52, 59, 88, 0.32)",
|
||||
Ramp: blue, FontSans: interStack,
|
||||
RadiusCard: cardRadius,
|
||||
},
|
||||
scheme{
|
||||
Background: "#1a1b26", Surface: "#20222f", SurfaceRaised: "#282a37",
|
||||
SurfaceSunken: "#16161e", Border: "#292e42", BorderStrong: "#3b4261",
|
||||
Text: "#c0caf5", TextMuted: "#9aa5ce", TextSubtle: "#7aa2f7",
|
||||
TextInverted: "#1a1b26",
|
||||
Primary: "#7aa2f7", PrimaryHover: "#93b1ff", PrimaryActive: "#aac7ff",
|
||||
OnPrimary: "#1a1b26",
|
||||
Secondary: "#bb9af7", OnSecondary: "#1a1b26",
|
||||
Success: "#9ece6a", Warning: "#e0af68", Danger: "#f7768e", Info: "#7dcfff",
|
||||
FocusRing: "#7aa2f7", Overlay: "rgba(0, 0, 0, 0.55)",
|
||||
Ramp: blue, FontSans: interStack,
|
||||
RadiusCard: cardRadius,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// catppuccin is go-loose's second palette, a soft pastel set.
|
||||
func catppuccin() SeededTheme {
|
||||
lavender := tokenengine.RampOptions{Hue: 232, Saturation: 62, Lightness: 62, HueSpread: 12}
|
||||
|
||||
return consolidate(
|
||||
"catppuccin", "Catppuccin",
|
||||
"go-loose's pastel palette. Softer contrast than Tokyo Night, which suits a "+
|
||||
"content-heavy screen better than a dense one.",
|
||||
domain.AppearanceDark,
|
||||
[]string{appearanceDark, "pastel", "lavender", "go-loose"},
|
||||
scheme{
|
||||
Background: "#eff1f5", Surface: white, SurfaceRaised: white,
|
||||
SurfaceSunken: "#e6e9ef", Border: "#bcc0cc", BorderStrong: "#9499b0",
|
||||
Text: "#4c4f69", TextMuted: "#5c61a8", TextSubtle: "#6c6f85",
|
||||
TextInverted: white,
|
||||
Primary: "#1e66f5", PrimaryHover: "#1a56db", PrimaryActive: "#1647b8",
|
||||
OnPrimary: white,
|
||||
Secondary: "#8839ef", OnSecondary: white,
|
||||
Success: "#40a02b", Warning: "#df8e1d", Danger: "#d20f39", Info: "#179299",
|
||||
FocusRing: "#1e66f5", Overlay: "rgba(76, 79, 105, 0.28)",
|
||||
Ramp: lavender, FontSans: interStack,
|
||||
RadiusCard: cardRadius,
|
||||
},
|
||||
scheme{
|
||||
Background: "#1e1e2e", Surface: "#181825", SurfaceRaised: "#313244",
|
||||
SurfaceSunken: "#11111b", Border: "#313244", BorderStrong: "#45475a",
|
||||
Text: "#cdd6f4", TextMuted: "#a6adc8", TextSubtle: "#9399b2",
|
||||
TextInverted: "#1e1e2e",
|
||||
Primary: "#89b4fa", PrimaryHover: "#a3c3f5", PrimaryActive: "#b8d0f6",
|
||||
OnPrimary: "#1e1e2e",
|
||||
Secondary: "#cba6f7", OnSecondary: "#1e1e2e",
|
||||
Success: "#a6e3a1", Warning: "#f9e2af", Danger: "#f38ba8", Info: "#94e2d5",
|
||||
FocusRing: "#89b4fa", Overlay: "rgba(0, 0, 0, 0.5)",
|
||||
Ramp: lavender, FontSans: interStack,
|
||||
RadiusCard: cardRadius,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// nordicMoss is go-tell's green palette, slugged `nordic` to match its own value. Its source theme is dark-only; the light
|
||||
// scheme is the inversion with the green family kept.
|
||||
func nordicMoss() SeededTheme {
|
||||
moss := tokenengine.RampOptions{Hue: 132, Saturation: 32, Lightness: 44, HueSpread: 12}
|
||||
|
||||
return consolidate(
|
||||
"nordic", "Nordic Moss",
|
||||
"go-tell's green palette. Desaturated and low-contrast; the light scheme is "+
|
||||
"derived, because the source theme is dark-only.",
|
||||
domain.AppearanceDark,
|
||||
[]string{appearanceDark, "green", "calm", "go-tell"},
|
||||
scheme{
|
||||
Background: "#e9f0e8", Surface: white, SurfaceRaised: "#f4f8f3",
|
||||
SurfaceSunken: "#dfe9de", Border: "#c2d6c4", BorderStrong: "#94a899",
|
||||
Text: "#16241c", TextMuted: "#3b5645", TextSubtle: "#588157",
|
||||
TextInverted: white,
|
||||
Primary: "#2e4435", PrimaryHover: "#25392d", PrimaryActive: "#1a2820",
|
||||
OnPrimary: "#e9f0e8",
|
||||
Secondary: "#6f894e", OnSecondary: white,
|
||||
Success: "#3f6b46", Warning: "#8a7434", Danger: "#a1453f", Info: "#3a6a70",
|
||||
FocusRing: "#2e4435", Overlay: "rgba(22, 36, 28, 0.28)",
|
||||
Ramp: moss, FontSans: interStack,
|
||||
RadiusCard: tightRadius,
|
||||
},
|
||||
scheme{
|
||||
Background: "#121c16", Surface: "#1e3025", SurfaceRaised: "#25392d",
|
||||
SurfaceSunken: "#0e1712", Border: "#2e4435", BorderStrong: "#3b5645",
|
||||
Text: "#e9f0e8", TextMuted: "#a3c9a8", TextSubtle: "#8fa193",
|
||||
TextInverted: "#121c16",
|
||||
Primary: "#a3c9a8", PrimaryHover: "#b8d8bb", PrimaryActive: "#c9e2cb",
|
||||
OnPrimary: "#121c16",
|
||||
Secondary: "#8fbc8f", OnSecondary: "#121c16",
|
||||
Success: "#8fbc8f", Warning: "#e2c044", Danger: "#e07a72", Info: "#7fb4ca",
|
||||
FocusRing: "#a3c9a8", Overlay: "rgba(0, 0, 0, 0.52)",
|
||||
Ramp: moss, FontSans: interStack,
|
||||
RadiusCard: tightRadius,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// deepSpace is go-tell's `obsidian` palette, and the one that most needs a light
|
||||
// scheme: its source is a near-black space theme, so an untouched inversion would be
|
||||
// unusable.
|
||||
func deepSpace() SeededTheme {
|
||||
sky := tokenengine.RampOptions{Hue: 199, Saturation: 88, Lightness: 58, HueSpread: 12}
|
||||
|
||||
return consolidate(
|
||||
"obsidian", "Deep Space Obsidian",
|
||||
"go-tell's near-black blue palette. The light scheme is authored rather than "+
|
||||
"inverted, because the source is a dark-first space theme.",
|
||||
domain.AppearanceDark,
|
||||
[]string{appearanceDark, "blue", "space", "go-tell"},
|
||||
scheme{
|
||||
Background: "#f1f5f9", Surface: white, SurfaceRaised: "#f8fafc",
|
||||
SurfaceSunken: "#e8eef5", Border: "#d3dce6", BorderStrong: "#a8b6c6",
|
||||
Text: "#0f172a", TextMuted: "#475569", TextSubtle: "#64748b",
|
||||
TextInverted: "#f8fafc",
|
||||
Primary: "#0284c7", PrimaryHover: "#0369a1", PrimaryActive: "#075985",
|
||||
OnPrimary: white,
|
||||
Secondary: "#1e293b", OnSecondary: "#f8fafc",
|
||||
Success: "#15803d", Warning: "#b45309", Danger: "#b91c1c", Info: "#0e7490",
|
||||
FocusRing: "#0284c7", Overlay: "rgba(15, 23, 42, 0.3)",
|
||||
Ramp: sky, FontSans: interStack,
|
||||
RadiusCard: tightRadius,
|
||||
},
|
||||
scheme{
|
||||
Background: "#060709", Surface: "#0f172a", SurfaceRaised: "#151d2a",
|
||||
SurfaceSunken: "#020617", Border: "#1e293b", BorderStrong: "#334155",
|
||||
Text: "#e2e8f0", TextMuted: "#94a3b8", TextSubtle: "#64748b",
|
||||
TextInverted: "#060709",
|
||||
Primary: "#38bdf8", PrimaryHover: "#7dd3fc", PrimaryActive: "#bae6fd",
|
||||
OnPrimary: "#060709",
|
||||
Secondary: "#60a5fa", OnSecondary: "#060709",
|
||||
Success: "#4ade80", Warning: "#fbbf24", Danger: "#f87171", Info: "#22d3ee",
|
||||
FocusRing: "#38bdf8", Overlay: "rgba(0, 0, 0, 0.6)",
|
||||
Ramp: sky, FontSans: interStack,
|
||||
RadiusCard: tightRadius,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// urpiStandard is go-guess's palette, which is the only light-first application of the
|
||||
// six and therefore the one whose light scheme is the authoritative one.
|
||||
func urpiStandard() SeededTheme {
|
||||
cyan := tokenengine.RampOptions{Hue: 190, Saturation: 78, Lightness: 40, HueSpread: 10}
|
||||
|
||||
return consolidate(
|
||||
"urpi-standard", "urpi Standard",
|
||||
"go-guess's palette: a cyan accent and lime highlight on a cool grey. The "+
|
||||
"light scheme is authoritative, being the application's only one.",
|
||||
domain.AppearanceLight,
|
||||
[]string{"light", tagDefault, "cyan", "go-guess"},
|
||||
scheme{
|
||||
Background: "#f3f7f8", Surface: white, SurfaceRaised: white,
|
||||
SurfaceSunken: "#edf2f3", Border: "#dce5e8", BorderStrong: "#c2d2d6",
|
||||
Text: "#142b3a", TextMuted: "#526872", TextSubtle: "#78909c",
|
||||
TextInverted: white,
|
||||
Primary: "#007f98", PrimaryHover: "#006b81", PrimaryActive: "#00586a",
|
||||
OnPrimary: white,
|
||||
Secondary: "#d9ef4d", OnSecondary: "#0b573c",
|
||||
Success: "#13704d", Warning: "#925a09", Danger: "#934141", Info: "#087187",
|
||||
FocusRing: "#007f98", Overlay: "rgba(14, 42, 56, 0.34)",
|
||||
Ramp: cyan, FontSans: "'DM Sans', Inter, ui-sans-serif, system-ui, sans-serif",
|
||||
RadiusCard: cardRadius,
|
||||
},
|
||||
scheme{
|
||||
Background: "#081c2c", Surface: "#0e2a3f", SurfaceRaised: "#123449",
|
||||
SurfaceSunken: "#04131f", Border: "#1d4258", BorderStrong: "#2c5f7a",
|
||||
Text: "#e3ebed", TextMuted: "#a9bec8", TextSubtle: "#82949d",
|
||||
TextInverted: "#081c2c",
|
||||
Primary: "#00a9c8", PrimaryHover: "#33bcd6", PrimaryActive: "#66cde0",
|
||||
OnPrimary: "#04131f",
|
||||
Secondary: "#d9ef4d", OnSecondary: "#0b573c",
|
||||
Success: "#16a274", Warning: "#eda83c", Danger: "#e6988c", Info: "#43c99c",
|
||||
FocusRing: "#00a9c8", Overlay: "rgba(0, 0, 0, 0.55)",
|
||||
Ramp: cyan, FontSans: "'DM Sans', Inter, ui-sans-serif, system-ui, sans-serif",
|
||||
RadiusCard: cardRadius,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// tomorrow is go-loose's third palette: a warm grey with a muted teal.
|
||||
func tomorrow() SeededTheme {
|
||||
warm := tokenengine.RampOptions{Hue: 40, Saturation: 8, Lightness: 42, HueSpread: 4}
|
||||
teal := tokenengine.RampOptions{Hue: 178, Saturation: 34, Lightness: 40, HueSpread: 8}
|
||||
|
||||
return consolidate(
|
||||
"tomorrow", "Tomorrow",
|
||||
"go-loose's warm grey palette. The least saturated of the four, and the "+
|
||||
"easiest to read for long periods.",
|
||||
domain.AppearanceDark,
|
||||
[]string{appearanceDark, "warm", "muted", "go-loose"},
|
||||
scheme{
|
||||
Background: "#f5f5f5", Surface: white, SurfaceRaised: white,
|
||||
SurfaceSunken: "#e8e8e8", Border: "#c9c9c9", BorderStrong: "#a3a3a3",
|
||||
Text: "#4d4d4c", TextMuted: "#6e6e6c", TextSubtle: "#8a8a88",
|
||||
TextInverted: white,
|
||||
Primary: "#3e999f", PrimaryHover: "#348389", PrimaryActive: "#2b6d72",
|
||||
OnPrimary: white,
|
||||
Secondary: "#8959a8", OnSecondary: white,
|
||||
Success: "#718c00", Warning: "#b58900", Danger: "#c82829", Info: "#3e999f",
|
||||
FocusRing: "#3e999f", Overlay: "rgba(77, 77, 76, 0.3)",
|
||||
Ramp: teal, FontSans: interStack,
|
||||
RadiusCard: cardRadius,
|
||||
},
|
||||
scheme{
|
||||
Background: "#1d1f21", Surface: "#282a2e", SurfaceRaised: "#373b41",
|
||||
SurfaceSunken: "#1a1c1e", Border: "#4d5057", BorderStrong: "#6b6f77",
|
||||
Text: "#c5c8c6", TextMuted: "#a0a4a2", TextSubtle: "#81a2be",
|
||||
TextInverted: "#1d1f21",
|
||||
Primary: "#8abeb7", PrimaryHover: "#a5d1cb", PrimaryActive: "#bcdfd9",
|
||||
OnPrimary: "#1d1f21",
|
||||
Secondary: "#b294bb", OnSecondary: "#1d1f21",
|
||||
Success: "#b5bd68", Warning: "#e0af68", Danger: "#cc6666", Info: "#81a2be",
|
||||
FocusRing: "#8abeb7", Overlay: "rgba(0, 0, 0, 0.52)",
|
||||
Ramp: warm, FontSans: interStack,
|
||||
RadiusCard: cardRadius,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// kanagawa is go-loose's fourth palette: a warm paper light scheme and a stone dark one.
|
||||
func kanagawa() SeededTheme {
|
||||
wave := tokenengine.RampOptions{Hue: 28, Saturation: 26, Lightness: 56, HueSpread: 10}
|
||||
stone := tokenengine.RampOptions{Hue: 20, Saturation: 10, Lightness: 46, HueSpread: 6}
|
||||
|
||||
return consolidate(
|
||||
"kanagawa", "Kanagawa",
|
||||
"go-loose's paper palette. A warm off-white light scheme, which is the "+
|
||||
"warmest surface in the set.",
|
||||
domain.AppearanceLight,
|
||||
[]string{"light", "warm", "paper", "go-loose"},
|
||||
scheme{
|
||||
Background: "#f2ecde", Surface: paperLight, SurfaceRaised: paperLight,
|
||||
SurfaceSunken: "#e7dba9", Border: "#c8c093", BorderStrong: "#a89b6e",
|
||||
Text: "#545464", TextMuted: "#5e5e70", TextSubtle: "#78788c",
|
||||
TextInverted: paperLight,
|
||||
Primary: "#4d7f8c", PrimaryHover: "#406d78", PrimaryActive: "#345c65",
|
||||
OnPrimary: paperLight,
|
||||
Secondary: "#624c83", OnSecondary: paperLight,
|
||||
Success: "#6f894e", Warning: "#9a7d2e", Danger: "#c34043", Info: "#4d7f8c",
|
||||
FocusRing: "#4d7f8c", Overlay: "rgba(84, 84, 100, 0.3)",
|
||||
Ramp: stone, FontSans: interStack,
|
||||
RadiusCard: cardRadius,
|
||||
},
|
||||
scheme{
|
||||
Background: "#1f1f28", Surface: "#2a2a37", SurfaceRaised: "#363646",
|
||||
SurfaceSunken: "#191921", Border: "#54546d", BorderStrong: "#6b6b85",
|
||||
Text: "#dcd7ba", TextMuted: "#b4b098", TextSubtle: "#a8a28c",
|
||||
TextInverted: "#1f1f28",
|
||||
Primary: "#7fb4ca", PrimaryHover: "#98c4d6", PrimaryActive: "#b0d2e0",
|
||||
OnPrimary: "#1f1f28",
|
||||
Secondary: "#957fb8", OnSecondary: "#1f1f28",
|
||||
Success: "#98bb6c", Warning: "#e0c07a", Danger: "#e46876", Info: "#7fb4ca",
|
||||
FocusRing: "#7fb4ca", Overlay: "rgba(0, 0, 0, 0.5)",
|
||||
Ramp: wave, FontSans: interStack,
|
||||
RadiusCard: cardRadius,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// cyberpunk is go-tell's default palette: a near-black violet field with a hot pink
|
||||
// and a bright cyan.
|
||||
//
|
||||
// It is the one palette in the set whose identity is two accents rather than one, and
|
||||
// that is why it is expressed with two status roles doing unusual work: pink carries
|
||||
// the brand, cyan carries interaction. Keeping pink on `--bn-accent` would lose the
|
||||
// pink-versus-cyan distinction that the whole theme is built on, so the secondary
|
||||
// carries cyan instead and the pair reads in the order the design intends.
|
||||
func cyberpunk() SeededTheme {
|
||||
violet := tokenengine.RampOptions{Hue: 288, Saturation: 72, Lightness: 44, HueSpread: 20}
|
||||
|
||||
return consolidate(
|
||||
"cyberpunk", "Cyberpunk",
|
||||
"go-tell's default palette. A hot-pink and cyan pair on near-black violet, "+
|
||||
"which is the one palette here built on two accents rather than one.",
|
||||
domain.AppearanceDark,
|
||||
[]string{appearanceDark, tagDefault, "pink", "cyan", "go-tell"},
|
||||
scheme{
|
||||
Background: "#f2e8ee", Surface: "#ffffff", SurfaceRaised: "#fdf5f9",
|
||||
SurfaceSunken: "#e9dde5", Border: "#c9b3c0", BorderStrong: "#a68b9c",
|
||||
Text: "#2a1226", TextMuted: "#5c4457", TextSubtle: "#7f6577",
|
||||
TextInverted: "#f5e0e8",
|
||||
Primary: "#c2185b", PrimaryHover: "#a5144d", PrimaryActive: "#8c1042",
|
||||
OnPrimary: white,
|
||||
// Cyan as the secondary: see the note above.
|
||||
Secondary: "#00838f", OnSecondary: white,
|
||||
Success: "#2e7d32", Warning: "#c77800", Danger: "#c62828", Info: "#0277bd",
|
||||
FocusRing: "#c2185b", Overlay: "rgba(42, 18, 38, 0.5)",
|
||||
Ramp: violet, FontSans: interStack, RadiusCard: tightRadius,
|
||||
},
|
||||
scheme{
|
||||
Background: "#120826", Surface: "#1b1035", SurfaceRaised: "#22153d",
|
||||
SurfaceSunken: "#0c0519", Border: "#3d2366", BorderStrong: "#4a2d7a",
|
||||
Text: "#f5e0e8", TextMuted: "#a6adc8", TextSubtle: "#7f849c",
|
||||
TextInverted: "#120826",
|
||||
// The source has no separate hover or active step; these are the two
|
||||
// lighter pinks it uses on hover and on the cursor.
|
||||
Primary: "#ff2a85", PrimaryHover: "#ff4d9a", PrimaryActive: "#ff6b9d",
|
||||
OnPrimary: "#120826",
|
||||
// Cyan as the secondary, so a consumer's --bn-secondary reaches the
|
||||
// interaction colour the theme is known for.
|
||||
Secondary: "#00f0ff", OnSecondary: "#120826",
|
||||
Success: "#00e5a0", Warning: "#ffd166", Danger: "#ef233c", Info: "#00f0ff",
|
||||
FocusRing: "#00f0ff", Overlay: "rgba(0, 0, 0, 0.62)",
|
||||
Ramp: violet, FontSans: interStack, RadiusCard: tightRadius,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// terminalRetro is go-tell's green-on-black palette.
|
||||
//
|
||||
// Two of its traits are not colours and cannot be expressed as tokens: it forces a
|
||||
// monospace face on every element, and it adds a text glow. Both are recorded in the
|
||||
// description and left in the application's own stylesheet, because a token is a
|
||||
// value and these are rules.
|
||||
func terminalRetro() SeededTheme {
|
||||
green := tokenengine.RampOptions{Hue: 138, Saturation: 100, Lightness: 45, HueSpread: 16}
|
||||
|
||||
return consolidate(
|
||||
"terminal", "Terminal Retro",
|
||||
"go-tell's green-on-black palette. The source theme also forces a monospace "+
|
||||
"face on every element and adds a text glow; those are rules rather than "+
|
||||
"values, so they stay in the application's stylesheet.",
|
||||
domain.AppearanceDark,
|
||||
[]string{"dark", "terminal", "mono", "green", "go-tell"},
|
||||
scheme{
|
||||
Background: "#e8f5e9", Surface: "#ffffff", SurfaceRaised: "#f2fbf3",
|
||||
SurfaceSunken: "#dcecdc", Border: "#a8d8ad", BorderStrong: "#7fbf86",
|
||||
Text: "#041404", TextMuted: "#1e5c22", TextSubtle: "#3d7a42",
|
||||
TextInverted: "#041404",
|
||||
Primary: "#007a12", PrimaryHover: "#006410", PrimaryActive: "#004e0d",
|
||||
OnPrimary: "#dcfce0",
|
||||
Secondary: "#7a5c00", OnSecondary: "#fff8dc",
|
||||
Success: "#00a32b", Warning: "#8a6d00", Danger: "#b30000", Info: "#007a12",
|
||||
FocusRing: "#00a32b", Overlay: "rgba(4, 20, 4, 0.55)",
|
||||
Ramp: green,
|
||||
FontSans: "'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace",
|
||||
RadiusCard: "4px",
|
||||
},
|
||||
scheme{
|
||||
Background: "#040804", Surface: "#081608", SurfaceRaised: "#0e1a0e",
|
||||
SurfaceSunken: "#020402", Border: "#00aa44", BorderStrong: "#00ff66",
|
||||
Text: "#00ff66", TextMuted: "#33ff33", TextSubtle: "#00aa44",
|
||||
TextInverted: "#040804",
|
||||
// The source's brightest green is its interactive colour, and its mid green
|
||||
// is the hover step.
|
||||
Primary: "#00ff66", PrimaryHover: "#33ff33", PrimaryActive: "#00dd55",
|
||||
OnPrimary: "#040804",
|
||||
// The Mac traffic-light yellow the source uses in its window chrome.
|
||||
Secondary: "#ffcc00", OnSecondary: "#261e00",
|
||||
Success: "#00ff66", Warning: "#ffcc00", Danger: "#ff3333", Info: "#00aa44",
|
||||
FocusRing: "#00ff66", Overlay: "rgba(0, 0, 0, 0.7)",
|
||||
Ramp: green,
|
||||
FontSans: "'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace",
|
||||
RadiusCard: "4px",
|
||||
},
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue