Skip to content

Commit ce7014d

Browse files
committed
Added optional FloatingArrow to TextAnnotatorPopup
1 parent 5abe652 commit ce7014d

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import { ReactNode, useEffect, useMemo, useState } from 'react';
1+
import { ReactNode, useEffect, useMemo, useRef, useState } from 'react';
22
import { useAnnotator, useSelection } from '@annotorious/react';
33
import { isRevived, NOT_ANNOTATABLE_CLASS, TextAnnotation, TextAnnotator } from '@recogito/text-annotator';
44
import { isMobile } from './isMobile';
55
import {
6+
arrow,
67
autoUpdate,
78
flip,
9+
FloatingArrow,
10+
FloatingArrowProps,
811
FloatingFocusManager,
912
FloatingPortal,
1013
inline,
@@ -22,6 +25,10 @@ interface TextAnnotationPopupProps {
2225

2326
ariaCloseWarning?: string;
2427

28+
arrow?: boolean;
29+
30+
arrowProps?: Omit<FloatingArrowProps, 'context' | 'ref'>;
31+
2532
popup(props: TextAnnotationPopupContentProps): ReactNode;
2633

2734
}
@@ -46,6 +53,22 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => {
4653

4754
const [isOpen, setOpen] = useState(selected?.length > 0);
4855

56+
const arrowRef = useRef(null);
57+
58+
// Conditional floating-ui middleware
59+
const middleware = useMemo(() => {
60+
const m = [
61+
inline(),
62+
offset(10),
63+
flip({ crossAxis: true }),
64+
shift({ crossAxis: true, padding: 10 })
65+
];
66+
67+
return props.arrow
68+
? [...m, arrow({ element: arrowRef }) ]
69+
: m;
70+
}, [props.arrow]);
71+
4972
const { refs, floatingStyles, update, context } = useFloating({
5073
placement: isMobile() ? 'bottom' : 'top',
5174
open: isOpen,
@@ -55,12 +78,7 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => {
5578
r?.cancelSelected();
5679
}
5780
},
58-
middleware: [
59-
offset(10),
60-
inline(),
61-
flip(),
62-
shift({ mainAxis: false, crossAxis: true, padding: 10 })
63-
],
81+
middleware,
6482
whileElementsMounted: autoUpdate
6583
});
6684

@@ -132,6 +150,13 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => {
132150
event
133151
})}
134152

153+
{props.arrow && (
154+
<FloatingArrow
155+
ref={arrowRef}
156+
context={context}
157+
{...(props.arrowProps || {})} />
158+
)}
159+
135160
<button className="r6o-popup-sr-only" aria-live="assertive" onClick={onClose}>
136161
{props.ariaCloseWarning || 'Click or leave this dialog to close it.'}
137162
</button>

packages/text-annotator-react/test/App.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ export const App: FC = () => {
190190
</TextAnnotator>
191191

192192
<TextAnnotatorPopup
193+
arrow
194+
arrowProps={{
195+
fill: '#000000'
196+
}}
193197
popup={
194198
props => (<TestPopup {...props} />)
195199
}

packages/text-annotator-react/test/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
p {
2727
font-size: 17px;
2828
line-height: 160%;
29+
min-width: 600px;
2930
}
3031

3132
.r6o-popup {

0 commit comments

Comments
 (0)