Skip to content

Commit

Permalink
fix: copy to clipboard can now force collapse
Browse files Browse the repository at this point in the history
improved hover styling
  • Loading branch information
yougotwill committed Jul 8, 2024
1 parent 2e8918e commit 5a1990b
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 96 deletions.
8 changes: 4 additions & 4 deletions apps/staking/app/stake/node/[nodeId]/NodeStaking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { FEATURE_FLAG, useFeatureFlag } from '@/providers/feature-flag-provider'
import { useSessionStakingQuery } from '@/providers/sent-staking-provider';
import { ButtonDataTestId } from '@/testing/data-test-ids';
import { SENT_SYMBOL } from '@session/contracts';
import type { GetOpenNodesResponse } from '@session/sent-staking-js/client';
import type { GetOpenNodesResponse, OpenNode } from '@session/sent-staking-js/client';
import { generateOpenNodes } from '@session/sent-staking-js/test';
import { Loading } from '@session/ui/components/loading';
import { Button } from '@session/ui/ui/button';
Expand All @@ -27,7 +27,7 @@ export default function NodeStaking({ nodeId }: { nodeId: string }) {
if (showMockNodes && showNoNodes) {
console.error('Cannot show mock nodes and no nodes at the same time');
}

const { data, isLoading } = useSessionStakingQuery({
query: 'getOpenNodes',
args: undefined,
Expand Down Expand Up @@ -84,14 +84,14 @@ export function NodeStakingForm({ node }: { node: GetOpenNodesResponse['nodes'][
label={sessionNodeDictionary('publicKeyShort')}
tooltip={sessionNodeDictionary('publicKeyDescription')}
>
<PubKey pubKey={node.pubKey} alwaysShowCopyButton />
<PubKey pubKey={node.pubKey} force="collapse" alwaysShowCopyButton />
</ActionModuleRow>
<ActionModuleDivider />
<ActionModuleRow
label={sessionNodeDictionary('operatorAddress')}
tooltip={sessionNodeDictionary('operatorAddressTooltip')}
>
<PubKey pubKey={node.operatorAddress} alwaysShowCopyButton />
<PubKey pubKey={node.operatorAddress} force="collapse" alwaysShowCopyButton />
</ActionModuleRow>
<ActionModuleDivider />
<ActionModuleRow
Expand Down
2 changes: 1 addition & 1 deletion apps/staking/components/OpenNodeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const OpenNodeCard = forwardRef<
<span className="text-nowrap font-normal">
{titleFormat('format', { title: generalNodeDictionary('publicKeyShort') })}
</span>
<PubKey pubKey={pubKey} />
<PubKey pubKey={pubKey} force="collapse" />
</NodeCardTitle>
</div>
<NodeCardText className="col-span-10 mt-1 inline-flex max-h-max flex-row-reverse justify-center gap-2 text-center align-middle text-xs font-normal sm:justify-start sm:text-start md:mt-0 md:flex-row md:text-base">
Expand Down
165 changes: 78 additions & 87 deletions apps/staking/components/PubKey.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,97 +12,88 @@ type PubKeyType = HTMLAttributes<HTMLDivElement> & {
trailingChars?: number;
expandOnHover?: boolean;
alwaysShowCopyButton?: boolean;
forceExpand?: boolean;
force?: 'expand' | 'collapse';
};

const PubKey = forwardRef<HTMLDivElement, PubKeyType>(
(
{
className,
pubKey,
leadingChars,
trailingChars,
expandOnHover,
alwaysShowCopyButton,
forceExpand,
...props
},
ref
) => {
const dictionary = useTranslations('clipboard');
const [isExpanded, setIsExpanded] = useState(forceExpand ?? false);
const collapsedPubKey = useMemo(
() => (pubKey ? collapseString(pubKey, leadingChars ?? 6, trailingChars ?? 6) : ''),
[pubKey]
);
export const PubKey = forwardRef<HTMLDivElement, PubKeyType>((props, ref) => {
const {
className,
pubKey,
leadingChars,
trailingChars,
expandOnHover,
alwaysShowCopyButton,
force,
...rest
} = props;
const dictionary = useTranslations('clipboard');
const [isExpanded, setIsExpanded] = useState(force === 'expand' ?? false);
const collapsedPubKey = useMemo(
() => (pubKey ? collapseString(pubKey, leadingChars ?? 6, trailingChars ?? 6) : ''),
[pubKey]
);

const handleSelectionChange = useCallback(() => {
if (forceExpand) return;
const handleSelectionChange = useCallback(() => {
if (force === 'expand' || force === 'collapse') return;

const selection = window.getSelection();
if (
selection?.toString().includes(pubKey) ||
selection?.toString().includes(collapsedPubKey)
) {
setIsExpanded(true);
} else {
setIsExpanded(false);
}
}, [pubKey]);
const selection = window.getSelection();
if (selection?.toString().includes(pubKey) || selection?.toString().includes(collapsedPubKey)) {
setIsExpanded(true);
} else {
setIsExpanded(false);
}
}, [pubKey, collapsedPubKey, force]);

useEffect(() => {
/**
* Keeps the full pubkey visible when selected.
*/
document.addEventListener('selectionchange', handleSelectionChange);
return () => {
document.removeEventListener('selectionchange', handleSelectionChange);
};
}, [handleSelectionChange]);
useEffect(() => {
/**
* Keeps the full pubkey visible when selected.
*/
document.addEventListener('selectionchange', handleSelectionChange);
return () => {
document.removeEventListener('selectionchange', handleSelectionChange);
};
}, [handleSelectionChange]);

return (
<span ref={ref} className={cn('group flex select-all', className)} {...props}>
{!isExpanded ? (
<Tooltip>
<TooltipTrigger asChild disabled={expandOnHover}>
<span
className={cn(
'select-all break-all',
expandOnHover && 'group-hover:hidden',
expandOnHover && isExpanded ? 'hidden' : 'block'
)}
>
{collapsedPubKey}
</span>
</TooltipTrigger>
<TooltipContent>
<p>{pubKey}</p>
</TooltipContent>
</Tooltip>
) : null}
<div
className={cn(
'select-all break-all',
expandOnHover && 'group-hover:block',
(expandOnHover && isExpanded) || isExpanded ? 'block' : 'hidden'
)}
>
{pubKey}
</div>
<CopyToClipboardButton
className={cn(
'group-hover:block',
alwaysShowCopyButton || isExpanded ? 'block' : 'hidden'
)}
textToCopy={pubKey}
data-testid={ButtonDataTestId.Copy_Public_Key_To_Clipboard}
aria-label={dictionary('copyToClipboard')}
copyToClipboardToastMessage={dictionary('copyToClipboardSuccessToast')}
/>
</span>
);
}
);
return (
<span ref={ref} className={cn('group flex select-all items-center', className)} {...rest}>
{!isExpanded ? (
<Tooltip>
<TooltipTrigger asChild disabled={expandOnHover}>
<span
className={cn(
'select-all break-all',
force !== 'collapse' && expandOnHover && 'group-hover:hidden',
force !== 'collapse' && expandOnHover && isExpanded ? 'hidden' : 'block'
)}
>
{collapsedPubKey}
</span>
</TooltipTrigger>
<TooltipContent>
<p>{pubKey}</p>
</TooltipContent>
</Tooltip>
) : null}
<div
className={cn(
'select-all break-all',
force !== 'collapse' && expandOnHover && 'group-hover:block',
(force !== 'collapse' && expandOnHover && isExpanded) || isExpanded ? 'block' : 'hidden'
)}
>
{pubKey}
</div>
<CopyToClipboardButton
className={cn(
'group-hover:bg-session-green group-hover:text-session-black *:group-hover:fill-session-black mx-1 p-0.5 duration-0 group-hover:opacity-100',
alwaysShowCopyButton || isExpanded ? 'opacity-100' : 'opacity-0'
)}
textToCopy={pubKey}
data-testid={ButtonDataTestId.Copy_Public_Key_To_Clipboard}
aria-label={dictionary('copyToClipboard')}
copyToClipboardToastMessage={dictionary('copyToClipboardSuccessToast')}
/>
</span>
);
});
PubKey.displayName = 'PubKey';

export { PubKey };
6 changes: 3 additions & 3 deletions apps/staking/components/StakedNodeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -376,20 +376,20 @@ const StakedNodeCard = forwardRef<
{dictionary('lastUptime', { time: formatLocalizedRelativeTimeToNowClient(lastUptime) })}
</CollapsableContent>
{/** NOTE - ensure any changes here still work with the pubkey component */}
<NodeCardText className="flex w-full flex-row flex-wrap gap-1 peer-checked:mt-1 peer-checked:[&>span>span>button]:block peer-checked:[&>span>span>div]:block peer-checked:[&>span>span>span]:hidden">
<NodeCardText className="flex w-full flex-row flex-wrap gap-1 peer-checked:mt-1 peer-checked:[&>span>span>button]:opacity-100 peer-checked:[&>span>span>div]:block peer-checked:[&>span>span>span]:hidden">
{address && isNodeOperator(node, address) ? <NodeOperatorIndicator /> : null}
<span className="inline-flex flex-nowrap gap-1">
<RowLabel>
{titleFormat('format', { title: generalNodeDictionary('publicKeyShort') })}
</RowLabel>
<PubKey pubKey={pubKey} expandOnHover />
<PubKey pubKey={pubKey} expandOnHover={true} />
</span>
</NodeCardText>
<CollapsableContent className="inline-flex gap-1">
<RowLabel>
{titleFormat('format', { title: generalNodeDictionary('operatorAddress') })}
</RowLabel>
<PubKey pubKey={node.operator_address} expandOnHover />
<PubKey pubKey={node.operator_address} expandOnHover={true} />
</CollapsableContent>
<CollapsableContent>
<RowLabel>
Expand Down
3 changes: 2 additions & 1 deletion packages/ui/components/CopyToClipboardButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ const CopyToClipboardButton = forwardRef<HTMLButtonElement, CopyToClipboardButto
<Button
onClick={() => copyToClipboard(textToCopy, copyToClipboardToastMessage, onCopyComplete)}
variant="ghost"
className={cn(className, 'select-all p-0')}
rounded={'md'}
className={cn('select-all p-0', className)}
ref={ref}
{...props}
data-testid={props['data-testid']}
Expand Down

0 comments on commit 5a1990b

Please sign in to comment.