Skip to content

Commit

Permalink
feat(tooltip): add keyboard shortcuts to tooltip (#4161)
Browse files Browse the repository at this point in the history
* feat(keyboard-key): component init

* chore(tools): plopfile syntax fix

* chore(tools): plopfile syntax fix

* chore(tools): plopfile syntax fix

* feat(keyboard-key):  styled w/ hook unit tests

* feat(keyboard-key):  added variants and styles

* chore(plop): update tsx dependency

* chore(keyboard-key): internal exports in core

* chore(keyboard-key): typedocs & build

* feat(keyboard-key): change to infline-flex style

* chore(keyboard-key): added stroy

* chore(keyboard-key): linting

* fix(keyboard-key): command logic

* feat(design-tokens): added new box shadows to support keyboard-keys

* chore(ci-cd): added chagesets

* fix(keyboard-key): boxShadow stylings

* fix(keyboard-key): remove null component wrapper

* fix(keyboard-key): aria-hidden

* chore(keyboard-key): refactor

* chore(keyboard-key): code cleanup

* chore(keyboard-key): code cleanup

* chore(keyboard-key): typedocs

* chore(keyboard-key): fix tests

* fix(keyboard-key): aria and diableBrowserShortcuts

* fix(keyboard-key): props fix

* chore(keyboard-key): playgorund storybook

* chore(keyboard-key): formatting fix

* chore(keyboard-key): stories update

* chore(keyboard-key): formatting fix

* chore(keyboard-key): typo

* Update .changeset/sweet-mugs-admire.md

Co-authored-by: Nora Krantz <[email protected]>

* Update .changeset/shaggy-sheep-confess.md

Co-authored-by: Nora Krantz <[email protected]>

* chore(keyboard-key): address PR comments

* feat(keyboard-tooltip): wip

* chore(tooltip): update types

* chore(tooltip): update types

* chore(tooltip): better var naming

* chore(tooltip): fail safe check

* chore(tooltip): linting

* chore(tooltip): linting

* chore(tooltip): yarn lock

* chore(tooltip): changeset

* chore(tooltip): fix spelling

* chore(tooltip): uppdate type name

* feat(tooltip): add anonymous keybaord action to tooltip

* Update packages/paste-core/components/tooltip/src/Tooltip.tsx

Co-authored-by: Sarah <[email protected]>

* fix(tooltip): update keyboardkey styles

* chore(tooltip): formatting

* Update packages/paste-core/components/tooltip/src/Tooltip.tsx

Co-authored-by: Nora Krantz <[email protected]>

---------

Co-authored-by: Nora Krantz <[email protected]>
Co-authored-by: Sarah <[email protected]>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Nov 19, 2024
1 parent dbd982f commit a720e5e
Show file tree
Hide file tree
Showing 8 changed files with 471 additions and 11 deletions.
6 changes: 6 additions & 0 deletions .changeset/happy-panthers-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@twilio-paste/tooltip": minor
"@twilio-paste/core": minor
---

[Tooltip] added the ability to put keyboard combinations using the KeyboardKey in the tooltip
2 changes: 2 additions & 0 deletions packages/paste-core/components/code-block/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@twilio-paste/flex": "^8.0.0",
"@twilio-paste/heading": "^11.0.0",
"@twilio-paste/icons": "^12.0.0",
"@twilio-paste/keyboard-key": "^0.0.0",
"@twilio-paste/reakit-library": "^2.0.0",
"@twilio-paste/screen-reader-only": "^13.0.0",
"@twilio-paste/spinner": "^14.0.0",
Expand Down Expand Up @@ -68,6 +69,7 @@
"@twilio-paste/flex": "^8.1.0",
"@twilio-paste/heading": "^11.1.0",
"@twilio-paste/icons": "^12.2.0",
"@twilio-paste/keyboard-key": "^0.0.0",
"@twilio-paste/reakit-library": "^2.1.1",
"@twilio-paste/screen-reader-only": "^13.1.0",
"@twilio-paste/spinner": "^14.1.2",
Expand Down
4 changes: 4 additions & 0 deletions packages/paste-core/components/tooltip/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
"@twilio-paste/customization": "^8.0.0",
"@twilio-paste/design-tokens": "^10.0.0",
"@twilio-paste/icons": "^12.0.0",
"@twilio-paste/keyboard-key": "^0.0.0",
"@twilio-paste/reakit-library": "^2.0.0",
"@twilio-paste/spinner": "^14.0.0",
"@twilio-paste/stack": "^8.1.0",
"@twilio-paste/style-props": "^9.0.0",
"@twilio-paste/styling-library": "^3.0.0",
"@twilio-paste/text": "^10.0.0",
Expand All @@ -52,8 +54,10 @@
"@twilio-paste/customization": "^8.1.0",
"@twilio-paste/design-tokens": "^10.2.0",
"@twilio-paste/icons": "^12.2.0",
"@twilio-paste/keyboard-key": "^0.0.0",
"@twilio-paste/reakit-library": "^2.1.0",
"@twilio-paste/spinner": "^14.1.0",
"@twilio-paste/stack": "^8.1.0",
"@twilio-paste/style-props": "^9.1.0",
"@twilio-paste/styling-library": "^3.0.0",
"@twilio-paste/text": "^10.1.0",
Expand Down
102 changes: 91 additions & 11 deletions packages/paste-core/components/tooltip/src/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Box, safelySpreadBoxProps } from "@twilio-paste/box";
import type { BoxProps } from "@twilio-paste/box";
import { KeyboardKey, KeyboardKeyGroup } from "@twilio-paste/keyboard-key";
import { Stack } from "@twilio-paste/stack";
import { Text } from "@twilio-paste/text";
import { StyledBase } from "@twilio-paste/theme";
import { TooltipPrimitive, TooltipPrimitiveReference, useTooltipPrimitiveState } from "@twilio-paste/tooltip-primitive";
Expand Down Expand Up @@ -60,17 +62,48 @@ export interface TooltipProps extends TooltipPrimitiveInitialState {
* @memberof TooltipProps
*/
text: string;
actionHeader?: never;
keyCombinationsActions?: never;
}

