Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"main": "src/server.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"test": "vitest run",
"test:watch": "vitest",
"start": "node .",
"dev": "nodemon . --ignore 'src/assets/js/*.js' --ignore 'cypress/**/*.js' --ignore 'test/**/*.js'",
"css": "npx tailwindcss -i ./src/tailwind.css -o ./src/assets/css/index.css --watch",
Expand Down Expand Up @@ -56,6 +57,6 @@
"nodemon": "^3.0.2",
"supertest": "^6.3.3",
"tailwindcss": "^3.1.8",
"vitest": "^3.0.7"
"vitest": "^3.1.3"
}
}
}
148 changes: 103 additions & 45 deletions tailwind.config.cjs
Original file line number Diff line number Diff line change
@@ -1,47 +1,105 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/views/**/*.pug", "./src/assets/js/*.js"],
theme: {
screens: {
xs: "640px",
sm: "780px",
md: "926px",
lg: "1024px",
xl: "1280px",
"2xl": "1536px",
},
extend: {
fontFamily: {
logo: ["Orienta", "serif"],
main: ["Poppins", "sans-serif"],
awesome: ['"Font Awesome 6 Free"'],
},
colors: {
twilight: {
50: "#f1f8fa",
100: "#E8F3F7",
200: "#bfe0ee",
300: "#9ed0e5",
400: "#7ec0dd",
500: "#5eb1d4",
600: "#3ea1cc",
700: "#2e86ab",
800: "#226581",
900: "#153f51",
},
},
textUnderlineOffset: {
6: "6px",
},
textDecorationThickness: {
3: "3px",
},
maxWidth: {
"1/3": "33%",
80: "20rem",
},
},
},
plugins: [require("@tailwindcss/forms")],
safelist: ["flash-success", "flash-error", "flash-info"],
};
// Enable dark mode with class-based strategy
darkMode: 'class',
content: ["./src/views/**/*.pug", "./src/assets/js/*.js"],
theme: {
screens: {
xs: "640px",
sm: "780px",
md: "926px",
lg: "1024px",
xl: "1280px",
"2xl": "1536px",
},
extend: {
// Existing font configurations
fontFamily: {
logo: ["Orienta", "serif"],
main: ["Poppins", "sans-serif"],
awesome: ['"Font Awesome 6 Free"'],
},
// Color palette with comprehensive dark mode support
colors: {
// Existing Twilight palette with dark mode variants
twilight: {
light: {
50: "#f1f8fa",
100: "#E8F3F7",
200: "#bfe0ee",
300: "#9ed0e5",
400: "#7ec0dd",
500: "#5eb1d4",
600: "#3ea1cc",
700: "#2e86ab",
800: "#226581",
900: "#153f51",
},
dark: {
50: "#0c2834",
100: "#113642",
200: "#1b4c5a",
300: "#266272",
400: "#317889",
500: "#3d8ea1",
600: "#4ba5ba",
700: "#59bcd3",
800: "#6fd3ec",
900: "#85ebff",
}
},
// Dark mode semantic colors
background: {
light: "#ffffff",
dark: "#121212"
},
text: {
light: "#000000",
dark: "#e0e0e0"
},
primary: {
light: "#2e86ab",
dark: "#59bcd3"
},
secondary: {
light: "#153f51",
dark: "#266272"
},
accent: {
light: "#3ea1cc",
dark: "#4ba5ba"
},
// Additional semantic colors
success: {
light: "#4caf50",
dark: "#81c784"
},
error: {
light: "#f44336",
dark: "#e57373"
},
warning: {
light: "#ff9800",
dark: "#ffb74d"
},
info: {
light: "#2196f3",
dark: "#64b5f6"
}
},
// Existing extended configurations
textUnderlineOffset: {
6: "6px",
},
textDecorationThickness: {
3: "3px",
},
maxWidth: {
"1/3": "33%",
80: "20rem",
},
},
},
plugins: [require("@tailwindcss/forms")],
safelist: ["flash-success", "flash-error", "flash-info", "dark"],
};
46 changes: 46 additions & 0 deletions tests/tailwind-config.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { expect, describe, test } from 'vitest'
import resolveConfig from 'tailwindcss/resolveConfig'
import tailwindConfig from '../tailwind.config.cjs'

describe('Tailwind Dark Mode Configuration', () => {
const fullConfig = resolveConfig(tailwindConfig)

test('Dark mode is configured', () => {
expect(fullConfig.darkMode).toBe('class')
})

test('Twilight color palette is complete', () => {
const twilightColors = fullConfig.theme.colors.twilight
expect(twilightColors).toHaveProperty('light')
expect(twilightColors).toHaveProperty('dark')

// Check color depth
expect(Object.keys(twilightColors.light)).toHaveLength(10)
expect(Object.keys(twilightColors.dark)).toHaveLength(10)
})

test('Semantic color tokens are defined', () => {
const semanticColors = [
'background', 'text', 'primary',
'secondary', 'accent', 'success',
'error', 'warning', 'info'
]

semanticColors.forEach(color => {
expect(fullConfig.theme.colors[color]).toBeDefined()
expect(fullConfig.theme.colors[color]).toHaveProperty('light')
expect(fullConfig.theme.colors[color]).toHaveProperty('dark')
})
})

test('Dark mode colors have contrast', () => {
const colors = fullConfig.theme.colors

// Basic contrast check: light and dark variants should be different
Object.keys(colors).forEach(colorGroup => {
if (typeof colors[colorGroup] === 'object' && colors[colorGroup].light && colors[colorGroup].dark) {
expect(colors[colorGroup].light).not.toBe(colors[colorGroup].dark)
}
})
})
})
Loading