Commit 5baa223b authored by Lyza Danger Gardner's avatar Lyza Danger Gardner Committed by Lyza Gardner

Extract StyledText and refactor props on related components

Extract a StyledText component that can be used by MarkdownView and
AnnotationQuote. Update some props on Markdown components to match
conventions.
parent 17e990bb
......@@ -76,11 +76,11 @@ function AnnotationBody({ annotation, settings }) {
overflowThreshold={20}
>
<MarkdownView
textStyle={textStyle}
markdown={text}
textClass={{
'p-redacted-content': isHidden(annotation),
}}
classes={classnames({
'line-through grayscale contrast-50': isHidden(annotation),
})}
style={textStyle}
/>
</Excerpt>
)}
......
......@@ -4,51 +4,16 @@ import { withServices } from '../../service-context';
import { applyTheme } from '../../helpers/theme';
import Excerpt from '../Excerpt';
import StyledText from '../StyledText';
/**
* @typedef {import('../../../types/api').Annotation} Annotation
* @typedef {import('../../../types/config').SidebarSettings} SidebarSettings
*/
/**
* Style content as quoted text
*
* @param {object} props
* @param {import('preact').ComponentChildren} props.children
* @param {string} [props.classes] - Additional CSS classes
* @param {object} [props.style] - Inline style object
*/
function QuotedText({ children, classes, style }) {
// The language for the quote may be different than the client's UI (set by
// `<html lang="...">`).
//
// Use a blank string to indicate that it is unknown and it is up to the user
// agent to pick a default or analyze the content and guess.
//
// For web documents we could do better here and gather language information
// as part of the annotation anchoring process.
const documentLanguage = '';
return (
<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}
>
{children}
</blockquote>
);
}
/**
* @typedef AnnotationQuoteProps
* @prop {string} quote
* @prop {boolean} [isFocused] - Is this annotation currently focused?
* @prop {boolean} [isFocused]
* @prop {boolean} [isOrphan]
* @prop {SidebarSettings} [settings] - Used for theming.
*/
......@@ -61,15 +26,18 @@ function QuotedText({ children, classes, style }) {
function AnnotationQuote({ quote, isFocused, isOrphan, settings = {} }) {
return (
<Excerpt collapsedHeight={35} inlineControls={true} overflowThreshold={20}>
<QuotedText
classes={classnames({
<StyledText
classes={classnames({ 'line-through grayscale contrast-50': isOrphan })}
>
<blockquote
className={classnames('hover:border-l-blue-quote', {
'border-l-blue-quote': isFocused,
'line-through grayscale contrast-50': isOrphan,
})}
style={applyTheme(['selectionFontFamily'], settings)}
>
{quote}
</QuotedText>
</blockquote>
</StyledText>
</Excerpt>
);
}
......
......@@ -179,10 +179,7 @@ describe('AnnotationBody', () => {
.returns(textStyle);
const wrapper = createBody();
assert.deepEqual(
wrapper.find('MarkdownView').prop('textStyle'),
textStyle
);
assert.deepEqual(wrapper.find('MarkdownView').prop('style'), textStyle);
});
});
......
......@@ -438,12 +438,8 @@ export default function MarkdownEditor({
{preview ? (
<MarkdownView
markdown={text}
textClass={{
'hyp-u-border': true,
'hyp-u-bg-color--grey-1': true,
'hyp-u-padding': true,
}}
textStyle={textStyle}
classes="border bg-grey-1 p-2"
style={textStyle}
/>
) : (
<textarea
......
import classnames from 'classnames';
import { useEffect, useMemo, useRef } from 'preact/hooks';
import { replaceLinksWithEmbeds } from '../media-embedder';
import { renderMathAndMarkdown } from '../render-markdown';
import StyledText from './StyledText';
/**
* @typedef MarkdownViewProps
* @prop {string} markdown - The string of markdown to display
* @prop {Record<string,string>} [textStyle] -
* Additional CSS properties to apply to the rendered markdown
* @prop {Record<string,boolean>} [textClass] -
* Map of classes to apply to the container of the rendered markdown
* @prop {string} [classes]
* @prop {Record<string,string>} [style]
*/
/**
......@@ -19,11 +19,7 @@ import { renderMathAndMarkdown } from '../render-markdown';
*
* @param {MarkdownViewProps} props
*/
export default function MarkdownView({
markdown = '',
textClass = {},
textStyle = {},
}) {
export default function MarkdownView({ markdown, classes, style }) {
const html = useMemo(
() => (markdown ? renderMathAndMarkdown(markdown) : ''),
[markdown]
......@@ -39,24 +35,22 @@ export default function MarkdownView({
});
}, [markdown]);
// Use a blank string to indicate that the content language is unknown and may be
// different than the client UI. The user agent may pick a default or analyze
// the content to guess.
const contentLanguage = '';
// NB: The following could be implemented by setting attribute props directly
// on `StyledText` (which renders a `div` itself), versus introducing a child
// `div` as is done here. However, in initial testing, this interfered with
// some overflow calculations in the `Excerpt` element. This could be worth
// a review in the future.
return (
<div className="w-full break-words cursor-text">
<StyledText>
<div
className="w-full break-words cursor-text"
dir="auto"
lang={contentLanguage}
>
<div
className={classnames('styled-text', textClass)}
data-testid="styled-text"
className={classes}
data-testid="markdown-text"
ref={content}
dangerouslySetInnerHTML={{ __html: html }}
style={textStyle}
style={style}
/>
</StyledText>
</div>
);
}
import classnames from 'classnames';
/**
* @typedef StyledTextProps
* @prop {import('preact').ComponentChildren} children
* @prop {string} [classes]
*/
/**
* Render children as styled text: basic prose styling for HTML
*
* @param {StyledTextProps & import('preact').JSX.HTMLAttributes<HTMLDivElement>} props
*/
export default function StyledText({ children, classes, ...restProps }) {
// The language for the quote may be different than the client's UI (set by
// `<html lang="...">`).
//
// Use a blank string to indicate that it is unknown and it is up to the user
// agent to pick a default or analyze the content and guess.
//
// For web documents we could do better here and gather language information
// as part of the annotation anchoring process.
const documentLanguage = '';
return (
<div
dir="auto"
lang={documentLanguage}
className={classnames('StyledText', classes)}
{...restProps}
>
{children}
</div>
);
}
......@@ -500,7 +500,7 @@ describe('MarkdownEditor', () => {
});
wrapper.update();
assert.deepEqual(wrapper.find('MarkdownView').prop('textStyle'), textStyle);
assert.deepEqual(wrapper.find('MarkdownView').prop('style'), textStyle);
});
it(
......
......@@ -8,7 +8,7 @@ describe('MarkdownView', () => {
let fakeRenderMathAndMarkdown;
let fakeReplaceLinksWithEmbeds;
const markdownSelector = '[data-testid="styled-text"]';
const markdownSelector = '[data-testid="markdown-text"]';
beforeEach(() => {
fakeRenderMathAndMarkdown = markdown => `rendered:${markdown}`;
......@@ -56,14 +56,14 @@ describe('MarkdownView', () => {
it('applies `textClass` class to container', () => {
const wrapper = mount(
<MarkdownView markdown="foo" textClass={{ 'fancy-effect': true }} />
<MarkdownView markdown="foo" classes={'fancy-effect'} />
);
assert.isTrue(wrapper.find('.fancy-effect').exists());
});
it('applies `textStyle` style to container', () => {
const wrapper = mount(
<MarkdownView markdown="foo" textStyle={{ fontFamily: 'serif' }} />
<MarkdownView markdown="foo" style={{ fontFamily: 'serif' }} />
);
assert.deepEqual(wrapper.find(markdownSelector).prop('style'), {
fontFamily: 'serif',
......
......@@ -6,7 +6,7 @@
* https://github.com/hypothesis/client/pull/4295
*/
@layer components {
.styled-text {
.StyledText {
@apply font-sans font-normal leading-snug;
img,
......
......@@ -29,6 +29,7 @@
@use './PaginationNavigation';
@use './SelectionTabs';
@use './SearchInput';
@use './StyledText';
@use './TagEditor';
@use './Thread';
@use './ThreadCard';
......@@ -36,5 +37,3 @@
@use './ToastMessages';
@use './TopBar';
@use './VersionInfo';
@use './styled-text';
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