Skip to content

Commit

Permalink
chore: use css only to position button #2025
Browse files Browse the repository at this point in the history
  • Loading branch information
marek-mihok committed Aug 18, 2023
1 parent 4677eac commit f5fa3fc
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 48 deletions.
80 changes: 33 additions & 47 deletions ui/src/copyable_text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { B, S, U } from 'h2o-wave'
import React from 'react'
import { stylesheet } from 'typestyle'
import { clas, cssVar, pc } from './theme'
import ReactDOM from 'react-dom'

const
BUTTON_HEIGHT = 24,
Expand All @@ -20,7 +21,10 @@ const
},
btn: {
minWidth: 'initial',
position: 'fixed',
// position: 'fixed',
position: 'absolute',
top: CORNER_OFFSET,
right: CORNER_OFFSET,
width: BUTTON_WIDTH,
height: BUTTON_HEIGHT,
zIndex: 1,
Expand Down Expand Up @@ -64,7 +68,6 @@ export const ClipboardCopyButton = ({ value, anchorElement, showOnHoverOnly = fa
timeoutRef = React.useRef<U>(),
[copied, setCopied] = React.useState(false),
[visible, setVisible] = React.useState(!showOnHoverOnly),
[position, setPosition] = React.useState({ x: 0, y: 0 }),
onClick = async () => {
if (!anchorElement) return
try {
Expand All @@ -83,25 +86,8 @@ export const ClipboardCopyButton = ({ value, anchorElement, showOnHoverOnly = fa

React.useEffect(() => {
if (!anchorElement) return
const
{ left, top, width } = anchorElement.getBoundingClientRect(),
x = left + width - BUTTON_WIDTH - CORNER_OFFSET,
y = top + CORNER_OFFSET
setPosition({ x, y })

anchorElement.addEventListener('mouseenter', (ev) => {
setPosition(prevPosition => {
const target = ev.target as HTMLElement
if (!target) return prevPosition
const
rect = target.getBoundingClientRect(),
newX = rect.left + rect.width - BUTTON_WIDTH - CORNER_OFFSET,
newY = rect.top + CORNER_OFFSET
if (newX !== prevPosition.x || newY !== prevPosition.y) return { x: newX, y: newY }
return prevPosition
})
setVisible(true)
})
anchorElement.addEventListener('mouseenter', () => setVisible(true))
anchorElement.addEventListener('mouseleave', (ev: MouseEvent) => {
if ((ev.relatedTarget as HTMLElement)?.id === 'copybutton') return
setVisible(false)
Expand All @@ -115,7 +101,6 @@ export const ClipboardCopyButton = ({ value, anchorElement, showOnHoverOnly = fa
title='Copy to clipboard'
onClick={onClick}
iconProps={{ iconName: copied ? 'CheckMark' : 'Copy' }}
style={{ left: position.x, top: position.y }}
className={clas(css.btn, copied ? css.copiedBtn : '', showOnHoverOnly ? css.animate : '', visible ? css.visible : '')}
/>)
}
Expand All @@ -126,35 +111,36 @@ export const XCopyableText = ({ model }: { model: CopyableText }) => {
heightStyle = multiline && height === '1' ? fullHeightStyle : undefined,
[inputEl, setInputEl] = React.useState(),
domRef = React.useCallback(node => {
const inputEl = node?.children[0]?.children[1]?.children[0]
const inputEl = node?.children[0]?.children[1]
if (inputEl) setInputEl(inputEl)
}, [])

React.useEffect(() => {
if (!inputEl) return
ReactDOM.render(
ReactDOM.createPortal(<ClipboardCopyButton value={value} anchorElement={inputEl} showOnHoverOnly={!!multiline} />, inputEl),
document.createElement('div')
)
}, [inputEl, multiline, value])

return (
<>
<Fluent.TextField
data-test={name}
// Temporary solution which will be replaced with ref once TextField is converted to a function component.
elementRef={domRef}
value={value}
multiline={multiline}
label={label}
styles={{
root: {
...heightStyle,
textFieldRoot: { position: 'relative', width: pc(100) },
},
wrapper: heightStyle,
fieldGroup: heightStyle || { minHeight: height },
field: { ...heightStyle, height, resize: multiline ? 'vertical' : 'none', },
}}
readOnly
/>
<ClipboardCopyButton
anchorElement={inputEl}
showOnHoverOnly={!!multiline}
value={value}
/>
</>
<Fluent.TextField
data-test={name}
// Temporary solution which will be replaced with ref once TextField is converted to a function component.
elementRef={domRef}
value={value}
multiline={multiline}
label={label}
styles={{
root: {
...heightStyle,
textFieldRoot: { position: 'relative', width: pc(100) },
},
wrapper: heightStyle,
fieldGroup: heightStyle || { minHeight: height },
field: { ...heightStyle, height, resize: multiline ? 'vertical' : 'none', },
}}
readOnly
/>
)
}
2 changes: 1 addition & 1 deletion ui/src/markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ const highlightSyntax = async (str: S, language: S, codeBlockId: S) => {
const highlightedCode = language
? hljs.highlight(str, { language, ignoreIllegals: true }).value
: hljs.highlightAuto(str).value
codeBlock.outerHTML = `<code id="codeblock" class="hljs">${highlightedCode}</code>`
codeBlock.outerHTML = `<code id="codeblock" class="hljs" style="position:relative;">${highlightedCode}</code>`

const cb = document.getElementById('codeblock')
if (!cb) return
Expand Down

0 comments on commit f5fa3fc

Please sign in to comment.