/** * Orchis GTK Theme - Complete Design Token System * ================================================ * Extracted from: https://github.com/vinceliuice/Orchis-theme * Based on Google Material Design with custom Orchis adaptations * * This file provides a complete CSS/design token system for a Next.js * web application, faithfully representing the Orchis GTK theme. */ // ============================================================================ // 1. COLOR PALETTES - ALL VARIANTS // ============================================================================ /** * --- MATERIAL DESIGN BASE PALETTE --- * Orchis uses the standard Material Design 2014 color palette as its foundation. * Each color has shades from 50 (lightest) to 900 (darkest) plus accent variants. */ export const materialPalette = { red: { 50: "#FFEBEE", 100: "#FFCDD2", 200: "#EF9A9A", 300: "#E57373", 400: "#EF5350", 500: "#F44336", 600: "#E53935", 700: "#D32F2F", 800: "#C62828", 900: "#B71C1C", a100: "#FF8A80", a200: "#FF5252", a400: "#FF1744", a700: "#D50000", }, pink: { 50: "#FCE4EC", 100: "#F8BBD0", 200: "#F48FB1", 300: "#F06292", 400: "#EC407A", 500: "#E91E63", 600: "#D81B60", 700: "#C2185B", 800: "#AD1457", 900: "#880E4F", a100: "#FF80AB", a200: "#FF4081", a400: "#F50057", a700: "#C51162", }, purple: { 50: "#F3E5F5", 100: "#E1BEE7", 200: "#CE93D8", 300: "#BA68C8", 400: "#AB47BC", 500: "#9C27B0", 600: "#8E24AA", 700: "#7B1FA2", 800: "#6A1B9A", 900: "#4A148C", a100: "#EA80FC", a200: "#E040FB", a400: "#D500F9", a700: "#AA00FF", }, deepPurple: { 50: "#EDE7F6", 100: "#D1C4E9", 200: "#B39DDB", 300: "#9575CD", 400: "#7E57C2", 500: "#673AB7", 600: "#5E35B1", 700: "#512DA8", 800: "#4527A0", 900: "#311B92", a100: "#B388FF", a200: "#7C4DFF", a400: "#651FFF", a700: "#6200EA", }, indigo: { 50: "#E8EAF6", 100: "#C5CAE9", 200: "#9FA8DA", 300: "#7986CB", 400: "#5C6BC0", 500: "#3F51B5", 600: "#3949AB", 700: "#303F9F", 800: "#283593", 900: "#1A237E", a100: "#8C9EFF", a200: "#536DFE", a400: "#3D5AFE", a700: "#304FFE", }, blue: { 50: "#E3F2FD", 100: "#BBDEFB", 200: "#90CAF9", 300: "#64B5F6", 400: "#42A5F5", 500: "#2196F3", 600: "#1E88E5", 700: "#1976D2", 800: "#1565C0", 900: "#0D47A1", a100: "#82B1FF", a200: "#448AFF", a400: "#2979FF", a700: "#2962FF", }, teal: { 50: "#E0F2F1", 100: "#B2DFDB", 200: "#80CBC4", 300: "#4DB6AC", 400: "#26A69A", 500: "#009688", 600: "#00897B", 700: "#00796B", 800: "#00695C", 900: "#004D40", a100: "#A7FFEB", a200: "#64FFDA", a400: "#1DE9B6", a700: "#00BFA5", }, green: { 50: "#E8F5E9", 100: "#C8E6C9", 200: "#A5D6A7", 300: "#81C784", 400: "#66BB6A", 500: "#4CAF50", 600: "#43A047", 700: "#388E3C", 800: "#2E7D32", 900: "#1B5E20", a100: "#B9F6CA", a200: "#69F0AE", a400: "#00E676", a700: "#00C853", }, yellow: { 50: "#FFFDE7", 100: "#FFF9C4", 200: "#FFF59D", 300: "#FFF176", 400: "#FFEE58", 500: "#FFEB3B", 600: "#FDD835", 700: "#FBC02D", 800: "#F9A825", 900: "#F57F17", a100: "#FFFF8D", a200: "#FFFF00", a400: "#FFEA00", a700: "#FFD600", }, orange: { 50: "#FFF3E0", 100: "#FFE0B2", 200: "#FFCC80", 300: "#FFB74D", 400: "#FFA726", 500: "#FF9800", 600: "#FB8C00", 700: "#F57C00", 800: "#EF6C00", 900: "#E65100", a100: "#FFD180", a200: "#FFAB40", a400: "#FF9100", a700: "#FF6D00", }, grey: { 50: "#FAFAFA", 100: "#F5F5F5", 200: "#EEEEEE", 300: "#E0E0E0", 400: "#BDBDBD", 500: "#9E9E9E", 600: "#757575", 700: "#616161", 800: "#424242", 900: "#212121", }, blueGrey: { 50: "#ECEFF1", 100: "#CFD8DC", 200: "#B0BEC5", 300: "#90A4AE", 400: "#78909C", 500: "#607D8B", 600: "#546E7A", 700: "#455A64", 800: "#37474F", 900: "#263238", }, } as const; /** * --- ORCHIS CUSTOM GREY SCALE --- * Orchis defines a more granular grey scale (050 through 950) than * standard Material Design. These are used for backgrounds and surfaces. */ export const orchisGrey = { "050": "#FAFAFA", "100": "#F2F2F2", "150": "#EEEEEE", "200": "#DDDDDD", "250": "#CCCCCC", "300": "#BFBFBF", "350": "#A0A0A0", "400": "#9E9E9E", "450": "#868686", "500": "#727272", "550": "#555555", "600": "#464646", "650": "#3C3C3C", "700": "#2C2C2C", "750": "#242424", "800": "#212121", "850": "#121212", "900": "#0F0F0F", "950": "#030303", } as const; /** * --- ACCENT COLOR VARIANTS --- * Each accent has a "light" variant (used on dark backgrounds) * and a "dark" variant (used on light backgrounds). * * The DEFAULT theme color is Blue (default). */ export const accentColors = { default: { // Blue light: "#3281EA", // used on dark backgrounds dark: "#1A73E8", // used on light backgrounds }, purple: { light: "#BA68C8", dark: "#AB47BC", }, pink: { light: "#F06292", dark: "#EC407A", }, red: { light: "#F44336", dark: "#E53935", }, orange: { light: "#FB8C00", dark: "#F57C00", }, yellow: { light: "#FBC02D", dark: "#FFD600", }, green: { light: "#66BB6A", dark: "#4CAF50", }, teal: { light: "#4DB6AC", dark: "#009688", }, grey: { light: "#DDDDDD", // $grey-200 for dark mode dark: "#464646", // $grey-600 for light mode }, } as const; /** Success/sea green used for checkmarks and success states */ export const successColors = { light: "#81C995", dark: "#0F9D58", } as const; /** * --- THEME TOKENS: LIGHT MODE --- * Resolved color values for the light color scheme. * Primary defaults to Blue accent ($blue-dark = #1A73E8). */ export const lightTheme = { // Primary accent (default = blue) primary: "#1A73E8", // Backgrounds background: "#F2F2F2", // grey-100 = background(c) surface: "#FFFFFF", // white = background(a) => surface base: "#FFFFFF", // white = background(a) => base baseAlt: "#FAFAFA", // grey-050 = background(b) => base-alt // Text on background text: { primary: "rgba(0, 0, 0, 0.87)", secondary: "rgba(0, 0, 0, 0.6)", disabled: "rgba(0, 0, 0, 0.38)", secondaryDisabled: "rgba(0, 0, 0, 0.26)", }, // Text on primary (white text on blue bg) onPrimary: { primary: "#FFFFFF", secondary: "rgba(255, 255, 255, 0.7)", disabled: "rgba(255, 255, 255, 0.5)", }, // Semantic colors warning: "#FFD600", // $yellow-dark error: "#E53935", // $red-dark success: "#0F9D58", // $sea-dark link: "#1A73E8", // same as primary linkVisited: "#AB47BC", // $purple-dark // Borders and dividers border: "rgba(0, 0, 0, 0.12)", solidBorder: "#E2E2E2", // darken($background, 8%) divider: "rgba(0, 0, 0, 0.12)", frame: "rgba(0, 0, 0, 0.1)", // Overlay states (used on currentColor) overlay: { normal: "rgba(0, 0, 0, 0.05)", // 5% opacity hover: "rgba(0, 0, 0, 0.08)", // 8% opacity focus: "rgba(0, 0, 0, 0.08)", // 8% opacity focusHover: "rgba(0, 0, 0, 0.16)", // 16% opacity active: "rgba(0, 0, 0, 0.12)", // 12% opacity checked: "rgba(0, 0, 0, 0.10)", // 10% opacity selected: "rgba(0, 0, 0, 0.06)", // 6% opacity }, // Track (for sliders, switches) track: "rgba(0, 0, 0, 0.26)", trackDisabled: "rgba(0, 0, 0, 0.15)", // Fill (subtle backgrounds) fill: "rgba(0, 0, 0, 0.04)", secondaryFill: "rgba(0, 0, 0, 0.08)", // Tooltip tooltip: "rgba(0, 0, 0, 0.9)", // dark tooltip on light // Panel/titlebar titlebar: "#FFFFFF", // background(a) when topbar=light titlebarBackdrop: "#FAFAFA", // Window buttons (macOS style) buttonClose: "#fd5f51", buttonMaximize: "#38c76a", buttonMinimize: "#fdbe04", // Popover/menu popover: "#FFFFFF", // Sidebar sidebar: "#FAFAFA", // $base-alt } as const; /** * --- THEME TOKENS: DARK MODE --- * Resolved color values for the dark color scheme. * Primary defaults to Blue accent ($blue-light = #3281EA). */ export const darkTheme = { // Primary accent (default = blue) primary: "#3281EA", // Backgrounds background: "#212121", // grey-800 = background(e) surface: "#3C3C3C", // grey-650 = background(h) => surface base: "#2C2C2C", // grey-700 = background(g) => base baseAlt: "#242424", // grey-750 = background(f) => base-alt // Text on dark background text: { primary: "#FFFFFF", secondary: "rgba(255, 255, 255, 0.7)", disabled: "rgba(255, 255, 255, 0.5)", secondaryDisabled: "rgba(255, 255, 255, 0.3)", }, // Text on primary (white text on blue bg) onPrimary: { primary: "#FFFFFF", secondary: "rgba(255, 255, 255, 0.7)", disabled: "rgba(255, 255, 255, 0.5)", }, // Semantic colors warning: "#FBC02D", // $yellow-light error: "#F44336", // $red-light success: "#81C995", // $sea-light link: "#3281EA", // same as primary linkVisited: "#BA68C8", // $purple-light // Borders and dividers border: "rgba(255, 255, 255, 0.12)", solidBorder: "#3D3D3D", // lighten($background, 12%) divider: "rgba(255, 255, 255, 0.12)", frame: "rgba(0, 0, 0, 0.25)", // Overlay states overlay: { normal: "rgba(255, 255, 255, 0.05)", hover: "rgba(255, 255, 255, 0.08)", focus: "rgba(255, 255, 255, 0.08)", focusHover: "rgba(255, 255, 255, 0.16)", active: "rgba(255, 255, 255, 0.12)", checked: "rgba(255, 255, 255, 0.10)", selected: "rgba(255, 255, 255, 0.06)", }, // Track track: "rgba(255, 255, 255, 0.3)", trackDisabled: "rgba(255, 255, 255, 0.15)", // Fill fill: "rgba(255, 255, 255, 0.04)", secondaryFill: "rgba(255, 255, 255, 0.08)", // Tooltip tooltip: "rgba(0, 0, 0, 0.9)", // Panel/titlebar (dark topbar) titlebar: "#2C2C2C", // background(g) titlebarBackdrop: "#3C3C3C", // Window buttons buttonClose: "#fd5f51", buttonMaximize: "#38c76a", buttonMinimize: "#fdbe04", // Popover/menu popover: "#212121", // background(e) // Sidebar sidebar: "#242424", // $base-alt } as const; /** * --- BLACK VARIANT (tweaks: --black) --- * Full black backgrounds for OLED-friendly dark mode. */ export const blackVariant = { background: "#000000", // $black surface: "#121212", // grey-850 base: "#0F0F0F", // grey-900 baseAlt: "#030303", // grey-950 } as const; /** * --- NORD COLOR SCHEME VARIANT --- * Activated with: --tweaks nord */ export const nordPalette = { nord0: "#2e3440", nord1: "#3b4252", nord2: "#434c5e", nord3: "#4c566a", nord4: "#d8dee9", nord5: "#e5e9f0", nord6: "#eceff4", nord7: "#8fbcbb", nord8: "#88c0d0", nord9: "#81a1c1", nord10: "#5e81ac", nord11: "#bf616a", nord12: "#d08770", nord13: "#ebcb8b", nord14: "#a3be8c", nord15: "#b48ead", } as const; export const nordAccents = { default: { light: "#89a3c2", dark: "#5e81ac" }, purple: { light: "#c89dbf", dark: "#b57daa" }, pink: { light: "#dc98b1", dark: "#cd7092" }, red: { light: "#d4878f", dark: "#c35b65" }, orange: { light: "#dca493", dark: "#d08770" }, yellow: { light: "#eac985", dark: "#e4b558" }, green: { light: "#a0c082", dark: "#82ac5d" }, teal: { light: "#83b9b8", dark: "#63a6a5" }, grey: { light: "#d9dce3", dark: "#3a4150" }, } as const; export const nordGrey = { "050": "#f8fafc", "100": "#f0f1f4", "150": "#eaecf0", "200": "#d9dce3", "250": "#c4c9d4", "300": "#b5bcc9", "350": "#929cb0", "400": "#8e99ae", "450": "#74819a", "500": "#616d85", "550": "#464f62", "600": "#3a4150", "650": "#333a47", "700": "#242932", "750": "#1e222a", "800": "#1c1f26", "850": "#0f1115", "900": "#0d0e11", "950": "#020203", } as const; /** * --- DRACULA COLOR SCHEME VARIANT --- * Activated with: --tweaks dracula */ export const draculaAccents = { default: { light: "#6272a4", dark: "#5d70ac" }, purple: { light: "#bd93f9", dark: "#a679ec" }, pink: { light: "#ff79c6", dark: "#f04cab" }, red: { light: "#ff5555", dark: "#f44d4d" }, orange: { light: "#ffb86c", dark: "#f8a854" }, yellow: { light: "#f1fa8c", dark: "#e8f467" }, green: { light: "#50fa7b", dark: "#4be772" }, teal: { light: "#50fae9", dark: "#20eed9" }, grey: { light: "#d9dae3", dark: "#3c3f51" }, } as const; export const draculaGrey = { "050": "#f9f9fb", "100": "#f0f1f4", "150": "#ebecf1", "200": "#d9dae3", "250": "#c4c7d4", "300": "#b5b8c9", "350": "#9397af", "400": "#8f94ad", "450": "#757a99", "500": "#626784", "550": "#474b61", "600": "#3c3f51", "650": "#343746", "700": "#242632", "750": "#1f2029", "800": "#1c1e26", "850": "#0f1015", "900": "#0d0d11", "950": "#020203", } as const; // ============================================================================ // 2. TYPOGRAPHY // ============================================================================ export const typography = { /** Primary font stack - Orchis prefers M+ 1c and Roboto */ fontFamily: '"M+ 1c", Roboto, Cantarell, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', /** For large headings, Roboto is preferred first */ largeFontFamily: 'Roboto, "M+ 1c", Cantarell, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', /** Root font size */ rootFontSize: "14px", rootFontSizeCompact: "13px", /** Subheading font size */ subheadingSize: "16px", subheadingSizeCompact: "15px", /** * Typography scale (from GTK4 type classes) * Maps to CSS utility classes */ scale: { largeTitle: { weight: 300, size: "24pt" }, // .large-title title1: { weight: 800, size: "20pt" }, // .title-1 title2: { weight: 800, size: "15pt" }, // .title-2 title3: { weight: 700, size: "15pt" }, // .title-3 title4: { weight: 700, size: "13pt" }, // .title-4 heading: { weight: 700, size: "11pt" }, // .heading body: { weight: 400, size: "11pt" }, // .body caption: { weight: 400, size: "9pt" }, // .caption captionHeading: { weight: 700, size: "9pt" }, // .caption-heading }, /** Button text weight */ buttonWeight: 500, /** Tab text weight */ tabWeight: 500, /** Sidebar selected item weight */ sidebarSelectedWeight: 500, } as const; // ============================================================================ // 3. BORDER RADIUS / SHAPE LANGUAGE // ============================================================================ /** * Orchis uses a **rounded** design language by default. * $default_corner = 12px (configurable via --round flag from 2px to 15px). * * All other radii are derived from this base value. */ export const borderRadius = { /** Default corner radius (12px) */ default: 12, /** Window radius: $default_corner + $space-size = 12 + 6 = 18px */ window: 18, /** Standard corner radius (for buttons, entries, etc.): same as default = 12px * In compact mode: max(0, $default_corner - 2px) = 10px */ corner: 12, cornerCompact: 10, /** Material radius: $default_corner / 2 + 4 = 10px */ material: 10, /** Menu/popover radius: $default_corner / 4 + $space-size + 2 = 3 + 6 + 2 = 11px */ menu: 11, /** Popup radius: $default_corner + $space-size * 2 - 4 = 12 + 12 - 4 = 20px */ popup: 20, /** Menu item radius: $default_corner / 4 + 2 = 5px */ menuItem: 5, /** Card/boxed list radius: $corner-radius - 1px = 11px */ card: 11, /** Circular/pill radius (for pills, circular buttons) */ circular: 9999, /** Tooltip radius: $corner-radius / 2 = 6px */ tooltip: 6, /** Toolbar button radius: $corner-radius / 2 = 6px */ toolbarButton: 6, /** Panel corner radius (gnome-shell): 0 */ panel: 0, } as const; // ============================================================================ // 4. SPACING SYSTEM // ============================================================================ /** * Orchis uses a base spacing unit of 6px (4px in compact mode). * Margin is 4px (2px in compact). * Sizes scale consistently based on these units. */ export const spacing = { /** Base spacing unit: 6px */ space: 6, spaceCompact: 4, /** Base margin: 4px */ margin: 4, marginCompact: 2, /** Component sizes */ small: 24, // 24px (compact: 22px) - small buttons, icons smallCompact: 22, medium: 36, // 36px (compact: 32px) - buttons, entries, tabs mediumCompact: 32, large: 48, // 48px (compact: 40px) - large buttons, headers largeCompact: 40, /** Menu item height: 28px (compact: 24px) */ menuItem: 28, menuItemCompact: 24, /** Bar size (progress bars, level bars): 6px */ bar: 6, /** Icon sizes */ iconBase: 16, iconMedium: 24, // 16 * 1.5 iconLarge: 32, // 16 * 2 /** Derived spacing values frequently used */ xs: 2, // half margin sm: 4, // margin md: 6, // space lg: 12, // space * 2 xl: 18, // space * 3 xxl: 24, // space * 4 } as const; // ============================================================================ // 5. COMPONENT STYLING PATTERNS // ============================================================================ // --- 5.1 BUTTONS --- export const button = { /** Standard button */ standard: { minHeight: 24, minWidth: 24, // padding: (medium-size - 24) / 2 = (36-24)/2 = 6px padding: "6px", borderRadius: 12, // $corner-radius fontWeight: 500, transition: "all 75ms cubic-bezier(0.0, 0.0, 0.2, 1)", }, /** States for standard button (light mode) */ states: { normal: { background: "rgba(0, 0, 0, 0.05)", // currentColor at 5% color: "rgba(0, 0, 0, 0.87)", // $text primary boxShadow: "inset 0 0 0 2px transparent", }, hover: { background: "rgba(0, 0, 0, 0.08)", }, focus: { boxShadow: "inset 0 0 0 2px rgba(0, 0, 0, 0.08)", }, active: { // Ripple animation plays background: "rgba(0, 0, 0, 0.08)", }, disabled: { background: "rgba(0, 0, 0, 0.05)", color: "rgba(0, 0, 0, 0.38)", }, checked: { // PRIMARY colored button background: "#1A73E8", // $primary color: "#FFFFFF", // $primary-text }, }, /** Flat/text button */ flat: { normal: { background: "transparent", color: "rgba(0, 0, 0, 0.6)", // $text-secondary }, hover: { background: "rgba(0, 0, 0, 0.08)", color: "rgba(0, 0, 0, 0.87)", }, active: { background: "rgba(0, 0, 0, 0.08)", color: "rgba(0, 0, 0, 0.87)", }, disabled: { background: "transparent", color: "rgba(0, 0, 0, 0.26)", }, checked: { background: "rgba(0, 0, 0, 0.10)", color: "rgba(0, 0, 0, 0.87)", }, }, /** Suggested action (primary CTA) - uses primary color */ suggested: { background: "#1A73E8", color: "#FFFFFF", }, /** Destructive action */ destructive: { background: "#E53935", color: "#FFFFFF", }, /** Pill button (for dialog actions) */ pill: { borderRadius: 9999, padding: "6px 32px", }, /** Circular button */ circular: { borderRadius: 9999, minWidth: 24, minHeight: 24, }, } as const; // --- 5.2 CARDS / PANELS --- export const card = { borderRadius: 12, // $corner-radius (same as default) border: "1px solid", // $divider color // light: "rgba(0,0,0,0.12)", dark: "rgba(255,255,255,0.12)" boxShadow: "none", backgroundClip: "padding-box", // light bg: $base = #FFFFFF, dark bg: $base = #2C2C2C // color: $text-secondary /** Boxed list (grouped card rows) */ boxedList: { borderRadius: 11, // $corner-radius - 1px rowBorderBottom: "1px solid", // $divider transition: "200ms cubic-bezier(0.0, 0.0, 0.2, 1)", }, } as const; // --- 5.3 NAVIGATION / SIDEBAR --- export const sidebar = { // background: $base-alt (light: #FAFAFA, dark: #242424) borderRight: "1px solid", // $divider padding: "6px 0", // $space-size vertical only row: { minHeight: 36, // $medium-size padding: "0 9px", // 0 $space-size * 1.5 // Navigation sidebar rows have special pill-shaped right side borderRadius: "0 9999px 9999px 0", // 0 $circular 0 $circular margin: "0 6px 0 0", selected: { // background: overlay-checked = 10% currentColor color: "#1A73E8", // $primary }, }, stackSidebar: { rowPadding: "6px 9px", rowRadius: 6, // $corner-radius / 2 rowSelectedWeight: 500, }, } as const; // --- 5.4 HEADERBAR / NAVIGATION BAR --- export const headerbar = { // Light mode: background = #FFFFFF, dark mode: background = #2C2C2C // Topbar can be independently dark even in light mode minHeight: 48, // $large-size padding: "0 6px", borderSpacing: 6, /** Compact headerbar */ compact: { minHeight: 40, padding: "0 4px", borderSpacing: 4, }, buttonStyle: { // headerbar buttons are flat by default color: "inherit", // uses titlebar text colors fontWeight: 500, }, } as const; // --- 5.5 INPUT FIELDS --- export const input = { minHeight: 36, // $medium-size padding: "0 8px", // 0 ($space-size + 2px) borderRadius: 12, // $corner-radius borderSpacing: 6, states: { normal: { background: "rgba(0, 0, 0, 0.05)", // currentColor 5% outline: "0 solid transparent", outlineOffset: "4px", }, hover: { background: "rgba(0, 0, 0, 0.08)", outline: "2px solid rgba(0, 0, 0, 0.08)", outlineOffset: "-2px", }, focus: { background: "rgba(0, 0, 0, 0.08)", outline: "2px solid rgba(0, 0, 0, 0.26)", // $track color outlineOffset: "-2px", }, checked: { // When actively typing (focus + content) outline: "2px solid #1A73E8", // $primary outlineOffset: "-2px", }, disabled: { background: "rgba(0, 0, 0, 0.05)", color: "rgba(0, 0, 0, 0.38)", }, error: { outline: "2px solid #E53935", // $error }, warning: { outline: "2px solid #FFD600", // $warning }, success: { outline: "2px solid #0F9D58", // $success }, }, /** Flat entry (no background) */ flat: { minHeight: "auto", padding: "2px", borderRadius: 0, background: "transparent", }, } as const; // --- 5.6 DROPDOWNS / COMBOBOX --- // Orchis treats dropdowns as button + popover combinations export const dropdown = { // Inherits button styling for the trigger trigger: { minHeight: 24, borderRadius: 12, fontWeight: 500, }, // Menu uses popover styling menu: { borderRadius: 11, // $menu-radius boxShadow: "0 3px 3px -1px rgba(0,0,0,0.2), 0 6px 6px 0 rgba(0,0,0,0.14), 0 1px 11px 0 rgba(0,0,0,0.12)", // $shadow-z6 padding: 6, }, menuItem: { minHeight: 22, // $menuitem-size - $space-size minWidth: 56, // $menuitem-size * 2 padding: "3px 9px", // $space-size/2 $space-size*1.5 borderRadius: 5, // $menuitem-radius }, } as const; // --- 5.7 TOGGLES / SWITCHES --- export const toggle = { // GTK switch is a sliding toggle margin: "6px 0", padding: "0 2px", border: "5px solid transparent", borderRadius: 9999, // $circular-radius transition: "all 75ms cubic-bezier(0.0, 0.0, 0.2, 1)", // Track track: { unchecked: "rgba(0, 0, 0, 0.26)", // $track (light mode) checked: "rgba(26, 115, 232, 0.5)", // color-mix($primary 50%) disabled: { opacity: 0.5 }, }, // Slider/thumb slider: { width: 20, height: 20, margin: "-3px -2px", borderRadius: 9999, backgroundColor: "#FFFFFF", // $surface (light) boxShadow: "0 2px 2px -2px rgba(0,0,0,0.3), 0 1px 2px -1px rgba(0,0,0,0.24), 0 1px 2px -1px rgba(0,0,0,0.17)", // $shadow-z1 }, // Checked slider sliderChecked: { backgroundColor: "#1A73E8", // $primary }, // Hover ring hoverRing: "0 0 0 10px rgba(0, 0, 0, 0.08)", focusRing: "0 0 0 10px rgba(0, 0, 0, 0.08)", } as const; // --- 5.8 TABLES / TREE VIEWS --- export const table = { background: "#FFFFFF", // $base headerBackground: "#FFFFFF", // $base headerColor: "rgba(0, 0, 0, 0.6)", // $text-secondary headerPadding: "2px 6px", headerBorder: "1px solid rgba(0, 0, 0, 0.12)", // $divider headerFontWeight: "normal", row: { padding: "2px", color: "rgba(0, 0, 0, 0.6)", borderBottom: "1px solid rgba(0, 0, 0, 0.12)", }, /** Row hover (activatable rows) */ rowHover: { background: "rgba(0, 0, 0, 0.08)", color: "rgba(0, 0, 0, 0.87)", }, /** Row active (with ripple animation) */ rowActive: { background: "rgba(0, 0, 0, 0.08)", }, /** Row selected */ rowSelected: { background: "rgba(0, 0, 0, 0.06)", // $overlay-selected }, /** Progress bar in treeview */ progressBar: "6px solid #1A73E8", // $bar-size solid $primary progressTrough: "6px solid rgba(0, 0, 0, 0.15)", } as const; // --- 5.9 TABS / NOTEBOOK --- export const tabs = { tab: { minHeight: 24, // $small-size minWidth: 24, padding: "6px 12px", // $space-size $space-size*2 fontWeight: 500, transition: "all 75ms cubic-bezier(0.0, 0.0, 0.2, 1)", }, states: { normal: { borderColor: "transparent", background: "transparent", color: "rgba(0, 0, 0, 0.6)", // $text-secondary }, hover: { background: "#E2E2E2", // $solid-border (light) color: "rgba(0, 0, 0, 0.87)", }, disabled: { color: "rgba(0, 0, 0, 0.26)", }, checked: { background: "#FFFFFF", // $base borderColor: "#E2E2E2", // $solid-border color: "rgba(0, 0, 0, 0.87)", }, }, /** Notebook container */ notebook: { background: "#FFFFFF", // $base frameRadius: 12, // $corner-radius }, /** Stack switcher (segmented control style) */ stackSwitcher: { borderRadius: 9999, // $circular-radius background: "rgba(0, 0, 0, 0.05)", // $overlay-normal buttonRadius: 9999, // Checked: background = $primary, color = white }, } as const; // --- 5.10 DIALOGS / MODALS --- export const dialog = { background: "#3C3C3C", // $surface (or $surface in current mode) borderRadius: 18, // $window-radius boxShadow: "0 8px 6px -5px rgba(0,0,0,0.2), 0 16px 16px 2px rgba(0,0,0,0.14), 0 6px 18px 5px rgba(0,0,0,0.12)", // $shadow-z16 borderSpacing: 10, /** Message dialog specific */ messageDialog: { actionPadding: 6, actionButtonRadius: 9999, // $circular-radius (pill shaped) actionButtonStyle: "flat", // flat buttons in dialogs // Non-disabled buttons colored with $primary // Destructive buttons colored with $destructive }, /** About dialog */ aboutDialog: { iconSize: 128, scrolledWindowRadius: 12, // $window-radius - $space-size }, } as const; // --- 5.11 PROGRESS BARS --- export const progressBar = { /** Bar height: $bar-size = 6px */ height: 6, borderRadius: 12, // $corner-radius /** Trough (background track) */ trough: { background: "rgba(0, 0, 0, 0.15)", // $track-disabled (light) }, /** Progress (filled portion) */ progress: { background: "#1A73E8", // $primary }, /** Level bar */ levelBar: { low: "#FFD600", // $warning high: "#1A73E8", // $primary full: "#0F9D58", // $success empty: "rgba(0, 0, 0, 0.15)", }, } as const; // --- 5.12 TOOLTIPS --- export const tooltipStyle = { // Light mode: dark tooltip (darken(background(h), 3%) at 0.9 opacity) // Dark mode: dark tooltip background: "rgba(0, 0, 0, 0.9)", // $tooltip (light mode default) color: "#FFFFFF", borderRadius: 6, // $corner-radius / 2 padding: "6px 12px", // $space-size $space-size*2 boxShadow: "0 2px 2px -1px rgba(0,0,0,0.2), 0 4px 4px 0 rgba(0,0,0,0.14), 0 1px 6px 0 rgba(0,0,0,0.12)", // $shadow-z4 margin: "2px 6px 8px 6px", } as const; // --- 5.13 SCROLLBARS --- export const scrollbar = { background: "#FFFFFF", // $base borderWidth: 1, borderColor: "rgba(0, 0, 0, 0.12)", slider: { minWidth: 8, minHeight: 8, border: "4px solid transparent", borderRadius: 9999, backgroundClip: "padding-box", normal: "rgba(0, 0, 0, 0.26)", // $text-secondary-disabled hover: "rgba(0, 0, 0, 0.38)", // $text-disabled active: "rgba(0, 0, 0, 0.6)", // $text-secondary disabled: "rgba(0, 0, 0, 0.26)", }, /** Overlay scrollbar (thin) */ overlay: { sliderWidth: 4, sliderHeight: 4, margin: 3, }, } as const; // --- 5.14 POPOVERS / MENUS --- export const popover = { borderRadius: 11, // $menu-radius boxShadow: "0 3px 3px -1px rgba(0,0,0,0.2), 0 6px 6px 0 rgba(0,0,0,0.14), 0 1px 11px 0 rgba(0,0,0,0.12)", // $shadow-z6 padding: 6, // $space-size border: "none", // Light: background = $surface = #FFFFFF // Dark: background = $surface = #3C3C3C /** Menu item styling */ menuItem: { minHeight: 22, // $menuitem-size - $space-size minWidth: 56, padding: "3px 9px", borderRadius: 5, // $menuitem-radius transition: "background-color 75ms cubic-bezier(0.0, 0.0, 0.2, 1)", }, /** Separator */ separator: { margin: "3px 0", // $space-size/2 0 background: "rgba(0, 0, 0, 0.12)", }, /** Backdrop state */ backdrop: { boxShadow: "0 3px 2px -3px rgba(0,0,0,0.3), 0 2px 2px -1px rgba(0,0,0,0.24), 0 1px 3px 0 rgba(0,0,0,0.12)", // $shadow-z2 }, } as const; // --- 5.15 CALENDAR --- export const calendar = { borderRadius: 12, border: "1px solid rgba(0, 0, 0, 0.12)", headerBorderBottom: "1px solid rgba(0, 0, 0, 0.12)", headerPadding: 3, gridMargin: 3, dayPadding: 9, // $space-size * 1.5 todayHighlight: "#1A73E8", // primary color selectedBorder: 9999, // circular for selected days } as const; // ============================================================================ // 6. SHADOW / ELEVATION SYSTEM // ============================================================================ /** * Based on Material Design elevation system. * Values from material-components-web with Orchis adjustments. */ export const shadows = { /** z1 - Subtle elevation (cards at rest, buttons) */ z1: "0 2px 2px -2px rgba(0,0,0,0.3), 0 1px 2px -1px rgba(0,0,0,0.24), 0 1px 2px -1px rgba(0,0,0,0.17)", /** z2 - Low elevation (search bars, app bars) */ z2: "0 3px 2px -3px rgba(0,0,0,0.3), 0 2px 2px -1px rgba(0,0,0,0.24), 0 1px 3px 0 rgba(0,0,0,0.12)", /** z3 - Medium elevation (cards on hover, FAB at rest) */ z3: "0 3px 3px -2px rgba(0,0,0,0.2), 0 3px 3px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12)", /** z4 - Medium-high elevation (menus, tooltips, backdrops) */ z4: "0 2px 2px -1px rgba(0,0,0,0.2), 0 4px 4px 0 rgba(0,0,0,0.14), 0 1px 6px 0 rgba(0,0,0,0.12)", /** z6 - High elevation (popovers, dropdown menus) */ z6: "0 3px 3px -1px rgba(0,0,0,0.2), 0 6px 6px 0 rgba(0,0,0,0.14), 0 1px 11px 0 rgba(0,0,0,0.12)", /** z8 - Higher elevation (bottom sheets, side sheets) */ z8: "0 5px 5px -3px rgba(0,0,0,0.2), 0 8px 8px 1px rgba(0,0,0,0.14), 0 3px 9px 2px rgba(0,0,0,0.12)", /** z12 - Very high elevation (FAB pressed) */ z12: "0 7px 7px -4px rgba(0,0,0,0.2), 0 12px 12px 2px rgba(0,0,0,0.14), 0 5px 13px 4px rgba(0,0,0,0.12)", /** z16 - Window elevation (dialogs, modal windows) */ z16: "0 8px 6px -5px rgba(0,0,0,0.2), 0 16px 16px 2px rgba(0,0,0,0.14), 0 6px 18px 5px rgba(0,0,0,0.12)", /** z24 - Maximum elevation (full-screen dialogs) */ z24: "0 11px 11px -7px rgba(0,0,0,0.2), 0 24px 24px 3px rgba(0,0,0,0.14), 0 9px 28px 8px rgba(0,0,0,0.12)", /** Text shadow */ text: "0 1px 1px rgba(0,0,0,0.2), 0 1px 2px rgba(0,0,0,0.14), 0 1px 3px rgba(0,0,0,0.12)", /** Gnome Shell simplified shadows */ shell: { z1: "0 1px 2px rgba(0,0,0,0.25)", z2: "0 3px 3px rgba(0,0,0,0.32)", z3: "0 3px 8px rgba(0,0,0,0.2)", z4: "0 6px 10px rgba(0,0,0,0.32)", z5: "0 10px 15px rgba(0,0,0,0.45)", z6: "0 12px 20px rgba(0,0,0,0.6)", }, } as const; // ============================================================================ // 7. ANIMATION / TRANSITION PATTERNS // ============================================================================ export const animation = { /** Durations */ duration: { shortest: "75ms", // $duration - micro interactions shorter: "100ms", // $shorter-duration short: "150ms", // $longer-duration rippleFadeIn: "225ms", // $ripple-fade-in-duration rippleFadeOut: "300ms", // $ripple-fade-out-duration rippleOpacity: "1200ms", // $ripple-fade-out-opacity-duration }, /** Timing functions (Material Design standard) */ easing: { /** Standard easing - for most transitions */ standard: "cubic-bezier(0.4, 0.0, 0.2, 1)", /** Decelerate - for elements entering the screen */ decelerate: "cubic-bezier(0.0, 0.0, 0.2, 1)", /** Accelerate - for elements leaving the screen */ accelerate: "cubic-bezier(0.4, 0.0, 1, 1)", /** Sharp - for elements that may return to screen */ sharp: "cubic-bezier(0.4, 0.0, 0.6, 1)", }, /** Predefined transition shorthands */ transition: { default: "all 75ms cubic-bezier(0.0, 0.0, 0.2, 1)", shadow: "box-shadow 75ms cubic-bezier(0.0, 0.0, 0.2, 1)", }, /** Ripple effect (Material Design signature interaction) */ ripple: { /** * CSS keyframes for ripple effect: * @keyframes ripple { * from { background-image: radial-gradient(circle farthest-corner at center, rgba(0,0,0,0.10) 30%, transparent 0%); } * to { background-image: radial-gradient(circle farthest-corner at center, rgba(0,0,0,0.10) 100%, transparent 0%); } * } */ duration: "225ms", easing: "cubic-bezier(0.0, 0.0, 0.2, 1)", // The ripple circle starts at 30% and expands to 100% overlayColor: "rgba(0, 0, 0, 0.10)", // $overlay-checked }, /** Spinner animation: rotate 1 full turn, linear, infinite */ spinner: { animation: "spin 1s linear infinite", }, /** Needs-attention pulse */ needsAttention: { // Radial gradient pulse from 0% to 95% with primary color }, } as const; // ============================================================================ // 8. ICON STYLE PREFERENCES // ============================================================================ export const icons = { /** Orchis uses symbolic (monochrome outline) icons in the GNOME style */ style: "symbolic", // Monochrome, outline-based icons /** Base icon size */ baseSize: 16, // $base-icon-size mediumSize: 24, // $base-icon-size * 1.5 largeSize: 32, // $base-icon-size * 2 /** Icon color follows text color (currentColor) */ color: "currentColor", /** Check/radio icon size */ checkRadioSize: 24, /** The Orchis icon set uses: * - Papirus icons (recommended companion) * - Symbolic SVG icons for UI elements * - Material Design inspired icon shapes * - Rounded/soft stroke style */ recommendation: "Use Material Symbols (Rounded variant) or Phosphor Icons for web", } as const; // ============================================================================ // CSS CUSTOM PROPERTIES (ready for :root injection) // ============================================================================ /** * Generate CSS custom properties for a Next.js application. * Usage: inject these into your global CSS or a ThemeProvider. */ export function generateCSSVariables(mode: "light" | "dark" = "light", accent: keyof typeof accentColors = "default"): string { const theme = mode === "light" ? lightTheme : darkTheme; const accentColor = mode === "light" ? accentColors[accent].dark : accentColors[accent].light; return ` :root { /* ---- Primary / Accent ---- */ --orchis-primary: ${accentColor}; --orchis-on-primary: ${theme.onPrimary.primary}; --orchis-on-primary-secondary: ${theme.onPrimary.secondary}; /* ---- Backgrounds ---- */ --orchis-background: ${theme.background}; --orchis-surface: ${theme.surface}; --orchis-base: ${theme.base}; --orchis-base-alt: ${theme.baseAlt}; /* ---- Text ---- */ --orchis-text: ${theme.text.primary}; --orchis-text-secondary: ${theme.text.secondary}; --orchis-text-disabled: ${theme.text.disabled}; /* ---- Semantic ---- */ --orchis-error: ${theme.error}; --orchis-warning: ${theme.warning}; --orchis-success: ${theme.success}; --orchis-link: ${accentColor}; --orchis-link-visited: ${theme.linkVisited}; --orchis-destructive: ${theme.error}; /* ---- Borders ---- */ --orchis-border: ${theme.border}; --orchis-border-solid: ${theme.solidBorder}; --orchis-divider: ${theme.divider}; /* ---- Overlay States ---- */ --orchis-overlay-hover: ${theme.overlay.hover}; --orchis-overlay-focus: ${theme.overlay.focus}; --orchis-overlay-active: ${theme.overlay.active}; --orchis-overlay-checked: ${theme.overlay.checked}; --orchis-overlay-selected: ${theme.overlay.selected}; /* ---- Track / Fill ---- */ --orchis-track: ${theme.track}; --orchis-track-disabled: ${theme.trackDisabled}; --orchis-fill: ${theme.fill}; --orchis-secondary-fill: ${theme.secondaryFill}; /* ---- Tooltip ---- */ --orchis-tooltip-bg: ${theme.tooltip}; /* ---- Titlebar ---- */ --orchis-titlebar: ${theme.titlebar}; --orchis-titlebar-backdrop: ${theme.titlebarBackdrop}; --orchis-sidebar: ${theme.sidebar}; /* ---- Window Buttons ---- */ --orchis-btn-close: ${theme.buttonClose}; --orchis-btn-maximize: ${theme.buttonMaximize}; --orchis-btn-minimize: ${theme.buttonMinimize}; /* ---- Typography ---- */ --orchis-font-family: ${typography.fontFamily}; --orchis-font-size: ${typography.rootFontSize}; --orchis-font-weight-button: ${typography.buttonWeight}; /* ---- Spacing ---- */ --orchis-space: ${spacing.space}px; --orchis-space-xs: ${spacing.xs}px; --orchis-space-sm: ${spacing.sm}px; --orchis-space-md: ${spacing.md}px; --orchis-space-lg: ${spacing.lg}px; --orchis-space-xl: ${spacing.xl}px; --orchis-space-xxl: ${spacing.xxl}px; /* ---- Border Radius ---- */ --orchis-radius: ${borderRadius.default}px; --orchis-radius-window: ${borderRadius.window}px; --orchis-radius-corner: ${borderRadius.corner}px; --orchis-radius-menu: ${borderRadius.menu}px; --orchis-radius-card: ${borderRadius.card}px; --orchis-radius-tooltip: ${borderRadius.tooltip}px; --orchis-radius-menuitem: ${borderRadius.menuItem}px; --orchis-radius-circular: ${borderRadius.circular}px; /* ---- Shadows ---- */ --orchis-shadow-z1: ${shadows.z1}; --orchis-shadow-z2: ${shadows.z2}; --orchis-shadow-z3: ${shadows.z3}; --orchis-shadow-z4: ${shadows.z4}; --orchis-shadow-z6: ${shadows.z6}; --orchis-shadow-z8: ${shadows.z8}; --orchis-shadow-z12: ${shadows.z12}; --orchis-shadow-z16: ${shadows.z16}; --orchis-shadow-z24: ${shadows.z24}; /* ---- Transitions ---- */ --orchis-duration: ${animation.duration.shortest}; --orchis-duration-short: ${animation.duration.short}; --orchis-duration-ripple: ${animation.duration.rippleFadeIn}; --orchis-ease: ${animation.easing.standard}; --orchis-ease-out: ${animation.easing.decelerate}; --orchis-ease-in: ${animation.easing.accelerate}; --orchis-transition: ${animation.transition.default}; /* ---- Component Sizes ---- */ --orchis-size-small: ${spacing.small}px; --orchis-size-medium: ${spacing.medium}px; --orchis-size-large: ${spacing.large}px; --orchis-icon-size: ${icons.baseSize}px; --orchis-icon-size-md: ${icons.mediumSize}px; --orchis-icon-size-lg: ${icons.largeSize}px; --orchis-bar-size: ${spacing.bar}px; } `.trim(); }