Skip to content

Commit

Permalink
Merge pull request #1683 from oasisprotocol/mz/floatingCopyBtn
Browse files Browse the repository at this point in the history
Add optional floating copy to clipboard button to JSON code preview
  • Loading branch information
buberdds authored Jan 10, 2025
2 parents fa76f74 + 0a1a32d commit 1d6eca6
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 16 deletions.
1 change: 1 addition & 0 deletions .changelog/1683.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add optional floating copy to clipboard button to JSON code preview
30 changes: 18 additions & 12 deletions src/app/components/CodeDisplay/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { FC, ReactNode } from 'react'
import { FC, ReactNode, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
import { styled } from '@mui/material/styles'
import { ScrollableDataDisplay } from '../../components/ScrollableDataDisplay'
import { CopyToClipboard } from '../../components/CopyToClipboard'
import { CopyToClipboard, FloatingCopyToClipboard } from '../../components/CopyToClipboard'
import { useScreenSize } from '../../hooks/useScreensize'
import { base64ToHex } from '../../utils/helpers'

Expand All @@ -13,31 +13,36 @@ type CodeDisplayProps = {
copyToClipboardValue: string
label?: string
extraTopPadding?: boolean
withCopyButton?: boolean
floatingCopyButton?: boolean
}

const CodeDisplay: FC<CodeDisplayProps> = ({
code,
copyToClipboardValue,
label,
extraTopPadding,
withCopyButton = true,
floatingCopyButton = false,
}) => {
const { t } = useTranslation()
const { isMobile } = useScreenSize()
const [isHovering, setIsHovering] = useState(false)

if (!code) {
return null
}

return (
<>
<Box
sx={{ flex: 1, position: 'relative' }}
onMouseEnter={() => setIsHovering(true)}
onMouseLeave={() => setIsHovering(false)}
>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
my: 3,
my: floatingCopyButton ? 0 : 3,
pt: extraTopPadding ? 4 : 0,
}}
>
Expand All @@ -46,16 +51,17 @@ const CodeDisplay: FC<CodeDisplayProps> = ({
{label}
</Typography>
)}
{withCopyButton && (
{floatingCopyButton ? (
<FloatingCopyToClipboard isVisible={isHovering} value={copyToClipboardValue} />
) : (
<CopyToClipboard
value={copyToClipboardValue}
label={isMobile ? t('common.copy') : t('contract.copyButton', { subject: label })}
/>
)}
</Box>

<ScrollableDataDisplay data={code} />
</>
</Box>
)
}

Expand Down Expand Up @@ -83,18 +89,18 @@ const StyledPre = styled('pre')({
type JsonCodeDisplayProps = {
data: Record<string, any>
label?: string
withCopyButton?: boolean
floatingCopyButton?: boolean
}

export const JsonCodeDisplay: FC<JsonCodeDisplayProps> = ({ data, label, withCopyButton = true }) => {
export const JsonCodeDisplay: FC<JsonCodeDisplayProps> = ({ data, label, floatingCopyButton }) => {
const formattedJson = JSON.stringify(data, null, 2)

return (
<CodeDisplay
code={<StyledPre>{formattedJson}</StyledPre>}
copyToClipboardValue={formattedJson}
label={label}
withCopyButton={withCopyButton}
floatingCopyButton={floatingCopyButton}
/>
)
}
41 changes: 38 additions & 3 deletions src/app/components/CopyToClipboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ import Button from '@mui/material/Button'
const clipboardTooltipDuration = 2000

type CopyToClipboardProps = {
floating?: boolean
isFloatingVisible?: boolean
value: string
label?: string
}

const StyledIconButton = styled(ButtonBase)(({ theme }) => ({
const StyledIconButton = styled(ButtonBase, {
shouldForwardProp: prop => prop !== 'floating' && prop !== 'isFloatingVisible',
})<{ floating?: boolean; isFloatingVisible?: boolean }>(({ theme, floating, isFloatingVisible }) => ({
display: 'inline-flex',
alignItems: 'center',
border: 0,
Expand All @@ -24,9 +28,34 @@ const StyledIconButton = styled(ButtonBase)(({ theme }) => ({
fontFamily: 'inherit',
padding: 0,
marginLeft: theme.spacing(4),
...(floating && {
position: 'absolute',
right: theme.spacing(5),
top: theme.spacing(4),
opacity: isFloatingVisible ? 1 : 0,
transition: 'opacity 0.2s ease-in-out',
zIndex: theme.zIndex.fab,
boxShadow: theme.shadows[1],
background: COLORS.white,
borderRadius: '50%',
width: 40,
height: 40,
display: 'flex',
justifyContent: 'center',
marginLeft: 0,
}),
}))

export const CopyToClipboard: FC<CopyToClipboardProps> = ({ value, label }) => {
type FloatingCopyToClipboardProps = {
isVisible: boolean
value: string
}

export const FloatingCopyToClipboard: FC<FloatingCopyToClipboardProps> = ({ isVisible, value }) => {
return <CopyToClipboard floating isFloatingVisible={isVisible} value={value} />
}

export const CopyToClipboard: FC<CopyToClipboardProps> = ({ label, floating, isFloatingVisible, value }) => {
const { t } = useTranslation()
const timeout = useRef<number | undefined>(undefined)
const ariaLabel = t('clipboard.label')
Expand Down Expand Up @@ -59,7 +88,13 @@ export const CopyToClipboard: FC<CopyToClipboardProps> = ({ value, label }) => {
{label}
</Button>
) : (
<StyledIconButton color="inherit" onClick={handleCopyToClipboard} aria-label={ariaLabel}>
<StyledIconButton
floating={floating}
isFloatingVisible={isFloatingVisible}
color="inherit"
onClick={handleCopyToClipboard}
aria-label={ariaLabel}
>
<ContentCopyIcon sx={{ fontSize: '1.25em', color: COLORS.brandDark }} />
</StyledIconButton>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/app/pages/RuntimeTransactionDetailPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ export const RuntimeTransactionDetailView: FC<{
<>
<dt>{t('transaction.rawData')}</dt>
<dd>
<JsonCodeDisplay data={transaction.body} withCopyButton={false} />
<JsonCodeDisplay data={transaction.body} floatingCopyButton />
</dd>
</>
)}
Expand Down

0 comments on commit 1d6eca6

Please sign in to comment.