Skip to content

Commit

Permalink
[amp-fit-text:1.0] Use ResizeObserver for content changes (ampproject…
Browse files Browse the repository at this point in the history
…#28496)

* Observe measurerRef

* Set and observe a nested `contentRef` div with `height: min-content`

* Move `height: min-content` to css

* Use `ContainWrapper` preset refs

* Place in css file
  • Loading branch information
caroqliu authored and ed-bird committed Dec 10, 2020
1 parent 95dfc35 commit 95d4fc6
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 19 deletions.
8 changes: 6 additions & 2 deletions extensions/amp-fit-text/1.0/fit-text.css.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

export const LINE_HEIGHT_EM_ = 1.15;

export const fitTextContent = {
export const fitTextContentWrapper = {
'display': 'flex',
'flexDirection': 'column',
'flexWrap': 'nowrap',
Expand All @@ -25,10 +25,14 @@ export const fitTextContent = {

/* Legacy comment: We have to use the old-style flex box with line clamping. It will only
work in WebKit, but unfortunately there's no alternative. */
export const fitTextContentWrapper = {
export const fitTextContent = {
lineHeight: `${LINE_HEIGHT_EM_}em`,
'display': '-webkit-box',
'-webkit-box-orient': 'vertical',
'overflow': 'hidden',
'textOverflow': 'ellipsis',
};

export const minContentHeight = {
'height': 'min-content',
};
31 changes: 15 additions & 16 deletions extensions/amp-fit-text/1.0/fit-text.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ export function FitText({
maxFontSize = 72,
...rest
}) {
const contentRef = useRef(null);
const containerRef = useRef(null);
const measurerRef = useRef(null);
const heightRef = useRef(null);

const resize = useCallback(() => {
if (!measurerRef.current || !contentRef.current) {
if (!measurerRef.current || !containerRef.current) {
return;
}
const {clientHeight, clientWidth} = contentRef.current;
const {clientHeight, clientWidth} = containerRef.current;
const fontSize = calculateFontSize(
measurerRef.current,
clientHeight,
Expand All @@ -50,34 +51,32 @@ export function FitText({
setOverflowStyle(measurerRef.current, clientHeight, fontSize);
}, [maxFontSize, minFontSize]);

// Here and below, useLayoutEffect is used so intermediary font sizes
// during resizing are resolved before the component visually updates.
// Font size should readjust when container resizes.
// useLayoutEffect is used so intermediary font sizes during calculation
// are resolved before the component visually updates.
useLayoutEffect(() => {
const node = contentRef.current;
if (!node) {
const container = containerRef.current;
const content = heightRef.current;
if (!container || !content) {
return;
}
const observer = new ResizeObserver(() => resize());
observer.observe(node);
observer.observe(container);
observer.observe(content);
return () => observer.disconnect();
}, [resize]);

// Font size should readjust when content changes.
useLayoutEffect(() => {
resize();
}, [children, resize]);

return (
<ContainWrapper
size={true}
layout={true}
paint={true}
contentRef={contentRef}
ref={containerRef}
wrapperStyle={styles.fitTextContentWrapper}
contentRef={measurerRef}
contentStyle={styles.fitTextContent}
{...rest}
>
<div ref={measurerRef} style={styles.fitTextContentWrapper}>
<div ref={heightRef} style={styles.minContentHeight}>
{children}
</div>
</ContainWrapper>
Expand Down
2 changes: 1 addition & 1 deletion extensions/amp-fit-text/1.0/storybook/Basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default {
};

export const _default = () => {
const minFontSize = number('minFontSize', 6);
const minFontSize = number('minFontSize', 35);
const maxFontSize = number('maxFontSize', 72);
const width = number('width', 300);
const height = number('height', 200);
Expand Down

0 comments on commit 95d4fc6

Please sign in to comment.