Commit 156ce129 authored by Lyza Danger Gardner's avatar Lyza Danger Gardner Committed by Lyza Gardner

Convert AnnotationQuote to Tailwind

parent 9d40fff9
......@@ -2,7 +2,7 @@ import { Actions } from '@hypothesis/frontend-shared';
import classnames from 'classnames';
import { useStoreProxy } from '../../store/use-store';
import { isSaved, quote } from '../../helpers/annotation-metadata';
import { isOrphan, isSaved, quote } from '../../helpers/annotation-metadata';
import { withServices } from '../../service-context';
import AnnotationActionBar from './AnnotationActionBar';
......@@ -83,7 +83,11 @@ function Annotation({
/>
{hasQuote && (
<AnnotationQuote annotation={annotation} isFocused={isFocused} />
<AnnotationQuote
quote={quote(annotation)}
isFocused={isFocused}
isOrphan={isOrphan(annotation)}
/>
)}
{!isCollapsedReply && !isEditing && (
......
import classnames from 'classnames';
import { isOrphan, quote } from '../../helpers/annotation-metadata';
import { withServices } from '../../service-context';
import { applyTheme } from '../../helpers/theme';
......@@ -12,18 +11,14 @@ import Excerpt from '../Excerpt';
*/
/**
* @typedef AnnotationQuoteProps
* @prop {Annotation} annotation
* @prop {boolean} [isFocused] - Is this annotation currently focused?
* @prop {SidebarSettings} [settings] - Used for theming.
*/
/**
* Display the selected text from the document associated with an annotation.
* Style content as quoted text
*
* @parm {AnnotationQuoteProps} props
* @param {object} props
* @param {import('preact').ComponentChildren} props.children
* @param {string} [props.classes] - Additional CSS classes
* @param {object} [props.style] - Inline style object
*/
function AnnotationQuote({ annotation, isFocused, settings = {} }) {
function QuotedText({ children, classes, style }) {
// The language for the quote may be different than the client's UI (set by
// `<html lang="...">`).
//
......@@ -35,29 +30,47 @@ function AnnotationQuote({ annotation, isFocused, settings = {} }) {
const documentLanguage = '';
return (
<div
className={classnames({
'is-orphan': isOrphan(annotation),
})}
<blockquote
className={classnames(
'border-l-[3px] border-grey-3 hover:border-l-blue-quote',
'italic text-color-text-light px-[1em]',
classes
)}
dir="auto"
lang={documentLanguage}
style={style}
>
<Excerpt
collapsedHeight={35}
inlineControls={true}
overflowThreshold={20}
{children}
</blockquote>
);
}
/**
* @typedef AnnotationQuoteProps
* @prop {string} quote
* @prop {boolean} [isFocused] - Is this annotation currently focused?
* @prop {boolean} [isOrphan]
* @prop {SidebarSettings} [settings] - Used for theming.
*/
/**
* Display the selected text from the document associated with an annotation.
*
* @parm {AnnotationQuoteProps} props
*/
function AnnotationQuote({ quote, isFocused, isOrphan, settings = {} }) {
return (
<Excerpt collapsedHeight={35} inlineControls={true} overflowThreshold={20}>
<QuotedText
classes={classnames({
'border-l-blue-quote': isFocused,
'line-through grayscale contrast-50': isOrphan,
})}
style={applyTheme(['selectionFontFamily'], settings)}
>
<blockquote
className={classnames('p-quoted-text', {
'is-focused': isFocused,
'p-redacted-content': isOrphan(annotation),
})}
dir="auto"
lang={documentLanguage}
style={applyTheme(['selectionFontFamily'], settings)}
>
{quote(annotation)}
</blockquote>
</Excerpt>
</div>
{quote}
</QuotedText>
</Excerpt>
);
}
......
......@@ -6,15 +6,14 @@ import { mockImportedComponents } from '../../../../test-util/mock-imported-comp
import AnnotationQuote, { $imports } from '../AnnotationQuote';
describe('AnnotationQuote', () => {
let fakeAnnotation;
let fakeIsOrphan;
let fakeQuote;
let fakeApplyTheme;
function createQuote(props) {
return mount(
<AnnotationQuote
annotation={fakeAnnotation}
quote={'test quote'}
isFocused={false}
isOrphan={false}
settings={{}}
{...props}
/>
......@@ -22,18 +21,12 @@ describe('AnnotationQuote', () => {
}
beforeEach(() => {
fakeAnnotation = {
target: [],
};
fakeQuote = sinon.stub().returns('test quote');
fakeIsOrphan = sinon.stub();
fakeApplyTheme = sinon.stub().returns({});
$imports.$mock(mockImportedComponents());
$imports.$mock({
'../../helpers/annotation-metadata': {
quote: fakeQuote,
isOrphan: fakeIsOrphan,
'../../helpers/theme': {
applyTheme: fakeApplyTheme,
},
});
});
......@@ -48,6 +41,18 @@ describe('AnnotationQuote', () => {
assert.equal(quote.text(), 'test quote');
});
it('applies selectionFontFamily styling from settings', () => {
fakeApplyTheme
.withArgs(sinon.match.array.deepEquals(['selectionFontFamily']))
.returns({ fontFamily: 'monospace' });
const wrapper = createQuote();
const quote = wrapper.find('blockquote');
assert.equal(quote.getDOMNode().style.fontFamily, 'monospace');
});
it(
'should pass a11y checks',
checkAccessibility({
......
......@@ -19,22 +19,6 @@
}
}
// Represent quoted text, as in an excerpt, with a hover or focused state.
.p-quoted-text {
border-left: 3px solid var.$color-border;
color: var.$color-text--light;
font-style: italic;
padding: 0 var.$layout-space;
// Prevent long URLs etc. in quote causing overflow
overflow-wrap: break-word;
&.is-focused,
&:hover {
border-left: var.$color-quote 3px solid;
}
}
// A pattern for displaying redacted (moderated) text content
.p-redacted-content {
text-decoration: line-through;
......
......@@ -39,6 +39,9 @@ export default {
'color-text': {
inverted: '#f2f2f2',
},
blue: {
quote: '#58cef4',
},
},
fontFamily: {
mono: ['"Open Sans Mono"', 'Menlo', '"DejaVu Sans Mono"', 'monospace'],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment