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: 
This commit is contained in:
@@ -40,7 +40,7 @@ function ButtonGroupItem({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ToolbarButton editor={editor} item={item} key={item.key}>
|
<ToolbarButton editor={editor} item={item} key={item.key}>
|
||||||
{<item.ChildComponent />}
|
<item.ChildComponent />
|
||||||
</ToolbarButton>
|
</ToolbarButton>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import type { LexicalEditor } from 'lexical'
|
import type { LexicalEditor } from 'lexical'
|
||||||
|
|
||||||
|
import { Button } from '@payloadcms/ui'
|
||||||
import React, { type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
import React, { type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { createPortal } from 'react-dom'
|
import { createPortal } from 'react-dom'
|
||||||
|
|
||||||
@@ -19,15 +20,17 @@ export function DropDownItem({
|
|||||||
children,
|
children,
|
||||||
editor,
|
editor,
|
||||||
enabled,
|
enabled,
|
||||||
|
Icon,
|
||||||
item,
|
item,
|
||||||
title,
|
tooltip,
|
||||||
}: {
|
}: {
|
||||||
active?: boolean
|
active?: boolean
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
editor: LexicalEditor
|
editor: LexicalEditor
|
||||||
enabled?: boolean
|
enabled?: boolean
|
||||||
|
Icon: React.ReactNode
|
||||||
item: ToolbarGroupItem
|
item: ToolbarGroupItem
|
||||||
title?: string
|
tooltip?: string
|
||||||
}): React.ReactNode {
|
}): React.ReactNode {
|
||||||
const [className, setClassName] = useState<string>(baseClass)
|
const [className, setClassName] = useState<string>(baseClass)
|
||||||
|
|
||||||
@@ -61,8 +64,14 @@ export function DropDownItem({
|
|||||||
}, [ref, registerItem])
|
}, [ref, registerItem])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<Button
|
||||||
|
aria-label={tooltip}
|
||||||
|
buttonStyle="none"
|
||||||
className={className}
|
className={className}
|
||||||
|
disabled={enabled === false}
|
||||||
|
icon={Icon}
|
||||||
|
iconPosition="left"
|
||||||
|
iconStyle="none"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (enabled !== false) {
|
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.
|
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()
|
e.preventDefault()
|
||||||
}}
|
}}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
title={title}
|
tooltip={tooltip}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: var(--theme-elevation-900);
|
color: var(--theme-elevation-900);
|
||||||
transition: background-color 0.15s cubic-bezier(0, 0.2, 0.2, 1);
|
transition: background-color 0.15s cubic-bezier(0, 0.2, 0.2, 1);
|
||||||
|
position: relative;
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -91,6 +92,13 @@
|
|||||||
opacity: 0.2;
|
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-left: 6.25px;
|
||||||
padding-right: 6.25px;
|
padding-right: 6.25px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ const ToolbarItem = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let title = item.key
|
let title = item.key
|
||||||
|
let croppedTitle = item.key
|
||||||
if (item.label) {
|
if (item.label) {
|
||||||
title =
|
title =
|
||||||
typeof item.label === 'function'
|
typeof item.label === 'function'
|
||||||
@@ -57,13 +58,22 @@ const ToolbarItem = ({
|
|||||||
}
|
}
|
||||||
// Crop title to max. 25 characters
|
// Crop title to max. 25 characters
|
||||||
if (title.length > 25) {
|
if (title.length > 25) {
|
||||||
title = title.substring(0, 25) + '...'
|
croppedTitle = title.substring(0, 25) + '...'
|
||||||
|
} else {
|
||||||
|
croppedTitle = title
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropDownItem active={active} editor={editor} enabled={enabled} item={item} key={item.key}>
|
<DropDownItem
|
||||||
{item?.ChildComponent && <item.ChildComponent />}
|
active={active}
|
||||||
<span className="text">{title}</span>
|
editor={editor}
|
||||||
|
enabled={enabled}
|
||||||
|
Icon={item?.ChildComponent ? <item.ChildComponent /> : undefined}
|
||||||
|
item={item}
|
||||||
|
key={item.key}
|
||||||
|
tooltip={title}
|
||||||
|
>
|
||||||
|
<span className="text">{croppedTitle}</span>
|
||||||
</DropDownItem>
|
</DropDownItem>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ export const Button = forwardRef<HTMLAnchorElement | HTMLButtonElement, Props>((
|
|||||||
Link,
|
Link,
|
||||||
newTab,
|
newTab,
|
||||||
onClick,
|
onClick,
|
||||||
|
onMouseDown,
|
||||||
round,
|
round,
|
||||||
size = 'medium',
|
size = 'medium',
|
||||||
SubMenuPopupContent,
|
SubMenuPopupContent,
|
||||||
@@ -114,6 +115,7 @@ export const Button = forwardRef<HTMLAnchorElement | HTMLButtonElement, Props>((
|
|||||||
className: !SubMenuPopupContent ? [classes, styleClasses].join(' ') : classes,
|
className: !SubMenuPopupContent ? [classes, styleClasses].join(' ') : classes,
|
||||||
disabled,
|
disabled,
|
||||||
onClick: !disabled ? handleClick : undefined,
|
onClick: !disabled ? handleClick : undefined,
|
||||||
|
onMouseDown: !disabled ? onMouseDown : undefined,
|
||||||
onPointerEnter: tooltip ? () => setShowTooltip(true) : undefined,
|
onPointerEnter: tooltip ? () => setShowTooltip(true) : undefined,
|
||||||
onPointerLeave: tooltip ? () => setShowTooltip(false) : undefined,
|
onPointerLeave: tooltip ? () => setShowTooltip(false) : undefined,
|
||||||
rel: newTab ? 'noopener noreferrer' : undefined,
|
rel: newTab ? 'noopener noreferrer' : undefined,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export type Props = {
|
|||||||
Link?: React.ElementType
|
Link?: React.ElementType
|
||||||
newTab?: boolean
|
newTab?: boolean
|
||||||
onClick?: (event: MouseEvent) => void
|
onClick?: (event: MouseEvent) => void
|
||||||
|
onMouseDown?: (event: MouseEvent) => void
|
||||||
round?: boolean
|
round?: boolean
|
||||||
secondaryActions?: secondaryAction | secondaryAction[]
|
secondaryActions?: secondaryAction | secondaryAction[]
|
||||||
size?: 'large' | 'medium' | 'small'
|
size?: 'large' | 'medium' | 'small'
|
||||||
|
|||||||
Reference in New Issue
Block a user