style rework - kimi k2.5

This commit is contained in:
Tomas Dvorak
2026-04-14 16:06:57 +02:00
parent 7ddfb1f52b
commit f77823ad90
3 changed files with 598 additions and 286 deletions
+34
View File
@@ -0,0 +1,34 @@
# Primora Design Context
## Users
- Solo developers and small teams (2-10 people)
- Technical users who want managed database experience without vendor lock-in
- Self-hosters who value control and ownership
- Job: Easy database access, simple self-hosted managed alternative to native Postgres
## Brand Personality
- Powerful yet affordable (premium feel, accessible pricing)
- Minimal — no bloat, only what you need
- Self-hosted — sense of ownership and control
- Clean, simple, nice to look at
- Developer-first but approachable
## Aesthetic Direction
- **Visual tone**: Refined developer tool — think Linear, Appwrite, Vercel
- **References**: Appwrite (layout inspiration), Supabase (clean data UI), Neon (modern simplicity)
- **Anti-references**: Overly corporate dashboards, cluttered admin panels, "enterprise software" bloat
- **Theme**: Primarily dark mode with light mode support
- **Feel**: Like a precision tool — every pixel intentional, every interaction snappy
## Design Principles
1. **Information density without clutter** — show what matters, hide the rest
2. **Predictable patterns** — developers live in keyboard shortcuts and muscle memory
3. **Progressive disclosure** — simple by default, powerful when needed
4. **Performance is aesthetic** — fast interactions feel premium
5. **Self-hosted soul** — emphasize control, local-first feel, no cloud ambiguity
## Technical Constraints
- SolidJS + TypeScript
- Tailwind CSS
- Must work self-hosted (no external dependencies for core UI)
- Responsive down to tablet (developers rarely use mobile for admin)
File diff suppressed because it is too large Load Diff
+96 -71
View File
@@ -1,8 +1,12 @@
/** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: ["./index.html", "./src/**/*.{ts,tsx}"], content: ["./index.html", "./src/**/*.{ts,tsx}"],
darkMode: "class", darkMode: "class",
theme: { theme: {
extend: { extend: {
/* ============================================
COLORS — OKLCH Design System
============================================ */
colors: { colors: {
// Background layers // Background layers
bg: { bg: {
@@ -30,7 +34,7 @@ module.exports = {
muted: "var(--text-muted)", muted: "var(--text-muted)",
faint: "var(--text-faint)", faint: "var(--text-faint)",
}, },
// Accent // Accent — refined cyan
accent: { accent: {
DEFAULT: "var(--accent)", DEFAULT: "var(--accent)",
hover: "var(--accent-hover)", hover: "var(--accent-hover)",
@@ -39,7 +43,7 @@ module.exports = {
subtle: "var(--accent-subtle)", subtle: "var(--accent-subtle)",
glow: "var(--accent-glow)", glow: "var(--accent-glow)",
}, },
// Status colors // Status colors — semantic
success: { success: {
DEFAULT: "var(--success)", DEFAULT: "var(--success)",
muted: "var(--success-muted)", muted: "var(--success-muted)",
@@ -57,28 +61,71 @@ module.exports = {
muted: "var(--info-muted)", muted: "var(--info-muted)",
}, },
}, },
// Border radius
/* ============================================
GEOMETRY — Radii & Shadows
============================================ */
borderRadius: { borderRadius: {
sm: "var(--radius-sm)", sm: "var(--radius-sm)",
DEFAULT: "var(--radius)", DEFAULT: "var(--radius)",
lg: "var(--radius-lg)", lg: "var(--radius-lg)",
xl: "var(--radius-xl)", xl: "var(--radius-xl)",
full: "var(--radius-full)",
}, },
// Box shadows
boxShadow: { boxShadow: {
sm: "var(--shadow-sm)", sm: "var(--shadow-sm)",
DEFAULT: "var(--shadow-md)", DEFAULT: "var(--shadow-md)",
lg: "var(--shadow-lg)", lg: "var(--shadow-lg)",
elevated: "var(--shadow-elevated)", elevated: "var(--shadow-elevated)",
glow: "var(--shadow-glow)", inner: "var(--shadow-inner)",
glow: "var(--glow-accent)",
"glow-success": "var(--glow-success)",
"glow-error": "var(--glow-error)",
}, },
// Font families
/* ============================================
TYPOGRAPHY — Space Grotesk + Plus Jakarta Sans
============================================ */
fontFamily: { fontFamily: {
sans: "var(--font-sans)", sans: ["var(--font-sans)", { fontFeatureSettings: '"ss01", "ss02", "cv01"' }],
display: "var(--font-display)", display: ["var(--font-display)"],
mono: "var(--font-mono)", mono: ["var(--font-mono)"],
}, },
// Spacing
fontSize: {
// Fluid type scale
"2xs": ["var(--text-2xs)", { lineHeight: "1rem" }],
xs: ["var(--text-xs)", { lineHeight: "1.25rem" }],
sm: ["var(--text-sm)", { lineHeight: "1.5rem" }],
base: ["var(--text-base)", { lineHeight: "1.6" }],
lg: ["var(--text-lg)", { lineHeight: "1.6" }],
xl: ["var(--text-xl)", { lineHeight: "1.75rem" }],
"2xl": ["var(--text-2xl)", { lineHeight: "2rem" }],
"3xl": ["var(--text-3xl)", { lineHeight: "2.25rem" }],
"4xl": ["var(--text-4xl)", { lineHeight: "1.1" }],
},
letterSpacing: {
tighter: "-0.03em",
tight: "-0.02em",
normal: "-0.01em",
wide: "0.02em",
wider: "0.08em",
widest: "0.12em",
},
lineHeight: {
tighter: "1.1",
tight: "1.2",
snug: "1.4",
normal: "1.6",
relaxed: "1.8",
},
/* ============================================
SPACING — Rhythmic fluid scale
============================================ */
spacing: { spacing: {
1: "var(--space-1)", 1: "var(--space-1)",
2: "var(--space-2)", 2: "var(--space-2)",
@@ -89,35 +136,42 @@ module.exports = {
8: "var(--space-8)", 8: "var(--space-8)",
10: "var(--space-10)", 10: "var(--space-10)",
12: "var(--space-12)", 12: "var(--space-12)",
16: "var(--space-16)",
}, },
// Animation durations
/* ============================================
ANIMATION — Purposeful motion
============================================ */
transitionDuration: { transitionDuration: {
instant: "var(--duration-instant)",
fast: "var(--duration-fast)", fast: "var(--duration-fast)",
normal: "var(--duration-normal)", normal: "var(--duration-normal)",
slow: "var(--duration-slow)", slow: "var(--duration-slow)",
slower: "var(--duration-slower)",
}, },
// Animation timing functions
transitionTimingFunction: { transitionTimingFunction: {
"ease-out": "var(--ease-out)", "ease-out": "var(--ease-out)",
"ease-out-expo": "var(--ease-out-expo)",
"ease-in-out": "var(--ease-in-out)", "ease-in-out": "var(--ease-in-out)",
spring: "var(--ease-spring)", spring: "var(--ease-spring)",
bounce: "var(--ease-bounce)",
}, },
// Animations
animation: { animation: {
"fade-in": "fadeIn var(--duration-normal) var(--ease-out)", // Entrances
"slide-up": "slideUp var(--duration-normal) var(--ease-out)", "fade-in": "fadeIn var(--duration-normal) var(--ease-out) forwards",
"slide-in-left": "slideInLeft var(--duration-normal) var(--ease-out)", "slide-up": "slideUp var(--duration-normal) var(--ease-out) forwards",
"slide-in-right": "slideInRight var(--duration-normal) var(--ease-out)", "slide-in-left": "slideInLeft var(--duration-normal) var(--ease-out) forwards",
"scale-in": "scaleIn var(--duration-fast) var(--ease-spring)", "slide-in-right": "slideInRight var(--duration-normal) var(--ease-out) forwards",
"bounce-in": "bounceIn 0.5s var(--ease-spring)", "scale-in": "scaleIn var(--duration-fast) var(--ease-spring) forwards",
"float": "float 3s ease-in-out infinite", // Continuous
"pulse-glow": "pulseGlow 2s ease-in-out infinite",
"gradient-shift": "gradientShift 3s ease infinite",
pulse: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite", pulse: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",
spin: "spin 0.8s linear infinite", spin: "spin 0.8s linear infinite",
"spin-slow": "spin 8s linear infinite", "spin-slow": "spin 8s linear infinite",
shimmer: "shimmer 2s ease-in-out infinite", shimmer: "shimmer 2s ease-in-out infinite",
}, },
keyframes: { keyframes: {
fadeIn: { fadeIn: {
from: { opacity: "0" }, from: { opacity: "0" },
@@ -128,35 +182,17 @@ module.exports = {
to: { opacity: "1", transform: "translateY(0)" }, to: { opacity: "1", transform: "translateY(0)" },
}, },
slideInLeft: { slideInLeft: {
from: { opacity: "0", transform: "translateX(-20px)" }, from: { opacity: "0", transform: "translateX(-16px)" },
to: { opacity: "1", transform: "translateX(0)" }, to: { opacity: "1", transform: "translateX(0)" },
}, },
slideInRight: { slideInRight: {
from: { opacity: "0", transform: "translateX(20px)" }, from: { opacity: "0", transform: "translateX(16px)" },
to: { opacity: "1", transform: "translateX(0)" }, to: { opacity: "1", transform: "translateX(0)" },
}, },
scaleIn: { scaleIn: {
from: { opacity: "0", transform: "scale(0.95)" }, from: { opacity: "0", transform: "scale(0.96)" },
to: { opacity: "1", transform: "scale(1)" }, to: { opacity: "1", transform: "scale(1)" },
}, },
bounceIn: {
"0%": { opacity: "0", transform: "scale(0.3)" },
"50%": { transform: "scale(1.05)" },
"70%": { transform: "scale(0.9)" },
"100%": { opacity: "1", transform: "scale(1)" },
},
float: {
"0%, 100%": { transform: "translateY(0)" },
"50%": { transform: "translateY(-10px)" },
},
pulseGlow: {
"0%, 100%": { boxShadow: "0 0 20px rgba(25, 163, 217, 0.2)" },
"50%": { boxShadow: "0 0 40px rgba(25, 163, 217, 0.4)" },
},
gradientShift: {
"0%, 100%": { backgroundPosition: "0% 50%" },
"50%": { backgroundPosition: "100% 50%" },
},
pulse: { pulse: {
"0%, 100%": { opacity: "1" }, "0%, 100%": { opacity: "1" },
"50%": { opacity: "0.5" }, "50%": { opacity: "0.5" },
@@ -169,37 +205,26 @@ module.exports = {
"100%": { backgroundPosition: "1000px 0" }, "100%": { backgroundPosition: "1000px 0" },
}, },
}, },
// Typography
fontSize: { /* ============================================
"2xs": ["0.625rem", { lineHeight: "1rem" }], Z-INDEX — Purposeful scale
xs: ["0.75rem", { lineHeight: "1rem" }], ============================================ */
sm: ["0.875rem", { lineHeight: "1.25rem" }],
base: ["1rem", { lineHeight: "1.5rem" }],
lg: ["1.125rem", { lineHeight: "1.5rem" }],
xl: ["1.25rem", { lineHeight: "1.75rem" }],
"2xl": ["1.5rem", { lineHeight: "2rem" }],
"3xl": ["2rem", { lineHeight: "2.5rem" }],
},
// Letter spacing
letterSpacing: {
tighter: "-0.02em",
tight: "-0.01em",
normal: "0",
wide: "0.05em",
wider: "0.1em",
widest: "0.14em",
},
// Z-index scale
zIndex: { zIndex: {
1: "1", base: "0",
10: "10", dropdown: "100",
20: "20", sticky: "200",
30: "30", fixed: "300",
40: "40", overlay: "400",
50: "50", modal: "500",
popover: "600",
tooltip: "700",
}, },
// Screens for responsive design
/* ============================================
SCREENS — Responsive breakpoints
============================================ */
screens: { screens: {
xs: "480px",
sm: "640px", sm: "640px",
md: "768px", md: "768px",
lg: "1024px", lg: "1024px",