Skip to content

Commit

Permalink
Update EuiButtonGroup to use EuiTooltip instead of the default browse…
Browse files Browse the repository at this point in the history
…r title attribute
  • Loading branch information
davismcphee committed Jan 14, 2024
1 parent 9b5b111 commit b5dfa76
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 47 deletions.
3 changes: 3 additions & 0 deletions src-docs/src/views/button/button_group_icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ export default () => {
label: 'Underline',
name: 'underline',
iconType: 'editorUnderline',
title: 'Underline with a custom title',
titleDelay: 'short',
titlePosition: 'bottom',
},
{
id: `${idPrefix3}6`,
Expand Down
2 changes: 1 addition & 1 deletion src/components/button/button_group/button_group.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const euiButtonGroupButtonsStyles = (euiThemeContext: UseEuiTheme) => {
fullWidth: css`
${logicalCSS('width', '100%')}
.euiButtonGroupButton {
.euiButtonGroupButton__tooltipAnchor {
flex: 1;
}
`,
Expand Down
17 changes: 15 additions & 2 deletions src/components/button/button_group/button_group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { EuiScreenReaderOnly } from '../../accessibility';
import { CommonProps } from '../../common';

import { _EuiButtonColor } from '../../../themes/amsterdam/global_styling/mixins';
import { EuiToolTipProps } from '../../../components/tool_tip';
import { EuiButtonDisplayContentProps } from '../button_display/_button_display_content';
import { EuiButtonGroupButton } from './button_group_button';
import {
Expand Down Expand Up @@ -41,6 +42,18 @@ export interface EuiButtonGroupOptionProps
* The type of the underlying HTML button
*/
type?: 'button' | 'submit' | 'reset';
/**
* Custom title content for the button, only used if isIconOnly is true
*/
title?: EuiToolTipProps['content'];
/**
* Custom title delay
*/
titleDelay?: EuiToolTipProps['delay'];
/**
* Custom title position
*/
titlePosition?: EuiToolTipProps['position'];
}

export type EuiButtonGroupProps = CommonProps & {
Expand Down Expand Up @@ -172,10 +185,10 @@ export const EuiButtonGroup: FunctionComponent<Props> = ({
</EuiScreenReaderOnly>

<div css={cssStyles} className="euiButtonGroup__buttons">
{options.map((option, index) => {
{options.map((option) => {
return (
<EuiButtonGroupButton
key={index}
key={option.id}
isDisabled={isDisabled}
{...(option as EuiButtonGroupOptionProps)}
onClick={
Expand Down
62 changes: 37 additions & 25 deletions src/components/button/button_group/button_group_button.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,30 @@ export const euiButtonGroupButtonStyles = (euiThemeContext: UseEuiTheme) => {
const uncompressedBorderRadii = (
radiusSize: CSSProperties['borderRadius']
) => `
border-radius: 0;
& > .euiButtonGroupButton {
border-radius: 0;
}
&:first-child {
&:first-child > .euiButtonGroupButton {
${logicalShorthandCSS('border-radius', `${radiusSize} 0 0 ${radiusSize}`)}
}
&:last-child {
&:last-child > .euiButtonGroupButton {
${logicalShorthandCSS('border-radius', `0 ${radiusSize} ${radiusSize} 0`)}
}
`;

return {
// Base
euiButtonGroupButton: css`
euiButtonGroupButtonTooltipAnchor: css`
/* Allow button to shrink and truncate */
${logicalCSS('min-width', 0)}
flex-shrink: 1;
flex-grow: 0;
`,
euiButtonGroupButton: css`
${logicalCSS('width', '100%')}
${logicalCSS('min-width', 0)}
${euiCanAnimate} {
transition: background-color ${euiTheme.animation.normal} ease-in-out,
Expand All @@ -77,40 +83,46 @@ export const euiButtonGroupButtonStyles = (euiThemeContext: UseEuiTheme) => {
${uncompressedBorderRadii(euiTheme.border.radius.medium)}
`,
uncompressed: css`
&:is(.euiButtonGroupButton-isSelected) {
& > .euiButtonGroupButton:is(.euiButtonGroupButton-isSelected) {
font-weight: ${euiTheme.font.weight.bold};
}
/* "Borders" between buttons - should be present between two of the same colored buttons,
and absent between selected vs non-selected buttons (different colors) */
&:not(.euiButtonGroupButton-isSelected)
+ .euiButtonGroupButton:not(.euiButtonGroupButton-isSelected) {
&:not(.euiButtonGroupButton__tooltipAnchor-isSelected)
+ .euiButtonGroupButton__tooltipAnchor:not(
.euiButtonGroupButton__tooltipAnchor-isSelected
)
> .euiButtonGroupButton {
box-shadow: -${euiTheme.border.width.thin} 0 0 0 ${transparentize(euiTheme.colors.fullShade, 0.1)};
}
&:is(.euiButtonGroupButton-isSelected)
+ .euiButtonGroupButton-isSelected {
&:is(.euiButtonGroupButton__tooltipAnchor-isSelected)
+ .euiButtonGroupButton__tooltipAnchor-isSelected
> .euiButtonGroupButton {
box-shadow: -${euiTheme.border.width.thin} 0 0 0 ${transparentize(euiTheme.colors.emptyShade, 0.2)};
}
`,
compressed: css`
${logicalCSS('height', compressedButtonHeight)}
line-height: ${compressedButtonHeight};
/* Offset the background color from the border by clipping background to before the padding starts */
padding: ${mathWithUnits(euiTheme.border.width.thin, (x) => x * 2)};
background-clip: content-box;
/* Tweak border radius to account for the padding & background-clip */
border-radius: ${mathWithUnits(
[controlCompressedBorderRadius, euiTheme.border.width.thin],
(x, y) => x + y
)};
font-weight: ${euiTheme.font.weight.regular};
&:is(.euiButtonGroupButton-isSelected) {
font-weight: ${euiTheme.font.weight.semiBold};
& > .euiButtonGroupButton {
${logicalCSS('height', compressedButtonHeight)}
line-height: ${compressedButtonHeight};
/* Offset the background color from the border by clipping background to before the padding starts */
padding: ${mathWithUnits(euiTheme.border.width.thin, (x) => x * 2)};
background-clip: content-box;
/* Tweak border radius to account for the padding & background-clip */
border-radius: ${mathWithUnits(
[controlCompressedBorderRadius, euiTheme.border.width.thin],
(x, y) => x + y
)};
font-weight: ${euiTheme.font.weight.regular};
&:is(.euiButtonGroupButton-isSelected) {
font-weight: ${euiTheme.font.weight.semiBold};
}
}
`,
// States
Expand Down
65 changes: 46 additions & 19 deletions src/components/button/button_group/button_group_button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import classNames from 'classnames';
import React, { FunctionComponent, MouseEventHandler } from 'react';
import React, { FunctionComponent, MouseEventHandler, useRef } from 'react';

import { useEuiTheme } from '../../../services';
import { useEuiButtonColorCSS } from '../../../themes/amsterdam/global_styling/mixins/button';
Expand All @@ -20,6 +20,7 @@ import {
_compressedButtonFocusColor,
_uncompressedButtonFocus,
} from './button_group_button.styles';
import { EuiToolTip } from '../../../components/tool_tip';

type Props = EuiButtonGroupOptionProps & {
/**
Expand Down Expand Up @@ -54,6 +55,10 @@ export const EuiButtonGroupButton: FunctionComponent<Props> = ({
value, // Prevent prop from being spread
size,
color: _color = 'primary',
title,
titleDelay = 'long',
titlePosition = 'top',
onClick,
...rest
}) => {
const isCompressed = size === 'compressed';
Expand All @@ -70,8 +75,6 @@ export const EuiButtonGroupButton: FunctionComponent<Props> = ({
const cssStyles = [
styles.euiButtonGroupButton,
isIconOnly && styles.iconOnly,
styles[size!],
!isCompressed && styles.uncompressed,
isDisabled && isSelected ? styles.disabledAndSelected : buttonColorStyles,
!isDisabled && focusColorStyles,
];
Expand Down Expand Up @@ -100,25 +103,49 @@ export const EuiButtonGroupButton: FunctionComponent<Props> = ({
* the base width of the button via the `euiTextShift()` method in SASS.
*/
const [buttonTextRef, innerText] = useInnerText();
const tooltipRef = useRef<EuiToolTip>(null);

const onClickOverride: React.MouseEventHandler<HTMLButtonElement> = (e) => {
// Blur the tooltip so it doesn't stick around after click until rehovered/refocused
tooltipRef.current?.onBlur();
onClick(e);
};

return (
<EuiButtonDisplay
css={cssStyles}
className={buttonClasses}
isDisabled={isDisabled}
size={size === 'compressed' ? 's' : size}
contentProps={{ css: contentStyles }}
textProps={{
css: textStyles,
ref: buttonTextRef,
'data-text': innerText,
<EuiToolTip
ref={tooltipRef}
content={isIconOnly ? title || innerText : undefined}
delay={titleDelay}
position={titlePosition}
anchorProps={{
className: classNames('euiButtonGroupButton__tooltipAnchor', {
'euiButtonGroupButton__tooltipAnchor-isSelected': isSelected,
}),
css: [
styles.euiButtonGroupButtonTooltipAnchor,
styles[size!],
!isCompressed && styles.uncompressed,
],
}}
title={innerText}
data-test-subj={id}
isSelected={isSelected}
{...rest}
>
{label}
</EuiButtonDisplay>
<EuiButtonDisplay
css={cssStyles}
className={buttonClasses}
isDisabled={isDisabled}
size={size === 'compressed' ? 's' : size}
contentProps={{ css: contentStyles }}
textProps={{
css: textStyles,
ref: buttonTextRef,
'data-text': innerText,
}}
data-test-subj={id}
isSelected={isSelected}
onClick={onClickOverride}
{...rest}
>
{label}
</EuiButtonDisplay>
</EuiToolTip>
);
};

0 comments on commit b5dfa76

Please sign in to comment.