feat(richtext-lexical): add tooltips to toolbar dropdown items (#9218)

Previously, if the dropdown item text is cut off due to length, there
was no way to view the full text.

Now, you can hover:

![CleanShot 2024-11-14 at 18 55
11@2x](https://github.com/user-attachments/assets/b160c172-c78a-4eb5-9fb3-b4ef8aee7eb5)
This commit is contained in:
Alessio Gravili
2024-11-14 19:29:12 -07:00
committed by GitHub
parent e6e0cc2a63
commit 729488028b
6 changed files with 40 additions and 10 deletions

View File

@@ -40,7 +40,7 @@ function ButtonGroupItem({
return (
<ToolbarButton editor={editor} item={item} key={item.key}>
{<item.ChildComponent />}
<item.ChildComponent />
</ToolbarButton>
)
}

View File

@@ -1,6 +1,7 @@
'use client'
import type { LexicalEditor } from 'lexical'
import { Button } from '@payloadcms/ui'
import React, { type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { createPortal } from 'react-dom'
@@ -19,15 +20,17 @@ export function DropDownItem({
children,
editor,
enabled,
Icon,
item,
title,
tooltip,
}: {
active?: boolean
children: React.ReactNode
editor: LexicalEditor
enabled?: boolean
Icon: React.ReactNode
item: ToolbarGroupItem
title?: string
tooltip?: string
}): React.ReactNode {
const [className, setClassName] = useState<string>(baseClass)
@@ -61,8 +64,14 @@ export function DropDownItem({
}, [ref, registerItem])
return (
<button
<Button
aria-label={tooltip}
buttonStyle="none"
className={className}
disabled={enabled === false}
icon={Icon}
iconPosition="left"
iconStyle="none"
onClick={() => {
if (enabled !== false) {
editor._updateTags = new Set(['toolbar', ...editor._updateTags]) // without setting the tags, our onSelect will not be able to trigger our onChange as focus onChanges are ignored.
@@ -82,11 +91,11 @@ export function DropDownItem({
e.preventDefault()
}}
ref={ref}
title={title}
tooltip={tooltip}
type="button"
>
{children}
</button>
</Button>
)
}

View File

@@ -75,6 +75,7 @@
cursor: pointer;
color: var(--theme-elevation-900);
transition: background-color 0.15s cubic-bezier(0, 0.2, 0.2, 1);
position: relative;
.text {
overflow: hidden;
@@ -91,6 +92,13 @@
opacity: 0.2;
}
.btn__icon {
// Override default button icon styles that
// set a background color when focused
background: none !important;
background-color: none !important;
}
padding-left: 6.25px;
padding-right: 6.25px;
width: 100%;

View File

@@ -49,6 +49,7 @@ const ToolbarItem = ({
}
let title = item.key
let croppedTitle = item.key
if (item.label) {
title =
typeof item.label === 'function'
@@ -57,13 +58,22 @@ const ToolbarItem = ({
}
// Crop title to max. 25 characters
if (title.length > 25) {
title = title.substring(0, 25) + '...'
croppedTitle = title.substring(0, 25) + '...'
} else {
croppedTitle = title
}
return (
<DropDownItem active={active} editor={editor} enabled={enabled} item={item} key={item.key}>
{item?.ChildComponent && <item.ChildComponent />}
<span className="text">{title}</span>
<DropDownItem
active={active}
editor={editor}
enabled={enabled}
Icon={item?.ChildComponent ? <item.ChildComponent /> : undefined}
item={item}
key={item.key}
tooltip={title}
>
<span className="text">{croppedTitle}</span>
</DropDownItem>
)
}

View File

@@ -63,6 +63,7 @@ export const Button = forwardRef<HTMLAnchorElement | HTMLButtonElement, Props>((
Link,
newTab,
onClick,
onMouseDown,
round,
size = 'medium',
SubMenuPopupContent,
@@ -114,6 +115,7 @@ export const Button = forwardRef<HTMLAnchorElement | HTMLButtonElement, Props>((
className: !SubMenuPopupContent ? [classes, styleClasses].join(' ') : classes,
disabled,
onClick: !disabled ? handleClick : undefined,
onMouseDown: !disabled ? onMouseDown : undefined,
onPointerEnter: tooltip ? () => setShowTooltip(true) : undefined,
onPointerLeave: tooltip ? () => setShowTooltip(false) : undefined,
rel: newTab ? 'noopener noreferrer' : undefined,

View File

@@ -20,6 +20,7 @@ export type Props = {
Link?: React.ElementType
newTab?: boolean
onClick?: (event: MouseEvent) => void
onMouseDown?: (event: MouseEvent) => void
round?: boolean
secondaryActions?: secondaryAction | secondaryAction[]
size?: 'large' | 'medium' | 'small'