interface KeyboardActions {
name: string;
eventKeyCombination: string[];
disabled?: boolean;
}

export interface KeyboardKeyTooltipProps
extends Omit<TooltipProps, "text" | "keyCombinationsActions" | "actionHeader"> {
text?: never;
/**
* The mapping of action names to their respective key combinations.
*
* @type {Array<KeyboardActions>}
* @memberof KeyboardKeyTooltipProps
*/
keyCombinationsActions: Array<KeyboardActions>;
/**
* The header content of the Tooltip.
*
* @type {string}
* @memberof KeyboardKeyTooltipProps
*/
actionHeader?: string;
}

// Union will stop users from adding types from both TooltipProps and KeyboardKeyTooltipProps at the same time.
export type TooltipVariantProps = TooltipProps | KeyboardKeyTooltipProps;

/*
*Tooltip's current structure does not allow for customization of its arrow.
*TODO: refactor Tooltip so that the styling of its arrow can be customized
*using Customization Provider.
*/

const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
({ baseId, children, element = "TOOLTIP", state, text, ...props }, ref) => {
const Tooltip = React.forwardRef<HTMLDivElement, TooltipVariantProps>(
({ baseId, children, element = "TOOLTIP", state, text, actionHeader, keyCombinationsActions, ...props }, ref) => {
const tooltip = state || useTooltipPrimitiveState({ baseId: `paste-tooltip-${useUID()}`, ...props });

return (
<>
{React.Children.only(
Expand All @@ -82,15 +115,62 @@ const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
{/* import Paste Theme Based Styles due to portal positioning. */}
<StyledBase>
<TooltipArrow {...tooltip} />
<Text
element={`${element}_TEXT`}
as="span"
color="colorTextInverse"
fontSize="fontSize20"
lineHeight="lineHeight10"
>
{text}
</Text>
{text && !keyCombinationsActions && (
<Text
element={`${element}_TEXT`}
as="span"
color="colorTextInverse"
fontSize="fontSize20"
lineHeight="lineHeight10"
>
{text}
</Text>
)}
{keyCombinationsActions && !text && (
<Box color="colorTextInverse" fontSize="fontSize20" lineHeight="lineHeight10">
<Stack orientation="vertical" spacing="space40">
{actionHeader && (
<Text
element={`${element}_HEADER`}
fontWeight="fontWeightSemibold"
as="p"
color="inherit"
fontSize="inherit"
lineHeight="inherit"
>
{actionHeader}
</Text>
)}
{keyCombinationsActions.map((action, idx) => (
<Box display="flex" key={`action-${idx}`} justifyContent="space-between">
{action.name && (
<Text
element={`${element}_ACTION_TEXT`}
as="span"
color="inherit"
fontSize="inherit"
lineHeight="inherit"
marginRight="space70"
>
{action.name}
</Text>
)}
<KeyboardKeyGroup
variant="inverse"
element={`${element}_ACTION_KEY_GROUP`}
disabled={action.disabled}
>
{action.eventKeyCombination.map((key, i) => (
<KeyboardKey key={`key-${idx}-${i}`} element={`${element}_ACTION_KEY`}>
{key}
</KeyboardKey>
))}
</KeyboardKeyGroup>
</Box>
))}
</Stack>
</Box>
)}
</StyledBase>
</TooltipPrimitive>
</>
Expand Down
2 changes: 2 additions & 0 deletions packages/paste-core/components/tooltip/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import type { TooltipStateReturn } from "./Tooltip";
export { Tooltip, useTooltipState } from "./Tooltip";
export type {
TooltipProps,
TooltipVariantProps,
KeyboardKeyTooltipProps,
TooltipStateReturn,
UseTooltipInitialStateProps,
} from "./Tooltip";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import type { StoryFn } from "@storybook/react";
import { Anchor } from "@twilio-paste/anchor";
import { Box } from "@twilio-paste/box";
import { Button } from "@twilio-paste/button";
import { CustomizationProvider } from "@twilio-paste/customization";
import { InformationIcon } from "@twilio-paste/icons/esm/InformationIcon";
import { Stack } from "@twilio-paste/stack";
import { Text } from "@twilio-paste/text";
import { Theme, useTheme } from "@twilio-paste/theme";
import * as React from "react";

import { Tooltip, useTooltipState } from "../src";

// eslint-disable-next-line import/no-default-export
export default {
title: "Components/Tooltip/KeyboardKey",
excludeStories: ["StateHookExample"],
component: Tooltip,
parameters: {
chromatic: { delay: 3000, diffThreshold: 0.2 },
},
};

export const Default = (): React.ReactNode => {
return (
<Box as="div" minHeight="400px">
<Tooltip
visible
actionHeader="Search shortcuts"
keyCombinationsActions={[
{ name: "Mac", eventKeyCombination: ["Command", "K"] },
{ name: "Windows", eventKeyCombination: ["Control", "K"] },
]}
>
<Button aria-keyshortcuts="command+k" variant="primary">
Click to search
</Button>
</Tooltip>
</Box>
);
};

export const CustomizedTooltip: StoryFn = (_args, { parameters: { isTestEnvironment } }) => {
const currentTheme = useTheme();
return (
<CustomizationProvider
disableAnimations={isTestEnvironment}
theme={currentTheme}
elements={{
TOOLTIP: {
backgroundColor: "colorBackgroundErrorWeakest",
borderColor: "colorBorderDestructive",
textAlign: "center",
},
TOOLTIP_ACTION_TEXT: {
color: "colorTextErrorStrong",
},
TOOLTIP_HEADER: {
color: "colorTextLinkDestructive",
fontWeight: "fontWeightBold",
},
TOOLTIP_ACTION_KEY_GROUP: {
backgroundColor: "colorBackgroundStrong",
padding: "space30",
},
TOOLTIP_ACTION_KEY: {
backgroundColor: "colorBackgroundPrimary",
color: "colorTextInverse",
},
CUSTOM_TOOLTIP: {
backgroundColor: "colorBackgroundSuccessWeakest",
borderColor: "colorBorderSuccess",
textAlign: "left",
},
CUSTOM_TOOLTIP_ACTION_TEXT: {
color: "colorTextSuccess",
},
CUSTOM_TOOLTIP_HEADER: {
color: "colorTextLinkStrongest",
fontWeight: "fontWeightLight",
},
CUSTOM_TOOLTIP_ACTION_KEY_GROUP: {
backgroundColor: "colorBackgroundInverse",
padding: "space30",
},
CUSTOM_TOOLTIP_ACTION_KEY: {
backgroundColor: "colorBackgroundBusy",
color: "colorTextInverse",
fontFamily: "fontFamilyCode",
},
}}
>
<Box as="div" display="flex" columnGap="space80">
<Box minWidth="200px">
<Tooltip
visible
actionHeader="Search shortcuts"
keyCombinationsActions={[
{ name: "Mac", eventKeyCombination: ["Command", "K"] },
{ name: "Windows", eventKeyCombination: ["Control", "K"] },
]}
>
<Button aria-keyshortcuts="command+k" variant="primary">
Click to search
</Button>
</Tooltip>
</Box>
<Box minWidth="600px">
<Tooltip
element="CUSTOM_TOOLTIP"
visible
actionHeader="Search shortcuts"
keyCombinationsActions={[
{ name: "Mac", eventKeyCombination: ["Command", "K"] },
{ name: "Windows", eventKeyCombination: ["Control", "K"] },
]}
>
<Button aria-keyshortcuts="command+k" variant="primary">
Click to search
</Button>
</Tooltip>
</Box>
</Box>
</CustomizationProvider>
);
};

CustomizedTooltip.storyName = "Customized Tooltip";
CustomizedTooltip.parameters = {
parameters: {
chromatic: { disableSnapshot: true },
},
a11y: {
// no need to a11y check customization
disable: true,
},
};
Loading

0 comments on commit a720e5e

Please sign in to comment.