From 752d5fc3c3826ae9d867dd7f516274722c653a94 Mon Sep 17 00:00:00 2001 From: Chris Beer <chris@cbeer.info> Date: Mon, 11 Dec 2023 15:31:12 -0800 Subject: [PATCH] Pull search hit styling up --- __tests__/src/components/SearchHit.test.js | 5 +- .../src/components/SearchResults.test.js | 4 +- src/components/SearchHit.js | 157 +++++++++++------- 3 files changed, 97 insertions(+), 69 deletions(-) diff --git a/__tests__/src/components/SearchHit.test.js b/__tests__/src/components/SearchHit.test.js index c72cef108..e999a8b1e 100644 --- a/__tests__/src/components/SearchHit.test.js +++ b/__tests__/src/components/SearchHit.test.js @@ -67,14 +67,13 @@ describe('SearchHit', () => { it('renders the annotationLabel if present', () => { render(<Subject annotationLabel="The Anno Label" />); - expect(screen.getAllByRole('heading', { level: 6 })).toHaveLength(2); - expect(screen.getByRole('heading', { level: 6, name: 'The Anno Label' })).toHaveClass('MuiTypography-subtitle2'); + expect(screen.getByRole('heading', { level: 4, name: 'The Anno Label' })).toBeInTheDocument(); }); it('does not render the typography if no annotation label is present', () => { render(<Subject />); - expect(screen.getByRole('heading', { level: 6 })).toBeInTheDocument(); + expect(screen.getByRole('heading', { level: 4 })).toBeInTheDocument(); }); }); diff --git a/__tests__/src/components/SearchResults.test.js b/__tests__/src/components/SearchResults.test.js index 14a906cb6..3579a9789 100644 --- a/__tests__/src/components/SearchResults.test.js +++ b/__tests__/src/components/SearchResults.test.js @@ -95,8 +95,8 @@ describe('SearchResults', () => { searchHits: [], }); - expect(screen.getByRole('heading', { level: 6, name: 'The Anno Label' })).toBeInTheDocument(); - expect(screen.getByRole('heading', { level: 6, name: 'Annother Anno Label' })).toBeInTheDocument(); + expect(screen.getByRole('heading', { level: 4, name: 'The Anno Label' })).toBeInTheDocument(); + expect(screen.getByRole('heading', { level: 4, name: 'Annother Anno Label' })).toBeInTheDocument(); }); }); diff --git a/src/components/SearchHit.js b/src/components/SearchHit.js index f2db8a965..41a8be606 100644 --- a/src/components/SearchHit.js +++ b/src/components/SearchHit.js @@ -5,10 +5,45 @@ import ListItem from '@mui/material/ListItem'; import ListItemText from '@mui/material/ListItemText'; import Typography from '@mui/material/Typography'; import Chip from '@mui/material/Chip'; +import { styled } from '@mui/material/styles'; import SanitizedHtml from '../containers/SanitizedHtml'; import TruncatedHit from '../lib/TruncatedHit'; import { ScrollTo } from './ScrollTo'; +const Root = styled(ListItem, { name: 'SearchHit', slot: 'root' })(({ ownerState, theme }) => ({ + '&.Mui-focused': { + '&:hover': { + ...(ownerState.windowSelected && { + backgroundColor: 'inherit', + }), + }, + ...(ownerState.windowSelected && { + backgroundColor: 'inherit', + }), + }, + paddingRight: theme.spacing(1), +})); + +const CanvasLabel = styled('h4', { name: 'SearchHit', slot: 'canvasLabel' })(({ theme }) => ({ + display: 'inline', + marginBottom: theme.spacing(1.5), +})); + +const Counter = styled(Chip, { name: 'SearchHit', slot: 'counter' })(({ ownerState, theme }) => ({ + // eslint-disable-next-line no-nested-ternary + backgroundColor: theme.palette.hitCounter.default, + ...(ownerState.windowSelected && { + backgroundColor: theme.palette.highlights.primary, + }), + ...(ownerState.adjacent && !ownerState.windowSelected && { + backgroundColor: theme.palette.highlights.secondary, + }), + height: 30, + marginRight: theme.spacing(1), + typography: 'subtitle2', + verticalAlign: 'inherit', +})); + /** */ export class SearchHit extends Component { /** */ @@ -93,6 +128,25 @@ export class SearchHit extends Component { const truncatedHit = focused ? hit : hit && new TruncatedHit(hit, annotation); const truncated = hit && (truncatedHit.before !== hit.before || truncatedHit.after !== hit.after); const canvasLabelHtmlId = `${companionWindowId}-${index}`; + const ownerState = { + adjacent, focused, selected, windowSelected, + }; + + const header = ( + <> + <Counter + component="span" + ownerState={ownerState} + label={index + 1} + /> + <CanvasLabel id={canvasLabelHtmlId}> + {canvasLabel} + {annotationLabel && ( + <Typography component="span" sx={{ display: 'block', marginTop: 1 }}>{annotationLabel}</Typography> + )} + </CanvasLabel> + </> + ); return ( <ScrollTo @@ -100,81 +154,56 @@ export class SearchHit extends Component { offsetTop={96} // offset for the height of the form above scrollTo={windowSelected && !focused} > - <ListItem + <Root + ownerState={ownerState} className={windowSelected ? 'windowSelected' : ''} - sx={{ - '&.Mui-focused': { - '&:hover': { - ...(windowSelected && { - backgroundColor: 'inherit', - }), - }, - ...(windowSelected && { - backgroundColor: 'inherit', - }), - }, - paddingRight: 1, - }} divider button={!selected} component="li" onClick={this.handleClick} selected={selected} > - <ListItemText primaryTypographyProps={{ variant: 'body1' }}> - <Typography variant="subtitle2" sx={{ marginBottom: 1.5 }}> - <Chip - component="span" - label={index + 1} - sx={{ - // eslint-disable-next-line no-nested-ternary - backgroundColor: windowSelected ? 'highlights.primary' : adjacent ? 'highlights.secondary' : 'hitCounter.default', - height: 30, - marginRight: 1, - typography: 'subtitle2', - verticalAlign: 'inherit', - }} - /> - <span id={canvasLabelHtmlId}> - {canvasLabel} - </span> - </Typography> - {annotationLabel && ( - <Typography variant="subtitle2">{annotationLabel}</Typography> - )} - {hit && ( + <ListItemText + primary={header} + primaryTypographyProps={{ component: 'div', sx: { marginBottom: 1 }, variant: 'subtitle2' }} + secondaryTypographyProps={{ variant: 'body1' }} + secondary={( <> - <SanitizedHtml ruleSet="iiif" htmlString={truncatedHit.before} /> - {' '} - <strong> - <SanitizedHtml ruleSet="iiif" htmlString={truncatedHit.match} /> - </strong> - {' '} - <SanitizedHtml ruleSet="iiif" htmlString={truncatedHit.after} /> - {' '} - { truncated && !focused && ( - <Button - sx={{ - '& span': { - lineHeight: '1.5em', - }, - margin: 0, - padding: 0, - textTransform: 'none', - }} - onClick={showDetails} - color="secondary" - size="small" - aria-describedby={canvasLabelHtmlId} - > - {t('more')} - </Button> + {hit && ( + <> + <SanitizedHtml ruleSet="iiif" htmlString={truncatedHit.before} /> + {' '} + <strong> + <SanitizedHtml ruleSet="iiif" htmlString={truncatedHit.match} /> + </strong> + {' '} + <SanitizedHtml ruleSet="iiif" htmlString={truncatedHit.after} /> + {' '} + {truncated && !focused && ( + <Button + sx={{ + '& span': { + lineHeight: '1.5em', + }, + margin: 0, + padding: 0, + textTransform: 'none', + }} + onClick={showDetails} + color="secondary" + size="small" + aria-describedby={canvasLabelHtmlId} + > + {t('more')} + </Button> + )} + </> )} + {!hit && annotation && <SanitizedHtml ruleSet="iiif" htmlString={annotation.chars} />} </> )} - {!hit && annotation && <SanitizedHtml ruleSet="iiif" htmlString={annotation.chars} />} - </ListItemText> - </ListItem> + /> + </Root> </ScrollTo> ); } -- GitLab