Rustelo/resources/nickel/themes/defaults.ncl
Jesús Pérez f1010e9d07
chore: update
2026-07-18 20:16:16 +01:00

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",
},
}