Set colorscheme.
This commit is contained in:
parent
6ef9843835
commit
420a904efe
13 changed files with 94 additions and 1090 deletions
|
|
@ -1,59 +1,8 @@
|
|||
@import 'tailwindcss';
|
||||
|
||||
@theme {
|
||||
--font-sans:
|
||||
'Inter', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji',
|
||||
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
|
||||
/* Captain's Log Design Tokens */
|
||||
--color-primary-50: #eff6ff;
|
||||
--color-primary-100: #dbeafe;
|
||||
--color-primary-500: #3b82f6;
|
||||
--color-primary-950: #172554;
|
||||
|
||||
--color-task-todo: #3b82f6;
|
||||
--color-task-done: #22c55e;
|
||||
--color-task-backlog: #6b7280;
|
||||
}
|
||||
/* Captain's Log - Global Styles */
|
||||
|
||||
/* Base font family is handled by Material-UI theme */
|
||||
html,
|
||||
body {
|
||||
@apply bg-gray-50 dark:bg-gray-950 text-gray-900 dark:text-gray-100;
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
color-scheme: dark;
|
||||
}
|
||||
}
|
||||
|
||||
/* Captain's Log Component Styles */
|
||||
.task-card {
|
||||
@apply bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-4 transition-all duration-200;
|
||||
}
|
||||
|
||||
.task-card:hover {
|
||||
@apply shadow-md border-gray-300 dark:border-gray-600;
|
||||
}
|
||||
|
||||
.quick-capture {
|
||||
@apply bg-white dark:bg-gray-800 border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-xl p-4 transition-colors duration-200;
|
||||
}
|
||||
|
||||
.quick-capture:focus-within {
|
||||
@apply border-blue-500 bg-blue-50 dark:bg-blue-950;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium;
|
||||
}
|
||||
|
||||
.status-todo {
|
||||
@apply bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200;
|
||||
}
|
||||
|
||||
.status-done {
|
||||
@apply bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200;
|
||||
}
|
||||
|
||||
.status-backlog {
|
||||
@apply bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import {
|
||||
AppBar,
|
||||
Box,
|
||||
|
|
@ -21,8 +21,6 @@ import {
|
|||
Dashboard as DashboardIcon,
|
||||
Add as AddIcon,
|
||||
Settings as SettingsIcon,
|
||||
DarkMode as DarkModeIcon,
|
||||
LightMode as LightModeIcon,
|
||||
} from '@mui/icons-material'
|
||||
|
||||
const drawerWidth = 240
|
||||
|
|
@ -35,28 +33,11 @@ interface LayoutProps {
|
|||
export default function Layout({ children, loading = false }: LayoutProps) {
|
||||
const theme = useTheme()
|
||||
const [mobileOpen, setMobileOpen] = useState(false)
|
||||
const [darkMode, setDarkMode] = useState(false)
|
||||
|
||||
// Check system preference and localStorage on mount
|
||||
useEffect(() => {
|
||||
const savedTheme = localStorage.getItem('theme')
|
||||
const prefersDark = window.matchMedia(
|
||||
'(prefers-color-scheme: dark)'
|
||||
).matches
|
||||
setDarkMode(savedTheme === 'dark' || (!savedTheme && prefersDark))
|
||||
}, [])
|
||||
|
||||
const handleDrawerToggle = () => {
|
||||
setMobileOpen(!mobileOpen)
|
||||
}
|
||||
|
||||
const handleThemeToggle = () => {
|
||||
const newTheme = !darkMode
|
||||
setDarkMode(newTheme)
|
||||
localStorage.setItem('theme', newTheme ? 'dark' : 'light')
|
||||
document.documentElement.classList.toggle('dark', newTheme)
|
||||
}
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
text: 'Tasks',
|
||||
|
|
@ -72,17 +53,7 @@ export default function Layout({ children, loading = false }: LayoutProps) {
|
|||
|
||||
const drawer = (
|
||||
<div>
|
||||
<Toolbar>
|
||||
<Typography
|
||||
variant="h6"
|
||||
noWrap
|
||||
component="div"
|
||||
sx={{ fontWeight: 700 }}
|
||||
>
|
||||
Captain's Log
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
<List>
|
||||
<List sx={{ pt: 2 }}>
|
||||
{menuItems.map(item => (
|
||||
<ListItem key={item.text} disablePadding>
|
||||
<ListItemButton
|
||||
|
|
@ -134,8 +105,10 @@ export default function Layout({ children, loading = false }: LayoutProps) {
|
|||
<AppBar
|
||||
position="fixed"
|
||||
sx={{
|
||||
width: { md: `calc(100% - ${drawerWidth}px)` },
|
||||
ml: { md: `${drawerWidth}px` },
|
||||
width: '100%',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
color: theme.palette.primary.contrastText,
|
||||
zIndex: theme.zIndex.drawer + 1,
|
||||
}}
|
||||
>
|
||||
<Toolbar>
|
||||
|
|
@ -149,17 +122,21 @@ export default function Layout({ children, loading = false }: LayoutProps) {
|
|||
<MenuIcon />
|
||||
</IconButton>
|
||||
|
||||
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1 }}>
|
||||
Captain's Log
|
||||
</Typography>
|
||||
|
||||
<IconButton
|
||||
color="inherit"
|
||||
onClick={handleThemeToggle}
|
||||
aria-label="toggle dark mode"
|
||||
<Typography
|
||||
variant="h6"
|
||||
noWrap
|
||||
component="div"
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
color: '#ffffff',
|
||||
fontWeight: 700,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
{darkMode ? <LightModeIcon /> : <DarkModeIcon />}
|
||||
</IconButton>
|
||||
⚓ Captain's Log
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
|
||||
|
|
@ -196,6 +173,8 @@ export default function Layout({ children, loading = false }: LayoutProps) {
|
|||
'& .MuiDrawer-paper': {
|
||||
boxSizing: 'border-box',
|
||||
width: drawerWidth,
|
||||
top: '64px', // Position below AppBar
|
||||
height: 'calc(100% - 64px)', // Adjust height to account for AppBar
|
||||
},
|
||||
}}
|
||||
open
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { ThemeProvider } from '@mui/material/styles'
|
|||
import { CssBaseline } from '@mui/material'
|
||||
|
||||
import type { Route } from './+types/root'
|
||||
import { theme, darkTheme } from './theme'
|
||||
import { theme } from './theme'
|
||||
import AppLayout from './components/Layout'
|
||||
import './app.css'
|
||||
|
||||
|
|
@ -46,14 +46,8 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
|||
}
|
||||
|
||||
export default function App() {
|
||||
const isDarkMode =
|
||||
typeof window !== 'undefined' &&
|
||||
(localStorage.getItem('theme') === 'dark' ||
|
||||
(!localStorage.getItem('theme') &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches))
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={isDarkMode ? darkTheme : theme}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<AppLayout>
|
||||
<Outlet />
|
||||
|
|
@ -78,14 +72,8 @@ export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
|
|||
stack = error.stack
|
||||
}
|
||||
|
||||
const isDarkMode =
|
||||
typeof window !== 'undefined' &&
|
||||
(localStorage.getItem('theme') === 'dark' ||
|
||||
(!localStorage.getItem('theme') &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches))
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={isDarkMode ? darkTheme : theme}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<AppLayout>
|
||||
<main className="pt-16 p-4 container mx-auto">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,24 @@
|
|||
import { createTheme } from '@mui/material/styles'
|
||||
|
||||
// Color palette constants
|
||||
const colors = {
|
||||
// Primary Colors
|
||||
deepNavy: '#1e3a5f', // Main brand color for headers and primary actions
|
||||
oceanBlue: '#2c5282', // Secondary blue for links and active states
|
||||
compassGold: '#d69e2e', // Accent color for highlights and call-to-actions
|
||||
|
||||
// Status Colors
|
||||
chartGreen: '#48bb78', // Completed tasks and success states
|
||||
sunsetCoral: '#f56565', // Urgent tasks and error states
|
||||
seaFoam: '#4fd1c7', // Information and notification states
|
||||
|
||||
// Neutrals
|
||||
parchment: '#f7fafc', // Clean background color
|
||||
fogGray: '#e2e8f0', // Subtle borders and dividers
|
||||
stormGray: '#718096', // Secondary text
|
||||
anchorDark: '#2d3748', // Primary text and headings
|
||||
}
|
||||
|
||||
declare module '@mui/material/styles' {
|
||||
interface Theme {
|
||||
custom: {
|
||||
|
|
@ -26,29 +45,37 @@ export const theme = createTheme({
|
|||
palette: {
|
||||
mode: 'light',
|
||||
primary: {
|
||||
50: '#eff6ff',
|
||||
100: '#dbeafe',
|
||||
500: '#3b82f6',
|
||||
main: '#3b82f6',
|
||||
main: colors.deepNavy,
|
||||
light: colors.oceanBlue,
|
||||
contrastText: '#ffffff',
|
||||
},
|
||||
secondary: {
|
||||
main: colors.compassGold,
|
||||
contrastText: '#ffffff',
|
||||
},
|
||||
success: {
|
||||
main: colors.chartGreen,
|
||||
},
|
||||
error: {
|
||||
main: colors.sunsetCoral,
|
||||
},
|
||||
info: {
|
||||
main: colors.seaFoam,
|
||||
},
|
||||
background: {
|
||||
default: '#f9fafb',
|
||||
default: colors.parchment,
|
||||
paper: '#ffffff',
|
||||
},
|
||||
text: {
|
||||
primary: '#111827',
|
||||
secondary: '#6b7280',
|
||||
primary: colors.anchorDark,
|
||||
secondary: colors.stormGray,
|
||||
},
|
||||
grey: {
|
||||
50: '#f9fafb',
|
||||
100: '#f3f4f6',
|
||||
200: '#e5e7eb',
|
||||
300: '#d1d5db',
|
||||
600: '#4b5563',
|
||||
700: '#374151',
|
||||
800: '#1f2937',
|
||||
900: '#111827',
|
||||
100: '#edf2f7',
|
||||
200: colors.fogGray,
|
||||
300: '#cbd5e0',
|
||||
500: colors.stormGray,
|
||||
700: colors.anchorDark,
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
|
|
@ -84,11 +111,11 @@ export const theme = createTheme({
|
|||
MuiAppBar: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: '#ffffff',
|
||||
color: '#111827',
|
||||
backgroundColor: colors.deepNavy,
|
||||
color: '#ffffff',
|
||||
boxShadow:
|
||||
'0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',
|
||||
borderBottom: '1px solid #e5e7eb',
|
||||
borderBottom: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -96,7 +123,7 @@ export const theme = createTheme({
|
|||
styleOverrides: {
|
||||
paper: {
|
||||
backgroundColor: '#ffffff',
|
||||
borderRight: '1px solid #e5e7eb',
|
||||
borderRight: `1px solid ${colors.fogGray}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -122,11 +149,11 @@ export const theme = createTheme({
|
|||
borderRadius: '0.75rem',
|
||||
boxShadow:
|
||||
'0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',
|
||||
border: '1px solid #e5e7eb',
|
||||
border: `1px solid ${colors.fogGray}`,
|
||||
'&:hover': {
|
||||
boxShadow:
|
||||
'0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
|
||||
borderColor: '#d1d5db',
|
||||
borderColor: '#cbd5e0',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -143,138 +170,9 @@ export const theme = createTheme({
|
|||
},
|
||||
custom: {
|
||||
task: {
|
||||
todo: '#3b82f6',
|
||||
done: '#22c55e',
|
||||
backlog: '#6b7280',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const darkTheme = createTheme({
|
||||
palette: {
|
||||
mode: 'dark',
|
||||
primary: {
|
||||
50: '#eff6ff',
|
||||
100: '#dbeafe',
|
||||
500: '#3b82f6',
|
||||
main: '#3b82f6',
|
||||
contrastText: '#ffffff',
|
||||
},
|
||||
background: {
|
||||
default: '#030712',
|
||||
paper: '#1f2937',
|
||||
},
|
||||
text: {
|
||||
primary: '#f9fafb',
|
||||
secondary: '#9ca3af',
|
||||
},
|
||||
grey: {
|
||||
50: '#f9fafb',
|
||||
100: '#f3f4f6',
|
||||
200: '#e5e7eb',
|
||||
300: '#d1d5db',
|
||||
600: '#4b5563',
|
||||
700: '#374151',
|
||||
800: '#1f2937',
|
||||
900: '#111827',
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
fontFamily: '"Inter", ui-sans-serif, system-ui, sans-serif',
|
||||
h1: {
|
||||
fontSize: '2rem',
|
||||
fontWeight: 700,
|
||||
lineHeight: 1.2,
|
||||
},
|
||||
h2: {
|
||||
fontSize: '1.5rem',
|
||||
fontWeight: 600,
|
||||
lineHeight: 1.3,
|
||||
},
|
||||
h3: {
|
||||
fontSize: '1.25rem',
|
||||
fontWeight: 600,
|
||||
lineHeight: 1.4,
|
||||
},
|
||||
body1: {
|
||||
fontSize: '1rem',
|
||||
lineHeight: 1.6,
|
||||
},
|
||||
body2: {
|
||||
fontSize: '0.875rem',
|
||||
lineHeight: 1.5,
|
||||
},
|
||||
},
|
||||
shape: {
|
||||
borderRadius: 12,
|
||||
},
|
||||
components: {
|
||||
MuiAppBar: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: '#1f2937',
|
||||
color: '#f9fafb',
|
||||
boxShadow:
|
||||
'0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',
|
||||
borderBottom: '1px solid #374151',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiDrawer: {
|
||||
styleOverrides: {
|
||||
paper: {
|
||||
backgroundColor: '#1f2937',
|
||||
borderRight: '1px solid #374151',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiButton: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
textTransform: 'none',
|
||||
borderRadius: '0.75rem',
|
||||
fontWeight: 500,
|
||||
},
|
||||
contained: {
|
||||
boxShadow: '0 1px 2px 0 rgb(0 0 0 / 0.05)',
|
||||
'&:hover': {
|
||||
boxShadow:
|
||||
'0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiCard: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: '#1f2937',
|
||||
borderRadius: '0.75rem',
|
||||
boxShadow:
|
||||
'0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',
|
||||
border: '1px solid #374151',
|
||||
'&:hover': {
|
||||
boxShadow:
|
||||
'0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
|
||||
borderColor: '#4b5563',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTextField: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'& .MuiOutlinedInput-root': {
|
||||
borderRadius: '0.75rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
custom: {
|
||||
task: {
|
||||
todo: '#3b82f6',
|
||||
done: '#22c55e',
|
||||
backlog: '#6b7280',
|
||||
todo: colors.oceanBlue,
|
||||
done: colors.chartGreen,
|
||||
backlog: colors.stormGray,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue