feat: create HighlightsTab component with color picker

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-12 07:01:06 +00:00
parent 409675bf73
commit 8185009da6
3 changed files with 156 additions and 3 deletions

View File

@@ -0,0 +1,58 @@
import { render, screen, fireEvent } from '@testing-library/react'
import { HighlightsTab } from '@/components/bible/highlights-tab'
import { BibleVerse } from '@/types'
describe('HighlightsTab', () => {
const mockVerse: BibleVerse = {
id: 'v-1',
verseNum: 1,
text: 'In the beginning God created the heavens and the earth'
}
it('should render highlight button when verse not highlighted', () => {
render(
<HighlightsTab
verse={mockVerse}
isHighlighted={false}
currentColor={null}
onToggleHighlight={() => {}}
onColorChange={() => {}}
/>
)
expect(screen.getByText(/Highlight/i)).toBeInTheDocument()
})
it('should render color picker when verse is highlighted', () => {
render(
<HighlightsTab
verse={mockVerse}
isHighlighted={true}
currentColor="yellow"
onToggleHighlight={() => {}}
onColorChange={() => {}}
/>
)
expect(screen.getByText(/Remove highlight/i)).toBeInTheDocument()
})
it('should call onColorChange when color is selected', () => {
const onColorChange = jest.fn()
render(
<HighlightsTab
verse={mockVerse}
isHighlighted={true}
currentColor="yellow"
onToggleHighlight={() => {}}
onColorChange={onColorChange}
/>
)
const blueButton = screen.getByTestId('color-blue')
fireEvent.click(blueButton)
expect(onColorChange).toHaveBeenCalledWith('blue')
})
})

View File

@@ -0,0 +1,90 @@
'use client'
import { Box, Button, Grid, Typography, Divider } from '@mui/material'
import { BibleVerse, HighlightColor } from '@/types'
const HIGHLIGHT_COLORS: HighlightColor[] = ['yellow', 'orange', 'pink', 'blue']
const COLOR_MAP: Record<HighlightColor, { bg: string; hex: string }> = {
yellow: { bg: 'rgba(255, 193, 7, 0.3)', hex: '#FFC107' },
orange: { bg: 'rgba(255, 152, 0, 0.3)', hex: '#FF9800' },
pink: { bg: 'rgba(233, 30, 99, 0.3)', hex: '#E91E63' },
blue: { bg: 'rgba(33, 150, 243, 0.3)', hex: '#2196F3' }
}
interface HighlightsTabProps {
verse: BibleVerse | null
isHighlighted: boolean
currentColor: HighlightColor | null
onToggleHighlight: () => void
onColorChange: (color: HighlightColor) => void
}
export function HighlightsTab({
verse,
isHighlighted,
currentColor,
onToggleHighlight,
onColorChange
}: HighlightsTabProps) {
if (!verse) return null
return (
<Box sx={{ p: 2 }}>
{!isHighlighted ? (
<Button
fullWidth
variant="contained"
color="primary"
onClick={onToggleHighlight}
>
Highlight this verse
</Button>
) : (
<>
<Button
fullWidth
variant="outlined"
color="error"
onClick={onToggleHighlight}
sx={{ mb: 2 }}
>
Remove highlight
</Button>
<Typography variant="subtitle2" sx={{ mb: 1 }}>
Highlight Color
</Typography>
<Grid container spacing={1} sx={{ mb: 2 }}>
{HIGHLIGHT_COLORS.map((color) => (
<Grid item xs={3} key={color}>
<Button
data-testid={`color-${color}`}
fullWidth
variant={currentColor === color ? 'contained' : 'outlined'}
onClick={() => onColorChange(color)}
sx={{
bgcolor: COLOR_MAP[color].bg,
borderColor: COLOR_MAP[color].hex,
border: currentColor === color ? `2px solid ${COLOR_MAP[color].hex}` : undefined,
minHeight: 50,
textTransform: 'capitalize',
color: currentColor === color ? '#000' : 'inherit'
}}
>
{color}
</Button>
</Grid>
))}
</Grid>
<Divider sx={{ my: 2 }} />
<Typography variant="body2" color="textSecondary">
You can highlight the same verse multiple times with different colors.
</Typography>
</>
)}
</Box>
)
}

View File

@@ -3,6 +3,7 @@ import { useState, useEffect } from 'react'
import { Box, Paper, Typography, Tabs, Tab, IconButton, useMediaQuery, useTheme, TextField, Button } from '@mui/material' import { Box, Paper, Typography, Tabs, Tab, IconButton, useMediaQuery, useTheme, TextField, Button } from '@mui/material'
import { Close, Bookmark, BookmarkBorder } from '@mui/icons-material' import { Close, Bookmark, BookmarkBorder } from '@mui/icons-material'
import { BibleVerse } from '@/types' import { BibleVerse } from '@/types'
import { HighlightsTab } from './highlights-tab'
interface VersDetailsPanelProps { interface VersDetailsPanelProps {
verse: BibleVerse | null verse: BibleVerse | null
@@ -118,9 +119,13 @@ export function VersDetailsPanel({
)} )}
{tabValue === 1 && ( {tabValue === 1 && (
<Typography variant="body2" color="text.secondary"> <HighlightsTab
Highlight colors coming soon verse={verse}
</Typography> isHighlighted={false} // TODO: get from state
currentColor={null} // TODO: get from state
onToggleHighlight={() => {}} // TODO: implement
onColorChange={() => {}} // TODO: implement
/>
)} )}
{tabValue === 2 && ( {tabValue === 2 && (