298 lines
9 KiB
Text
298 lines
9 KiB
Text
# Theme Configuration Defaults and Helpers
|
|
#
|
|
# Provides base theme with full configuration and helpers for creating variants.
|
|
|
|
let contracts = import "contracts.ncl" in
|
|
|
|
{
|
|
# Base theme with complete default configuration
|
|
# All theme variants should extend this
|
|
base_theme = {
|
|
typography = {
|
|
font_family_sans = "Inter, ui-sans-serif, system-ui, sans-serif",
|
|
font_family_mono = "JetBrains Mono, ui-monospace, 'Cascadia Code', monospace",
|
|
|
|
font_size_xs = "0.75rem",
|
|
font_size_sm = "0.875rem",
|
|
font_size_base = "1rem",
|
|
font_size_lg = "1.125rem",
|
|
font_size_xl = "1.25rem",
|
|
font_size_2xl = "1.5rem",
|
|
font_size_3xl = "1.875rem",
|
|
|
|
line_height_tight = "1.25",
|
|
line_height_normal = "1.5",
|
|
line_height_relaxed = "1.75",
|
|
},
|
|
|
|
spacing = {
|
|
xs = "0.25rem",
|
|
sm = "0.5rem",
|
|
md = "1rem",
|
|
lg = "1.5rem",
|
|
xl = "2rem",
|
|
"2xl" = "2.5rem",
|
|
"3xl" = "3rem",
|
|
},
|
|
|
|
radius = {
|
|
sm = "0.25rem",
|
|
md = "0.375rem",
|
|
lg = "0.5rem",
|
|
xl = "0.75rem",
|
|
"2xl" = "1rem",
|
|
full = "9999px",
|
|
},
|
|
|
|
shadows = {
|
|
sm = "0 1px 2px 0 rgb(0 0 0 / 0.05)",
|
|
base = "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
|
|
md = "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
|
|
lg = "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
|
|
xl = "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
|
|
},
|
|
|
|
components = {
|
|
button = {
|
|
border_radius = "0.5rem",
|
|
padding_x_sm = "0.75rem",
|
|
padding_y_sm = "0.375rem",
|
|
padding_x_md = "1rem",
|
|
padding_y_md = "0.5rem",
|
|
padding_x_lg = "1.5rem",
|
|
padding_y_lg = "0.75rem",
|
|
font_weight = "500",
|
|
transition = "all 200ms ease-in-out",
|
|
},
|
|
|
|
card = {
|
|
border_radius = "0.75rem",
|
|
padding = "1.5rem",
|
|
shadow = "sm",
|
|
border_width = "1px",
|
|
},
|
|
|
|
input = {
|
|
border_radius = "0.375rem",
|
|
padding_x = "0.75rem",
|
|
padding_y = "0.5rem",
|
|
border_width = "1px",
|
|
transition = "border-color 200ms ease-in-out, box-shadow 200ms ease-in-out",
|
|
},
|
|
|
|
navbar = {
|
|
height = "4rem",
|
|
padding_x = "1rem",
|
|
backdrop_blur = "true",
|
|
border_bottom_width = "1px",
|
|
},
|
|
|
|
footer = {
|
|
padding_y = "2rem",
|
|
border_top_width = "1px",
|
|
},
|
|
},
|
|
|
|
assets = {
|
|
logo_light = "/logos/jesusperez-logo-b.png",
|
|
logo_dark = "/logos/jesusperez-logo-w.png",
|
|
logo_icon = "/logos/logo-icon.svg",
|
|
favicon = "/images/favicon.ico",
|
|
favicon_dark = "/images/favicon.ico",
|
|
|
|
logo_alt = "Jesús Pérez Lorenzo",
|
|
logo_href = "/",
|
|
logo_show_in_nav = true,
|
|
logo_show_in_footer = true,
|
|
logo_width = "auto",
|
|
logo_height = "2.5rem",
|
|
|
|
logo_height_sm = "2rem",
|
|
logo_height_md = "2.5rem",
|
|
logo_height_lg = "3rem",
|
|
},
|
|
|
|
animations = {
|
|
duration_fast = "150ms",
|
|
duration_normal = "200ms",
|
|
duration_slow = "300ms",
|
|
easing = "cubic-bezier(0.4, 0, 0.2, 1)",
|
|
},
|
|
|
|
breakpoints = {
|
|
sm = "640px",
|
|
md = "768px",
|
|
lg = "1024px",
|
|
xl = "1280px",
|
|
"2xl" = "1536px",
|
|
},
|
|
},
|
|
|
|
# Helper function: Create a color variant theme
|
|
#
|
|
# Usage:
|
|
# make_color_variant {
|
|
# name = "Dark",
|
|
# description = "Dark theme with high contrast",
|
|
# colors = { primary = "#60a5fa", ... },
|
|
# }
|
|
#
|
|
# Parameters:
|
|
# config: Record with name, description, colors, and optional assets
|
|
#
|
|
# Returns: Complete theme with colors overridden
|
|
make_color_variant
|
|
| Dyn -> Dyn
|
|
= fun config =>
|
|
# For assets, rebuild the entire record with conditional field selection
|
|
# This avoids merge conflicts when overriding string fields
|
|
let final_assets =
|
|
if std.record.has_field "assets" config then
|
|
{
|
|
logo_light = if std.record.has_field "logo_light" config.assets then config.assets.logo_light else base_theme.assets.logo_light,
|
|
logo_dark = if std.record.has_field "logo_dark" config.assets then config.assets.logo_dark else base_theme.assets.logo_dark,
|
|
logo_icon = if std.record.has_field "logo_icon" config.assets then config.assets.logo_icon else base_theme.assets.logo_icon,
|
|
favicon = if std.record.has_field "favicon" config.assets then config.assets.favicon else base_theme.assets.favicon,
|
|
favicon_dark = if std.record.has_field "favicon_dark" config.assets then config.assets.favicon_dark else base_theme.assets.favicon_dark,
|
|
logo_alt = if std.record.has_field "logo_alt" config.assets then config.assets.logo_alt else base_theme.assets.logo_alt,
|
|
logo_href = if std.record.has_field "logo_href" config.assets then config.assets.logo_href else base_theme.assets.logo_href,
|
|
logo_show_in_nav = if std.record.has_field "logo_show_in_nav" config.assets then config.assets.logo_show_in_nav else base_theme.assets.logo_show_in_nav,
|
|
logo_show_in_footer = if std.record.has_field "logo_show_in_footer" config.assets then config.assets.logo_show_in_footer else base_theme.assets.logo_show_in_footer,
|
|
logo_width = if std.record.has_field "logo_width" config.assets then config.assets.logo_width else base_theme.assets.logo_width,
|
|
logo_height = if std.record.has_field "logo_height" config.assets then config.assets.height else base_theme.assets.logo_height,
|
|
logo_height_sm = if std.record.has_field "logo_height_sm" config.assets then config.assets.logo_height_sm else base_theme.assets.logo_height_sm,
|
|
logo_height_md = if std.record.has_field "logo_height_md" config.assets then config.assets.logo_height_md else base_theme.assets.logo_height_md,
|
|
logo_height_lg = if std.record.has_field "logo_height_lg" config.assets then config.assets.logo_height_lg else base_theme.assets.logo_height_lg,
|
|
}
|
|
else
|
|
base_theme.assets
|
|
in
|
|
# Explicitly construct new record to avoid merge conflicts
|
|
# Cannot use & merge because assets field has conflicting string values
|
|
{
|
|
metadata = {
|
|
name = config.name,
|
|
description = config.description,
|
|
version = "1.0.0",
|
|
author = "Rustelo Contributors",
|
|
extends = "default",
|
|
},
|
|
colors = config.colors,
|
|
typography = base_theme.typography,
|
|
spacing = base_theme.spacing,
|
|
radius = base_theme.radius,
|
|
shadows = base_theme.shadows,
|
|
components = base_theme.components,
|
|
assets = final_assets,
|
|
animations = base_theme.animations,
|
|
breakpoints = base_theme.breakpoints,
|
|
},
|
|
|
|
# Default light colors (Blue theme)
|
|
light_colors = {
|
|
primary = "#3b82f6",
|
|
primary_hover = "#2563eb",
|
|
secondary = "#6b7280",
|
|
secondary_hover = "#4b5563",
|
|
accent = "#f59e0b",
|
|
|
|
success = "#10b981",
|
|
warning = "#f59e0b",
|
|
error = "#ef4444",
|
|
info = "#06b6d4",
|
|
|
|
surface = "#ffffff",
|
|
surface_dark = "#1f2937",
|
|
surface_hover = "#f9fafb",
|
|
surface_hover_dark = "#374151",
|
|
|
|
text = "#111827",
|
|
text_dark = "#f9fafb",
|
|
text_secondary = "#6b7280",
|
|
text_secondary_dark = "#9ca3af",
|
|
|
|
border = "#e5e7eb",
|
|
border_dark = "#374151",
|
|
},
|
|
|
|
# Dark theme colors
|
|
dark_colors = {
|
|
primary = "#60a5fa",
|
|
primary_hover = "#3b82f6",
|
|
secondary = "#9ca3af",
|
|
secondary_hover = "#d1d5db",
|
|
accent = "#fbbf24",
|
|
|
|
success = "#34d399",
|
|
warning = "#fbbf24",
|
|
error = "#f87171",
|
|
info = "#22d3ee",
|
|
|
|
surface = "#111827",
|
|
surface_dark = "#030712",
|
|
surface_hover = "#1f2937",
|
|
surface_hover_dark = "#374151",
|
|
|
|
text = "#f9fafb",
|
|
text_dark = "#111827",
|
|
text_secondary = "#d1d5db",
|
|
text_secondary_dark = "#6b7280",
|
|
|
|
border = "#374151",
|
|
border_dark = "#4b5563",
|
|
},
|
|
|
|
# Corporate colors (Professional blue-gray)
|
|
corporate_colors = {
|
|
primary = "#1e40af",
|
|
primary_hover = "#1e3a8a",
|
|
secondary = "#64748b",
|
|
secondary_hover = "#475569",
|
|
accent = "#0ea5e9",
|
|
|
|
success = "#059669",
|
|
warning = "#d97706",
|
|
error = "#dc2626",
|
|
info = "#0284c7",
|
|
|
|
surface = "#ffffff",
|
|
surface_dark = "#1e293b",
|
|
surface_hover = "#f8fafc",
|
|
surface_hover_dark = "#334155",
|
|
|
|
text = "#0f172a",
|
|
text_dark = "#f8fafc",
|
|
text_secondary = "#64748b",
|
|
text_secondary_dark = "#94a3b8",
|
|
|
|
border = "#e2e8f0",
|
|
border_dark = "#334155",
|
|
},
|
|
|
|
# Purple colors (Creative purple theme)
|
|
purple_colors = {
|
|
primary = "#9333ea",
|
|
primary_hover = "#7e22ce",
|
|
secondary = "#71717a",
|
|
secondary_hover = "#52525b",
|
|
accent = "#f59e0b",
|
|
|
|
success = "#10b981",
|
|
warning = "#f59e0b",
|
|
error = "#ef4444",
|
|
info = "#06b6d4",
|
|
|
|
surface = "#ffffff",
|
|
surface_dark = "#18181b",
|
|
surface_hover = "#fafafa",
|
|
surface_hover_dark = "#27272a",
|
|
|
|
text = "#09090b",
|
|
text_dark = "#fafafa",
|
|
text_secondary = "#71717a",
|
|
text_secondary_dark = "#a1a1aa",
|
|
|
|
border = "#e4e4e7",
|
|
border_dark = "#3f3f46",
|
|
},
|
|
}
|