mirror of
https://github.com/harivansh-afk/Austens-Wedding-Guide.git
synced 2026-04-17 13:05:06 +00:00
timeline improvements
This commit is contained in:
parent
34516c0aa5
commit
cfcb36222d
2 changed files with 295 additions and 265 deletions
|
|
@ -10,12 +10,12 @@ interface Props {
|
||||||
|
|
||||||
// Define major time periods with matching category colors
|
// Define major time periods with matching category colors
|
||||||
const timePeriods = [
|
const timePeriods = [
|
||||||
{ start: 1775, end: 1785, name: 'Early Life', color: 'primary.50' },
|
{ start: 1775, end: 1785, name: 'Early Life', color: 'rgba(74, 93, 82, 0.1)' },
|
||||||
{ start: 1786, end: 1800, name: 'Juvenilia & Early Drafts', color: 'primary.100' },
|
{ start: 1786, end: 1800, name: 'Juvenilia & Early Drafts', color: 'rgba(74, 93, 82, 0.15)' },
|
||||||
{ start: 1801, end: 1817, name: 'Publication Years', color: 'primary.200' },
|
{ start: 1801, end: 1817, name: 'Publication Years', color: 'rgba(74, 93, 82, 0.2)' },
|
||||||
{ start: 1818, end: 1900, name: 'Victorian Reception', color: 'warning.50' },
|
{ start: 1818, end: 1900, name: 'Victorian Reception', color: 'rgba(74, 93, 82, 0.25)' },
|
||||||
{ start: 1901, end: 2000, name: '20th Century', color: 'success.50' },
|
{ start: 1901, end: 2000, name: '20th Century', color: 'rgba(74, 93, 82, 0.3)' },
|
||||||
{ start: 2001, end: new Date().getFullYear(), name: 'Contemporary', color: 'success.100' }
|
{ start: 2001, end: new Date().getFullYear(), name: 'Contemporary', color: 'rgba(74, 93, 82, 0.35)' }
|
||||||
];
|
];
|
||||||
|
|
||||||
// Timeline data focused on course texts and their context
|
// Timeline data focused on course texts and their context
|
||||||
|
|
@ -307,15 +307,25 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
const getEventColor = (type: string) => {
|
const getEventColor = (type: string) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'works':
|
case 'works':
|
||||||
return { main: 'primary.main', light: 'primary.50' };
|
return {
|
||||||
|
main: '#4A5D52',
|
||||||
|
light: '#E5E9E7'
|
||||||
|
};
|
||||||
case 'context':
|
case 'context':
|
||||||
return { main: 'secondary.main', light: 'secondary.50' };
|
return {
|
||||||
|
main: '#5B6E65',
|
||||||
|
light: '#D5DCD8'
|
||||||
|
};
|
||||||
case 'legacy':
|
case 'legacy':
|
||||||
return { main: 'warning.main', light: 'warning.50' };
|
return {
|
||||||
case 'adaptations':
|
main: '#6B7F75',
|
||||||
return { main: 'success.main', light: 'success.50' };
|
light: '#C5CEC9'
|
||||||
default:
|
};
|
||||||
return { main: 'grey.500', light: 'grey.50' };
|
default: // adaptations
|
||||||
|
return {
|
||||||
|
main: '#7C8F86',
|
||||||
|
light: '#B5C0BA'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -351,11 +361,12 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
onClick={() => toggleFilter('works')}
|
onClick={() => toggleFilter('works')}
|
||||||
variant={activeFilters.includes('works') ? 'contained' : 'outlined'}
|
variant={activeFilters.includes('works') ? 'contained' : 'outlined'}
|
||||||
sx={{
|
sx={{
|
||||||
color: activeFilters.includes('works') ? 'white' : 'primary.main',
|
color: activeFilters.includes('works') ? 'white' : 'sage.700',
|
||||||
borderColor: 'primary.main',
|
borderColor: 'sage.300',
|
||||||
|
bgcolor: activeFilters.includes('works') ? '#4A5D52' : 'transparent',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
borderColor: 'primary.dark',
|
borderColor: 'sage.400',
|
||||||
bgcolor: activeFilters.includes('works') ? 'primary.dark' : 'primary.50'
|
bgcolor: activeFilters.includes('works') ? '#3A4D42' : 'sage.50'
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -365,12 +376,12 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
onClick={() => toggleFilter('context')}
|
onClick={() => toggleFilter('context')}
|
||||||
variant={activeFilters.includes('context') ? 'contained' : 'outlined'}
|
variant={activeFilters.includes('context') ? 'contained' : 'outlined'}
|
||||||
sx={{
|
sx={{
|
||||||
color: activeFilters.includes('context') ? 'white' : 'secondary.main',
|
color: activeFilters.includes('context') ? 'white' : 'sage.700',
|
||||||
borderColor: 'secondary.main',
|
borderColor: 'sage.300',
|
||||||
bgcolor: activeFilters.includes('context') ? 'secondary.main' : 'transparent',
|
bgcolor: activeFilters.includes('context') ? '#5B6E65' : 'transparent',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
borderColor: 'secondary.dark',
|
borderColor: 'sage.400',
|
||||||
bgcolor: activeFilters.includes('context') ? 'secondary.dark' : 'secondary.50'
|
bgcolor: activeFilters.includes('context') ? '#4B5E55' : 'sage.50'
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -380,12 +391,12 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
onClick={() => toggleFilter('legacy')}
|
onClick={() => toggleFilter('legacy')}
|
||||||
variant={activeFilters.includes('legacy') ? 'contained' : 'outlined'}
|
variant={activeFilters.includes('legacy') ? 'contained' : 'outlined'}
|
||||||
sx={{
|
sx={{
|
||||||
color: activeFilters.includes('legacy') ? 'white' : 'warning.main',
|
color: activeFilters.includes('legacy') ? 'white' : 'sage.700',
|
||||||
borderColor: 'warning.main',
|
borderColor: 'sage.300',
|
||||||
bgcolor: activeFilters.includes('legacy') ? 'warning.main' : 'transparent',
|
bgcolor: activeFilters.includes('legacy') ? '#6B7F75' : 'transparent',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
borderColor: 'warning.dark',
|
borderColor: 'sage.400',
|
||||||
bgcolor: activeFilters.includes('legacy') ? 'warning.dark' : 'warning.50'
|
bgcolor: activeFilters.includes('legacy') ? '#5B6F65' : 'sage.50'
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -395,12 +406,12 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
onClick={() => toggleFilter('adaptations')}
|
onClick={() => toggleFilter('adaptations')}
|
||||||
variant={activeFilters.includes('adaptations') ? 'contained' : 'outlined'}
|
variant={activeFilters.includes('adaptations') ? 'contained' : 'outlined'}
|
||||||
sx={{
|
sx={{
|
||||||
color: activeFilters.includes('adaptations') ? 'white' : 'success.main',
|
color: activeFilters.includes('adaptations') ? 'white' : 'sage.700',
|
||||||
borderColor: 'success.main',
|
borderColor: 'sage.300',
|
||||||
bgcolor: activeFilters.includes('adaptations') ? 'success.main' : 'transparent',
|
bgcolor: activeFilters.includes('adaptations') ? '#7C8F86' : 'transparent',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
borderColor: 'success.dark',
|
borderColor: 'sage.400',
|
||||||
bgcolor: activeFilters.includes('adaptations') ? 'success.dark' : 'success.50'
|
bgcolor: activeFilters.includes('adaptations') ? '#6C7F76' : 'sage.50'
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -411,14 +422,14 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
|
|
||||||
{/* Timeline Container */}
|
{/* Timeline Container */}
|
||||||
<Box sx={{ position: 'relative', mt: 6 }}>
|
<Box sx={{ position: 'relative', mt: 6 }}>
|
||||||
{/* Navigation Buttons Container */}
|
{/* Navigation Buttons */}
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 200, // Half of the timeline height (400px)
|
top: 200,
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
height: 0, // Zero height to not affect layout
|
height: 0,
|
||||||
pointerEvents: 'none',
|
pointerEvents: 'none',
|
||||||
zIndex: 3
|
zIndex: 3
|
||||||
}}
|
}}
|
||||||
|
|
@ -431,19 +442,21 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
top: '50%',
|
top: '50%',
|
||||||
transform: 'translate(-50%, -50%)',
|
transform: 'translate(-50%, -50%)',
|
||||||
zIndex: 3,
|
zIndex: 3,
|
||||||
bgcolor: 'background.paper',
|
bgcolor: 'white',
|
||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: 'divider',
|
borderColor: 'sage.200',
|
||||||
boxShadow: theme => `0 2px 8px ${alpha(theme.palette.common.black, 0.15)}`,
|
boxShadow: theme => `0 2px 8px ${alpha(theme.palette.common.black, 0.15)}`,
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 40,
|
height: 40,
|
||||||
pointerEvents: 'auto',
|
pointerEvents: 'auto',
|
||||||
|
color: 'sage.700',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
bgcolor: 'grey.50',
|
bgcolor: 'sage.50',
|
||||||
|
borderColor: 'sage.300',
|
||||||
boxShadow: theme => `0 4px 12px ${alpha(theme.palette.common.black, 0.2)}`
|
boxShadow: theme => `0 4px 12px ${alpha(theme.palette.common.black, 0.2)}`
|
||||||
},
|
},
|
||||||
'&:active': {
|
'&:active': {
|
||||||
bgcolor: 'grey.100'
|
bgcolor: 'sage.100'
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -457,19 +470,21 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
top: '50%',
|
top: '50%',
|
||||||
transform: 'translate(50%, -50%)',
|
transform: 'translate(50%, -50%)',
|
||||||
zIndex: 3,
|
zIndex: 3,
|
||||||
bgcolor: 'background.paper',
|
bgcolor: 'white',
|
||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: 'divider',
|
borderColor: 'sage.200',
|
||||||
boxShadow: theme => `0 2px 8px ${alpha(theme.palette.common.black, 0.15)}`,
|
boxShadow: theme => `0 2px 8px ${alpha(theme.palette.common.black, 0.15)}`,
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 40,
|
height: 40,
|
||||||
pointerEvents: 'auto',
|
pointerEvents: 'auto',
|
||||||
|
color: 'sage.700',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
bgcolor: 'grey.50',
|
bgcolor: 'sage.50',
|
||||||
|
borderColor: 'sage.300',
|
||||||
boxShadow: theme => `0 4px 12px ${alpha(theme.palette.common.black, 0.2)}`
|
boxShadow: theme => `0 4px 12px ${alpha(theme.palette.common.black, 0.2)}`
|
||||||
},
|
},
|
||||||
'&:active': {
|
'&:active': {
|
||||||
bgcolor: 'grey.100'
|
bgcolor: 'sage.100'
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -508,18 +523,17 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
bgcolor: period.color,
|
bgcolor: period.color,
|
||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: 'divider',
|
borderColor: 'sage.200',
|
||||||
px: 2,
|
px: 2,
|
||||||
py: 0.5,
|
py: 0.5,
|
||||||
borderRadius: '16px',
|
borderRadius: '16px',
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap'
|
||||||
fontFamily: 'cormorant',
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography
|
<Typography
|
||||||
variant="caption"
|
variant="caption"
|
||||||
|
className="font-cormorant text-sage-800"
|
||||||
sx={{
|
sx={{
|
||||||
color: theme => theme.palette.text.primary,
|
|
||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
fontSize: '0.875rem'
|
fontSize: '0.875rem'
|
||||||
}}
|
}}
|
||||||
|
|
@ -538,8 +552,10 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
sx={{
|
sx={{
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
height: 400,
|
height: 400,
|
||||||
bgcolor: 'background.paper',
|
bgcolor: 'white',
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: 'sage.200',
|
||||||
boxShadow: theme => `0 2px 12px ${alpha(theme.palette.common.black, 0.08)}`,
|
boxShadow: theme => `0 2px 12px ${alpha(theme.palette.common.black, 0.08)}`,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
|
|
@ -558,12 +574,11 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
bgcolor: 'sage.400',
|
bgcolor: 'sage.400',
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
border: '2px solid',
|
border: '2px solid',
|
||||||
borderColor: 'background.paper',
|
borderColor: 'white',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
bgcolor: 'sage.500'
|
bgcolor: 'sage.500'
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
scrollBehavior: 'smooth'
|
|
||||||
}}
|
}}
|
||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
|
|
@ -571,24 +586,25 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseLeave={handleMouseLeave}
|
||||||
>
|
>
|
||||||
<Box sx={{ width: '300%', height: '100%', position: 'relative' }}>
|
<Box sx={{ width: '300%', height: '100%', position: 'relative' }}>
|
||||||
{/* Time Period Backgrounds */}
|
{/* Single Continuous Background */}
|
||||||
{timePeriods.map((period) => {
|
<Box
|
||||||
const startPos = ((period.start - actualMinYear) / timeSpan) * 100;
|
sx={{
|
||||||
const width = ((period.end - period.start) / timeSpan) * 100;
|
position: 'absolute',
|
||||||
return (
|
left: 0,
|
||||||
<Box
|
right: 0,
|
||||||
key={period.name}
|
top: 0,
|
||||||
sx={{
|
bottom: 0,
|
||||||
position: 'absolute',
|
background: `linear-gradient(to right,
|
||||||
left: `${startPos}%`,
|
rgba(74, 93, 82, 0.1) 0%,
|
||||||
width: `${width}%`,
|
rgba(74, 93, 82, 0.15) 20%,
|
||||||
height: '100%',
|
rgba(74, 93, 82, 0.2) 40%,
|
||||||
bgcolor: period.color,
|
rgba(74, 93, 82, 0.25) 60%,
|
||||||
opacity: 0.5
|
rgba(74, 93, 82, 0.3) 80%,
|
||||||
}}
|
rgba(74, 93, 82, 0.35) 100%
|
||||||
/>
|
)`,
|
||||||
);
|
zIndex: 0
|
||||||
})}
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Year Markers */}
|
{/* Year Markers */}
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
|
|
@ -598,7 +614,7 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
right: 0,
|
right: 0,
|
||||||
height: 40,
|
height: 40,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
zIndex: 2
|
zIndex: 1
|
||||||
}}>
|
}}>
|
||||||
{yearMarkers.map((year) => {
|
{yearMarkers.map((year) => {
|
||||||
const isDecade = year % 10 === 0;
|
const isDecade = year % 10 === 0;
|
||||||
|
|
@ -611,29 +627,24 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
transform: 'translateX(-50%)',
|
transform: 'translateX(-50%)',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
alignItems: 'center'
|
alignItems: 'center',
|
||||||
|
zIndex: 1
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
width: isDecade ? 2 : 1,
|
width: isDecade ? 2 : 1,
|
||||||
height: isDecade ? 10 : 6,
|
height: isDecade ? 10 : 6,
|
||||||
bgcolor: isDecade ? 'primary.main' : 'text.secondary',
|
bgcolor: isDecade ? 'sage.700' : 'sage.500',
|
||||||
opacity: isDecade ? 0.8 : 0.5
|
opacity: isDecade ? 0.8 : 0.5
|
||||||
}} />
|
}} />
|
||||||
<Typography
|
<Typography
|
||||||
variant="caption"
|
variant="caption"
|
||||||
sx={{
|
sx={{
|
||||||
color: isDecade ? 'primary.main' : 'text.secondary',
|
color: isDecade ? 'sage.800' : 'sage.600',
|
||||||
mt: 0.5,
|
mt: 0.5,
|
||||||
fontWeight: isDecade ? 600 : 400,
|
fontWeight: isDecade ? 600 : 400,
|
||||||
bgcolor: 'rgba(255, 255, 255, 0.9)',
|
|
||||||
px: 1,
|
|
||||||
py: 0.25,
|
|
||||||
borderRadius: 1,
|
|
||||||
fontSize: isDecade ? '0.75rem' : '0.7rem',
|
fontSize: isDecade ? '0.75rem' : '0.7rem',
|
||||||
boxShadow: isDecade ? '0 1px 3px rgba(0,0,0,0.1)' : 'none',
|
backgroundColor: 'transparent'
|
||||||
border: isDecade ? '1px solid' : 'none',
|
|
||||||
borderColor: 'primary.100'
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{year}
|
{year}
|
||||||
|
|
@ -643,18 +654,40 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
})}
|
})}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Timeline Base Line */}
|
{/* Timeline Base Lines */}
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: '50%',
|
top: '50%',
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
height: 2,
|
display: 'flex',
|
||||||
bgcolor: 'grey.300',
|
flexDirection: 'column',
|
||||||
transform: 'translateY(-50%)'
|
alignItems: 'center',
|
||||||
|
transform: 'translateY(-50%)',
|
||||||
|
zIndex: 1
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
|
{/* White line */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: '100%',
|
||||||
|
height: 2,
|
||||||
|
bgcolor: 'white',
|
||||||
|
position: 'absolute'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* Sage line */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: '100%',
|
||||||
|
height: 1,
|
||||||
|
bgcolor: 'sage.300',
|
||||||
|
opacity: 0.5,
|
||||||
|
position: 'absolute'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{/* Events */}
|
{/* Events */}
|
||||||
{filteredEvents.map((event, index) => {
|
{filteredEvents.map((event, index) => {
|
||||||
|
|
@ -673,11 +706,12 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
left: `${position}%`,
|
left: `${position}%`,
|
||||||
top: `${verticalPosition}%`,
|
top: `${verticalPosition}%`,
|
||||||
transform: 'translate(-50%, -50%)',
|
transform: 'translate(-50%, -50%)',
|
||||||
zIndex: isSelected ? 2 : 1,
|
zIndex: isSelected ? 10 : 5,
|
||||||
transition: 'all 0.3s ease',
|
transition: 'all 0.3s ease',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
transform: 'translate(-50%, -50%) scale(1.1)'
|
transform: 'translate(-50%, -50%) scale(1.1)',
|
||||||
|
zIndex: 15
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -835,53 +869,48 @@ export default function InteractiveTimeline({ events = timelineEvents }: Props)
|
||||||
{/* Event Details Section */}
|
{/* Event Details Section */}
|
||||||
{selectedEvent && (
|
{selectedEvent && (
|
||||||
<Paper
|
<Paper
|
||||||
|
elevation={0}
|
||||||
sx={{
|
sx={{
|
||||||
p: 4,
|
p: 4,
|
||||||
mt: 4,
|
mt: 4,
|
||||||
bgcolor: 'background.paper',
|
bgcolor: 'white',
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
boxShadow: 2,
|
|
||||||
transition: 'all 0.3s ease',
|
|
||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: 'divider'
|
borderColor: 'sage.200',
|
||||||
|
transition: 'all 0.3s ease'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', mb: 2 }}>
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', mb: 2 }}>
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" gutterBottom color="primary">
|
<Typography variant="h5" gutterBottom className="font-cormorant text-sage-900">
|
||||||
{selectedEvent.title}
|
{selectedEvent.title}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="subtitle1" color="text.secondary">
|
<Typography variant="subtitle1" className="text-sage-600">
|
||||||
{selectedEvent.year}
|
{selectedEvent.year}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Chip
|
<Chip
|
||||||
label={selectedEvent.type.charAt(0).toUpperCase() + selectedEvent.type.slice(1)}
|
label={selectedEvent.type.charAt(0).toUpperCase() + selectedEvent.type.slice(1)}
|
||||||
color={
|
|
||||||
selectedEvent.type === 'works'
|
|
||||||
? 'primary'
|
|
||||||
: selectedEvent.type === 'context'
|
|
||||||
? 'secondary'
|
|
||||||
: selectedEvent.type === 'legacy'
|
|
||||||
? 'warning'
|
|
||||||
: 'success'
|
|
||||||
}
|
|
||||||
size="small"
|
size="small"
|
||||||
|
sx={{
|
||||||
|
bgcolor: getEventColor(selectedEvent.type).main,
|
||||||
|
color: 'white'
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Divider sx={{ my: 2 }} />
|
<Divider sx={{ my: 2, borderColor: 'sage.200' }} />
|
||||||
|
|
||||||
<Typography variant="body1" paragraph>
|
<Typography variant="body1" paragraph className="text-sage-700">
|
||||||
{selectedEvent.description}
|
{selectedEvent.description}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{selectedEvent.significance && (
|
{selectedEvent.significance && (
|
||||||
<Box sx={{ mt: 2, p: 2, bgcolor: 'grey.50', borderRadius: 1 }}>
|
<Box sx={{ mt: 2, p: 2, bgcolor: 'sage.50', borderRadius: 1, border: '1px solid', borderColor: 'sage.200' }}>
|
||||||
<Typography variant="subtitle2" color="text.secondary" gutterBottom>
|
<Typography variant="subtitle2" className="text-sage-800 font-cormorant" gutterBottom>
|
||||||
Historical Significance
|
Historical Significance
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="text.secondary">
|
<Typography variant="body2" className="text-sage-600">
|
||||||
{selectedEvent.significance}
|
{selectedEvent.significance}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,16 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Box, Typography, Paper, Grid, Chip, IconButton, Tooltip, Tabs, Tab } from '@mui/material';
|
import { Box, Typography, Paper, Grid, Chip } from '@mui/material';
|
||||||
import { Help } from '@mui/icons-material';
|
|
||||||
import { TimelineEvent } from '../types/timeline';
|
import { TimelineEvent } from '../types/timeline';
|
||||||
import InteractiveTimeline from '../components/timeline/InteractiveTimeline';
|
import InteractiveTimeline from '../components/timeline/InteractiveTimeline';
|
||||||
|
import {
|
||||||
interface TabPanelProps {
|
Tabs,
|
||||||
children?: React.ReactNode;
|
TabsContent,
|
||||||
index: number;
|
TabsList,
|
||||||
value: number;
|
TabsTrigger,
|
||||||
}
|
} from "../components/ui/tabs";
|
||||||
|
|
||||||
function TabPanel(props: TabPanelProps) {
|
|
||||||
const { children, value, index, ...other } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
role="tabpanel"
|
|
||||||
hidden={value !== index}
|
|
||||||
id={`timeline-tabpanel-${index}`}
|
|
||||||
aria-labelledby={`timeline-tab-${index}`}
|
|
||||||
{...other}
|
|
||||||
>
|
|
||||||
{value === index && (
|
|
||||||
<Box sx={{ py: 3 }}>
|
|
||||||
{children}
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Timeline() {
|
export default function Timeline() {
|
||||||
const [selectedType, setSelectedType] = useState<'all' | 'works' | 'context' | 'legacy' | 'adaptations'>('all');
|
const [selectedType, setSelectedType] = useState<'all' | 'works' | 'context' | 'legacy' | 'adaptations'>('all');
|
||||||
const [tabValue, setTabValue] = useState(0);
|
|
||||||
|
|
||||||
const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
|
|
||||||
setTabValue(newValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Timeline data focused on course texts and their context
|
// Timeline data focused on course texts and their context
|
||||||
const timelineEvents: TimelineEvent[] = [
|
const timelineEvents: TimelineEvent[] = [
|
||||||
|
|
@ -184,139 +158,166 @@ export default function Timeline() {
|
||||||
.sort((a, b) => a.year - b.year);
|
.sort((a, b) => a.year - b.year);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: '100%' }}>
|
<div className="container mx-auto px-4 py-8 max-w-7xl">
|
||||||
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
<div className="text-center mb-12">
|
||||||
<Tabs
|
<h1 className="font-cormorant text-4xl md:text-5xl text-sage-900 mb-4">
|
||||||
value={tabValue}
|
Literary Timeline & Historical Context
|
||||||
onChange={handleTabChange}
|
</h1>
|
||||||
aria-label="timeline views"
|
<p className="text-sage-600 text-lg max-w-3xl mx-auto mb-6">
|
||||||
sx={{
|
Explore the chronological development of Austen's works and their historical context, from early drafts to modern adaptations.
|
||||||
'& .MuiTab-root': {
|
</p>
|
||||||
color: 'text.secondary',
|
</div>
|
||||||
'&.Mui-selected': {
|
|
||||||
color: 'primary.main',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Tab label="Interactive Timeline" />
|
|
||||||
<Tab label="Basic Timeline" />
|
|
||||||
</Tabs>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<TabPanel value={tabValue} index={0}>
|
<Tabs defaultValue="interactive" className="w-full">
|
||||||
<InteractiveTimeline events={timelineEvents} />
|
<TabsList className="grid w-full grid-cols-2">
|
||||||
</TabPanel>
|
<TabsTrigger value="interactive">Interactive Timeline</TabsTrigger>
|
||||||
|
<TabsTrigger value="basic">Basic Timeline</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
<TabPanel value={tabValue} index={1}>
|
<TabsContent value="interactive">
|
||||||
<Box sx={{ p: 3 }}>
|
<InteractiveTimeline events={timelineEvents} />
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', mb: 3 }}>
|
</TabsContent>
|
||||||
<Typography variant="h4" component="h1">
|
|
||||||
Literary Timeline & Historical Context
|
|
||||||
</Typography>
|
|
||||||
<Tooltip title="Explore the chronological development of Austen's works and their historical/literary context" arrow>
|
|
||||||
<IconButton size="small" sx={{ ml: 2 }}>
|
|
||||||
<Help />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box sx={{ mb: 4 }}>
|
<TabsContent value="basic">
|
||||||
<Typography variant="body1" color="text.secondary" sx={{ mb: 2 }}>
|
<Box sx={{ p: 3 }}>
|
||||||
Discover how Austen's novels interact with their historical moment and continue to inspire contemporary retellings.
|
<Box sx={{ mb: 4 }}>
|
||||||
</Typography>
|
<Typography variant="body1" className="text-sage-600 mb-4">
|
||||||
<Box sx={{ display: 'flex', gap: 1 }}>
|
Filter events by category to focus on specific aspects of Austen's literary journey and influence.
|
||||||
<Chip
|
</Typography>
|
||||||
label="All Events"
|
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
|
||||||
onClick={() => setSelectedType('all')}
|
<Chip
|
||||||
color={selectedType === 'all' ? 'primary' : 'default'}
|
label="All Events"
|
||||||
/>
|
onClick={() => setSelectedType('all')}
|
||||||
<Chip
|
|
||||||
label="Austen's Works"
|
|
||||||
onClick={() => setSelectedType('works')}
|
|
||||||
color={selectedType === 'works' ? 'primary' : 'default'}
|
|
||||||
/>
|
|
||||||
<Chip
|
|
||||||
label="Historical Context"
|
|
||||||
onClick={() => setSelectedType('context')}
|
|
||||||
color={selectedType === 'context' ? 'secondary' : 'default'}
|
|
||||||
/>
|
|
||||||
<Chip
|
|
||||||
label="Legacy & Reception"
|
|
||||||
onClick={() => setSelectedType('legacy')}
|
|
||||||
color={selectedType === 'legacy' ? 'warning' : 'default'}
|
|
||||||
/>
|
|
||||||
<Chip
|
|
||||||
label="Modern Adaptations"
|
|
||||||
onClick={() => setSelectedType('adaptations')}
|
|
||||||
color={selectedType === 'adaptations' ? 'success' : 'default'}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Grid container spacing={3}>
|
|
||||||
{filteredEvents.map((event, index) => (
|
|
||||||
<Grid item xs={12} key={index}>
|
|
||||||
<Paper
|
|
||||||
elevation={3}
|
|
||||||
sx={{
|
sx={{
|
||||||
p: 3,
|
bgcolor: selectedType === 'all' ? '#4A5D52' : 'transparent',
|
||||||
position: 'relative',
|
color: selectedType === 'all' ? 'white' : 'sage.700',
|
||||||
'&::before': {
|
border: '1px solid',
|
||||||
content: '""',
|
borderColor: selectedType === 'all' ? '#4A5D52' : 'sage.300',
|
||||||
position: 'absolute',
|
'&:hover': {
|
||||||
left: 0,
|
bgcolor: selectedType === 'all' ? '#3A4D42' : 'sage.50'
|
||||||
top: 0,
|
|
||||||
bottom: 0,
|
|
||||||
width: 4,
|
|
||||||
backgroundColor: event.type === 'works'
|
|
||||||
? 'primary.main'
|
|
||||||
: event.type === 'context'
|
|
||||||
? 'secondary.main'
|
|
||||||
: event.type === 'legacy'
|
|
||||||
? 'warning.main'
|
|
||||||
: 'success.main'
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
<Box sx={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>
|
<Chip
|
||||||
<Box>
|
label="Austen's Works"
|
||||||
<Typography variant="h6" component="h2">
|
onClick={() => setSelectedType('works')}
|
||||||
{event.title}
|
sx={{
|
||||||
</Typography>
|
bgcolor: selectedType === 'works' ? '#5B6E65' : 'transparent',
|
||||||
<Typography variant="subtitle1" color="text.secondary" sx={{ mb: 1 }}>
|
color: selectedType === 'works' ? 'white' : 'sage.700',
|
||||||
{event.year}
|
border: '1px solid',
|
||||||
</Typography>
|
borderColor: selectedType === 'works' ? '#5B6E65' : 'sage.300',
|
||||||
<Typography variant="body1" sx={{ mb: 2 }}>
|
'&:hover': {
|
||||||
{event.description}
|
bgcolor: selectedType === 'works' ? '#4B5E55' : 'sage.50'
|
||||||
</Typography>
|
}
|
||||||
{event.significance && (
|
}}
|
||||||
<Typography variant="body2" color="text.secondary">
|
/>
|
||||||
<strong>Significance:</strong> {event.significance}
|
<Chip
|
||||||
</Typography>
|
label="Historical Context"
|
||||||
)}
|
onClick={() => setSelectedType('context')}
|
||||||
</Box>
|
sx={{
|
||||||
<Chip
|
bgcolor: selectedType === 'context' ? '#6B7F75' : 'transparent',
|
||||||
label={event.type.charAt(0).toUpperCase() + event.type.slice(1)}
|
color: selectedType === 'context' ? 'white' : 'sage.700',
|
||||||
size="small"
|
border: '1px solid',
|
||||||
color={
|
borderColor: selectedType === 'context' ? '#6B7F75' : 'sage.300',
|
||||||
event.type === 'works'
|
'&:hover': {
|
||||||
? 'primary'
|
bgcolor: selectedType === 'context' ? '#5B6F65' : 'sage.50'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Chip
|
||||||
|
label="Legacy & Reception"
|
||||||
|
onClick={() => setSelectedType('legacy')}
|
||||||
|
sx={{
|
||||||
|
bgcolor: selectedType === 'legacy' ? '#7C8F86' : 'transparent',
|
||||||
|
color: selectedType === 'legacy' ? 'white' : 'sage.700',
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: selectedType === 'legacy' ? '#7C8F86' : 'sage.300',
|
||||||
|
'&:hover': {
|
||||||
|
bgcolor: selectedType === 'legacy' ? '#6C7F76' : 'sage.50'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Chip
|
||||||
|
label="Modern Adaptations"
|
||||||
|
onClick={() => setSelectedType('adaptations')}
|
||||||
|
sx={{
|
||||||
|
bgcolor: selectedType === 'adaptations' ? '#8C9F96' : 'transparent',
|
||||||
|
color: selectedType === 'adaptations' ? 'white' : 'sage.700',
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: selectedType === 'adaptations' ? '#8C9F96' : 'sage.300',
|
||||||
|
'&:hover': {
|
||||||
|
bgcolor: selectedType === 'adaptations' ? '#7C8F86' : 'sage.50'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Grid container spacing={3}>
|
||||||
|
{filteredEvents.map((event, index) => (
|
||||||
|
<Grid item xs={12} key={index}>
|
||||||
|
<Paper
|
||||||
|
elevation={0}
|
||||||
|
sx={{
|
||||||
|
p: 3,
|
||||||
|
position: 'relative',
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: 'sage.200',
|
||||||
|
borderRadius: 2,
|
||||||
|
'&::before': {
|
||||||
|
content: '""',
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
width: 4,
|
||||||
|
backgroundColor: event.type === 'works'
|
||||||
|
? '#4A5D52'
|
||||||
: event.type === 'context'
|
: event.type === 'context'
|
||||||
? 'secondary'
|
? '#5B6E65'
|
||||||
: event.type === 'legacy'
|
: event.type === 'legacy'
|
||||||
? 'warning'
|
? '#6B7F75'
|
||||||
: 'success'
|
: '#7C8F86'
|
||||||
}
|
}
|
||||||
sx={{ ml: 2 }}
|
}}
|
||||||
/>
|
>
|
||||||
</Box>
|
<Box sx={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>
|
||||||
</Paper>
|
<Box>
|
||||||
</Grid>
|
<Typography variant="h6" component="h2" className="font-cormorant text-sage-900">
|
||||||
))}
|
{event.title}
|
||||||
</Grid>
|
</Typography>
|
||||||
</Box>
|
<Typography variant="subtitle1" className="text-sage-600 mb-1">
|
||||||
</TabPanel>
|
{event.year}
|
||||||
</Box>
|
</Typography>
|
||||||
|
<Typography variant="body1" className="text-sage-700 mb-2">
|
||||||
|
{event.description}
|
||||||
|
</Typography>
|
||||||
|
{event.significance && (
|
||||||
|
<Typography variant="body2" className="text-sage-600">
|
||||||
|
<strong>Significance:</strong> {event.significance}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
<Chip
|
||||||
|
label={event.type.charAt(0).toUpperCase() + event.type.slice(1)}
|
||||||
|
size="small"
|
||||||
|
sx={{
|
||||||
|
bgcolor: event.type === 'works' ? '#4A5D52' :
|
||||||
|
event.type === 'context' ? '#5B6E65' :
|
||||||
|
event.type === 'legacy' ? '#6B7F75' :
|
||||||
|
'#7C8F86',
|
||||||
|
color: 'white',
|
||||||
|
ml: 2
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue