diff --git a/packages/core/src/components/Text/Text.tsx b/packages/core/src/components/Text/Text.tsx index 04bbca5664..69a0191a02 100644 --- a/packages/core/src/components/Text/Text.tsx +++ b/packages/core/src/components/Text/Text.tsx @@ -10,7 +10,7 @@ import { withStaticProps } from "../../types"; import styles from "./Text.module.scss"; export interface TextProps extends TypographyProps { - type: TextType; + type?: TextType; weight?: TextWeight; children: ReactNode; } diff --git a/packages/core/src/components/Tipseen/__stories__/tipseen.mdx b/packages/core/src/components/Tipseen/__stories__/tipseen.mdx index 946cafec63..242a277ab0 100644 --- a/packages/core/src/components/Tipseen/__stories__/tipseen.mdx +++ b/packages/core/src/components/Tipseen/__stories__/tipseen.mdx @@ -81,7 +81,7 @@ Wrap your custom media with `TipseenMedia` component. This use case is good for Use Floating Tipseen in case where the guidance is not relevant to a specific UI element, but general. In this case, the Tipseen position will be the right corner of the screen and without an arrow tip. - + ## Do’s and Don’ts @@ -96,7 +96,9 @@ In this case, the Tipseen position will be the right corner of the screen and wi modifiers={modifiers} position={Tipseen.positions.RIGHT} color={Tipseen.colors.INVERTED} - content={ {}} />} + content={ + {}} /> + } >
{" "} @@ -118,8 +120,7 @@ In this case, the Tipseen position will be the right corner of the screen and wi
), - description: - "Don’t finish the Tipseen wizard process with a disabled CTA." + description: "Don’t finish the Tipseen wizard process with a disabled CTA." } }, { @@ -157,7 +158,11 @@ In this case, the Tipseen position will be the right corner of the screen and wi modifiers={modifiers} position={Tipseen.positions.TOP} color={Tipseen.colors.INVERTED} - content={You still have 14 days on your free trial, enjoy it! At the end you can choose your favorite plan.} + content={ + + You still have 14 days on your free trial, enjoy it! At the end you can choose your favorite plan. + + } >
@@ -172,7 +177,7 @@ In this case, the Tipseen position will be the right corner of the screen and wi ) } }, - { + { positive: { component: (
@@ -189,8 +194,7 @@ In this case, the Tipseen position will be the right corner of the screen and wi
), - description: - "Add a pointer to indicate the specific component that the tipseen comes from." + description: "Add a pointer to indicate the specific component that the tipseen comes from." }, negative: { component: ( @@ -209,8 +213,7 @@ In this case, the Tipseen position will be the right corner of the screen and wi
), - description: - "Don’t use a tipseen without a pointer, unless it’s a general tipseen for an entire screen." + description: "Don’t use a tipseen without a pointer, unless it’s a general tipseen for an entire screen." } } ]} diff --git a/packages/core/src/components/Tipseen/__stories__/tipseen.stories.scss b/packages/core/src/components/Tipseen/__stories__/tipseen.stories.scss index 35dd89f6af..94dd121ebf 100644 --- a/packages/core/src/components/Tipseen/__stories__/tipseen.stories.scss +++ b/packages/core/src/components/Tipseen/__stories__/tipseen.stories.scss @@ -24,7 +24,6 @@ $component-rules-grid-cell-array-calc: calc(50% - #{$tipseen-rules-cell-min-widt } &_image { - width: 320px; height: 175px; } @@ -69,7 +68,7 @@ $component-rules-grid-cell-array-calc: calc(50% - #{$tipseen-rules-cell-min-widt height: 100%; display: flex; flex-direction: column; - justify-content: center + justify-content: center; } &_small-box { diff --git a/packages/core/src/components/Tooltip/Tooltip.module.scss b/packages/core/src/components/Tooltip/Tooltip.module.scss index 772d6fbe44..a71af678af 100644 --- a/packages/core/src/components/Tooltip/Tooltip.module.scss +++ b/packages/core/src/components/Tooltip/Tooltip.module.scss @@ -12,9 +12,36 @@ $tooltip-z-index: 9999999999999999; max-width: var(--tooltip-max-width, 50vw); word-break: break-word; + &.tooltipWithContent { + padding: unset; + } + &.withMaxWidth { --tooltip-max-width: 240px; } + + .image { + display: block; + position: relative; + border-top-right-radius: 2px; + border-top-left-radius: 2px; + padding: 2px 2px 0 2px; + object-fit: cover; + width: 100%; + height: 100%; + min-width: var(--tooltip-max-width); + z-index: 1; + } + + .title { + @include vibe-text(text2, bold); + } + + .content { + word-break: break-word; + display: inline-block; + padding: var(--tooltip-padding, #{var(--spacing-small) var(--spacing-medium)}); + } } .tooltip.paddingSizeMd { diff --git a/packages/core/src/components/Tooltip/Tooltip.tsx b/packages/core/src/components/Tooltip/Tooltip.tsx index ea440f38dc..c20915af2b 100644 --- a/packages/core/src/components/Tooltip/Tooltip.tsx +++ b/packages/core/src/components/Tooltip/Tooltip.tsx @@ -13,6 +13,9 @@ import { MoveBy } from "../../types/MoveBy"; import { getStyle } from "../../helpers/typesciptCssModulesHelper"; import styles from "./Tooltip.module.scss"; import { ComponentDefaultTestId, getTestId } from "../../tests/test-ids-utils"; +import { SubIcon } from "../../types"; +import Icon from "../Icon/Icon"; +import Flex from "../Flex/Flex"; export type TooltipProps = TooltipBaseProps & (TooltipWithChildrenProps | TooltipWithoutChildrenProps); @@ -100,7 +103,7 @@ interface TooltipBaseProps extends VibeComponentProps { */ showOnDialogEnter?: boolean; /** - * A Classname to be added to element which wraps the children + * A Classname to be added to element which wraps the children */ referenceWrapperClassName?: string; /** @@ -115,11 +118,23 @@ interface TooltipBaseProps extends VibeComponentProps { * Overwrites z-index of the tooltip */ zIndex?: number; - // TODO: make defualt next major + // TODO: make default next major /** * Limit tooltip to 240px */ withMaxWidth?: boolean; + /** + * The title of the tooltip + */ + title?: string; + /** + * The image of the tooltip + */ + image?: string; + /** + * The icon of the tooltip next to the title + */ + icon?: SubIcon; } // When last tooltip was shown in the last 1.5 second - the next tooltip will be shown immediately const IMMEDIATE_SHOW_THRESHOLD_MS = 1500; @@ -175,7 +190,7 @@ export default class Tooltip extends PureComponent { } renderTooltipContent() { - const { theme, content, paddingSize, className, style, withMaxWidth } = this.props; + const { theme, content, paddingSize, className, style, withMaxWidth, title, image, icon } = this.props; if (!content) { // don't render empty tooltip return null; @@ -192,6 +207,34 @@ export default class Tooltip extends PureComponent { if (!contentValue) { return null; } + + if (title || image) { + return ( +
+ {image && } +
+ {title && ( + + {icon && } +
{title}
+
+ )} + {contentValue} +
+
+ ); + } + + // TODO: remove in next major, use (title || image) variant instead return (
{ - return
Text
; -}; - -export default TooltipContent; diff --git a/packages/core/src/components/Tooltip/__stories__/TooltipLineWrapper.jsx b/packages/core/src/components/Tooltip/__stories__/TooltipLineWrapper.jsx deleted file mode 100644 index a6197191e4..0000000000 --- a/packages/core/src/components/Tooltip/__stories__/TooltipLineWrapper.jsx +++ /dev/null @@ -1,39 +0,0 @@ -import React from "react"; -import cx from "classnames"; -import Tooltip from "../Tooltip"; -import TooltipContent from "./TooltipContent"; -import "./tooltip-story.scss"; - -const SHOW_HIDE_TRIGGER = ["click"]; - -const TooltipLineWrapper = ({ justify = "center", position = "top", theme = "dark" }) => { - const isBottom = position.indexOf("bottom") > -1; - return ( -
-
-
- } - showTrigger={SHOW_HIDE_TRIGGER} - hideTrigger={SHOW_HIDE_TRIGGER} - > -
- -
-
- ); -}; -TooltipLineWrapper.propTypes = {}; -TooltipLineWrapper.defaultProps = {}; -export default TooltipLineWrapper; diff --git a/packages/core/src/components/Tooltip/__stories__/TooltipReference.jsx b/packages/core/src/components/Tooltip/__stories__/TooltipReference.jsx deleted file mode 100644 index e2d8e25048..0000000000 --- a/packages/core/src/components/Tooltip/__stories__/TooltipReference.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from "react"; -import cx from "classnames"; -import "./TooltipReference.scss"; - -const TooltipReference = () => { - return ( -
-
-
-
-
- ); -}; - -export default TooltipReference; diff --git a/packages/core/src/components/Tooltip/__stories__/TooltipReference.scss b/packages/core/src/components/Tooltip/__stories__/TooltipReference.scss deleted file mode 100644 index af4f77f39c..0000000000 --- a/packages/core/src/components/Tooltip/__stories__/TooltipReference.scss +++ /dev/null @@ -1,20 +0,0 @@ -.tooltip-reference-container { - background-color: var(--sb-disabled-background-color); - width: 40px; - height: 40px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - transition: background-color 0.15s ease-in; - &:hover { - background-color: var(--sb-primary-background-hover-color); - } - .tooltip-reference-dot { - background-color: var(--sb-inverted-color-background); - width: 6px; - height: 6px; - margin: 0 2px; - border-radius: 50%; - } -} diff --git a/packages/core/src/components/Tooltip/__stories__/assets/tooltip-image.png b/packages/core/src/components/Tooltip/__stories__/assets/tooltip-image.png new file mode 100644 index 0000000000..92061c0161 Binary files /dev/null and b/packages/core/src/components/Tooltip/__stories__/assets/tooltip-image.png differ diff --git a/packages/core/src/components/Tooltip/__stories__/tooltip-story.scss b/packages/core/src/components/Tooltip/__stories__/tooltip-story.scss deleted file mode 100644 index de7ddb62ab..0000000000 --- a/packages/core/src/components/Tooltip/__stories__/tooltip-story.scss +++ /dev/null @@ -1,17 +0,0 @@ -.tooltip-empty-element { - &.bottom { - margin: 0 auto 48px 0; - } - &.right { - width: 1px; - height: 2px; - margin: 20px auto 0 0; - } - width: 89px; - height: 2px; - margin: 48px auto 0 0; -} -.width-20 { - width: 20%; - height: 80px; -} diff --git a/packages/core/src/components/Tooltip/__stories__/tooltip.mdx b/packages/core/src/components/Tooltip/__stories__/tooltip.mdx index 32e029a8b0..ad1223e2fc 100644 --- a/packages/core/src/components/Tooltip/__stories__/tooltip.mdx +++ b/packages/core/src/components/Tooltip/__stories__/tooltip.mdx @@ -3,10 +3,15 @@ import { Canvas, Meta } from "@storybook/blocks"; import { Bolt } from "../../Icon/Icons"; import Icon from "../../Icon/Icon"; import Button from "../../Button/Button"; +import TabList from "../../Tabs/TabList/TabList"; +import Tab from "../../Tabs/Tab/Tab"; +import Link from "../../Link/Link.tsx"; +import IconButton from "../../IconButton/IconButton"; import { CHIP, LABEL, TIPSEEN } from "../../../storybook/components/related-components/component-description-map"; import "./tooltip.stories.scss"; import * as TooltipStories from "./tooltip.stories"; -import { TipOtherComponents } from "./tooltip.stories.helpers"; +import { TipOtherComponents, modifiers } from "./tooltip.stories.helpers"; +import image from "./assets/tooltip-image.png"; @@ -17,14 +22,14 @@ import { TipOtherComponents } from "./tooltip.stories.helpers"; - [Usage](#usage) - [Variants](#variants) - [Themes](#themes) -- [Do’s and don’ts](#dos-and-donts) +- [Do's and don'ts](#dos-and-donts) - [Use cases and examples](#use-cases-and-examples) - [Related components](#related-components) - [Feedback](#feedback) ## Overview -Tooltips show contextual help or information about specific components when a user hovers on them. +Tooltips provide helpful information and can include detailed context about a specific component when a user hovers on it. @@ -36,8 +41,10 @@ Tooltips show contextual help or information about specific components when a us @@ -45,40 +52,137 @@ Tooltips show contextual help or information about specific components when a us ## Variants -### Positions +### Tooltip with title -Tooltip’s arrow can appear from top, bottom, left or right. +Use tooltip with title when you want to present more complex content and you need to add a heading to emphasize the main idea. Titles can also come with an icon. - + + +### Tooltip with image + +Use tooltip with image to provide a preview for an image or when giving a closer look at a feature. + + -### Themes +### Positions -Tooltip’s arrow can have various themes. +Tooltip's arrow can appear from top, bottom, left or right. - + -## Do’s and Don’ts +## Do's and Don'ts -
- -
+ + ), - description: "Use tooltips for adding alternative textual purpose for buttons which do not include any text." + description: "Use tooltips for interactive imagery." }, negative: { component: ( - + ), - description: "Don't use a tooltip to display information already written on the button text." + description: "Don't use tooltips to restate visible UI text." + } + }, + { + positive: { + component: ( + + Boards + Items + + ), + description: "If an element doesn't need additional clarification, don't use a tooltip." + }, + negative: { + component: ( + + + Boards + + Items + + ), + description: "Don't use tooltips to restate text that is already displayed within the element." + } + }, + { + positive: { + component: ( + + I have a title, text, image and I can come{" "} + . +
+ } + > +
+ + ), + description: "Add links inline and in the same color of the text." + }, + negative: { + component: ( + + I have a title, text, image and I can come with a link. +
+ } + > +
+ + ), + description: "Don't add links on a separate line or in a different color from the text." + } + }, + { + positive: { + component: ( + +
+ + ), + description: "Use this app to visualize data." + }, + negative: { + component: ( + +
+ + ), + description: "Don't add an image just for aesthetic reasons, or if it doesn't help the user." } } ]} diff --git a/packages/core/src/components/Tooltip/__stories__/tooltip.stories.helpers.js b/packages/core/src/components/Tooltip/__stories__/tooltip.stories.helpers.tsx similarity index 83% rename from packages/core/src/components/Tooltip/__stories__/tooltip.stories.helpers.js rename to packages/core/src/components/Tooltip/__stories__/tooltip.stories.helpers.tsx index ad2e65fcce..212e94a7e3 100644 --- a/packages/core/src/components/Tooltip/__stories__/tooltip.stories.helpers.js +++ b/packages/core/src/components/Tooltip/__stories__/tooltip.stories.helpers.tsx @@ -10,6 +10,7 @@ export const modifiers = [ { name: "flip", options: { + // @ts-ignore fallbackPlacements: [] } } @@ -19,12 +20,12 @@ export const TipOtherComponents = () => ( As tooltips only surface from a hover, never include links or buttons in the copy. If your tooltip requires either of these, considers putting your content in a{" "} - - Tipseen + + Attention box {" "} or{" "} - - Attention box. + + Dialog. ); diff --git a/packages/core/src/components/Tooltip/__stories__/tooltip.stories.js b/packages/core/src/components/Tooltip/__stories__/tooltip.stories.js deleted file mode 100644 index d8915f3136..0000000000 --- a/packages/core/src/components/Tooltip/__stories__/tooltip.stories.js +++ /dev/null @@ -1,174 +0,0 @@ -import Tooltip from "../Tooltip"; -import { capitalize } from "lodash-es"; -import TooltipReference from "./TooltipReference"; -import { Hide, Subitems } from "../../Icon/Icons"; -import Icon from "../../Icon/Icon"; -import { modifiers } from "./tooltip.stories.helpers"; -import { TooltipTheme } from "../TooltipConstants"; -import "./tooltip.stories.scss"; - -export default { - title: "Popover/Tooltip", - component: Tooltip -}; - -const tooltipTemplate = args => { - return ( -
- -
- -
- ); -}; - -export const Overview = { - render: tooltipTemplate.bind({}), - name: "Overview", - - args: { - shouldShowOnMount: true, - content: "I'm a tooltip" - }, - - parameters: { - chromatic: { - pauseAnimationAtEnd: true - } - } -}; - -export const Positions = { - // The modifier's purpose is to prevent the tipseen from being displayed when the user scrolls the story upwards / downwards. - render: - // Therefore, there is no need to move this prop in your implementations. - () => { - return ( - <> -
- -
- -
-
- -
- -
-
- -
- -
-
- -
- -
- - ); - }, - - name: "Positions", - - parameters: { - chromatic: { - pauseAnimationAtEnd: true - } - } -}; - -export const Themes = { - render: () => - Object.values(TooltipTheme).map(theme => ( -
- -
- -
- )), - - name: "Themes" -}; - -export const IconTooltip = { - render: () => ( -
- -
- -
-
-
- ), - - name: "Icon tooltip" -}; - -export const DefinitionTooltip = { - render: () => ( -
- -
- - Subitem -
-
-
- ), - - name: "Definition tooltip" -}; - -export const ImmediateTooltips = { - render: () => ( -
- - - - - - - - - -
- ), - - name: "Immediate tooltips" -}; diff --git a/packages/core/src/components/Tooltip/__stories__/tooltip.stories.scss b/packages/core/src/components/Tooltip/__stories__/tooltip.stories.scss index 3b3627abc9..da53290c72 100644 --- a/packages/core/src/components/Tooltip/__stories__/tooltip.stories.scss +++ b/packages/core/src/components/Tooltip/__stories__/tooltip.stories.scss @@ -5,45 +5,65 @@ gap: 16px; } - &_icon-wrapper { + &_title { + padding: 30px 0; display: flex; - padding: 6px; - gap: 8px; - align-items: center; - background-color: var(--sb-disabled-background-color); - cursor: pointer; - &:hover { - background-color: var(--sb-primary-background-hover-color); - } } - &_icon-box { - background-color: var(--sb-color-winter); - width: 54px; - height: 54px; + &_image { + padding: 120px 0; display: flex; - align-items: center; - justify-content: center; + + &__tooltip > img { + min-height: 135px; + } } - &_top { - padding: 0 64px 68px 0; - margin: 0 32px; + &_tabs { + ul, + li { + padding: 0; + margin: 0; + } + } + + &_position-left { + position: relative; + left: -25%; } - &_bottom { - padding: 50px 0 0 0; - margin: 0 32px; + &_link { + color: var(--text-color-on-primary); + text-decoration: underline; } - &_left { - padding: 0 64px 8px 64px; - margin: 0 64px; + &_position-bottom { + position: relative; + top: 25%; } - &_right { - padding: 0 32px 8px 32px; - margin: 0 32px; + &_positions { + display: flex; + align-items: center; + + > :nth-child(1) { + padding: 0 64px 68px 0; + margin: 0 32px; + } + + > :nth-child(2) { + padding: 50px 0 0 0; + margin: 0 32px; + } + > :nth-child(3) { + padding: 0 32px 8px 32px; + margin: 0 32px; + } + + > :nth-child(4) { + padding: 0 64px 8px 64px; + margin: 0 64px; + } } &_overview { diff --git a/packages/core/src/components/Tooltip/__stories__/tooltip.stories.tsx b/packages/core/src/components/Tooltip/__stories__/tooltip.stories.tsx new file mode 100644 index 0000000000..5b2814543a --- /dev/null +++ b/packages/core/src/components/Tooltip/__stories__/tooltip.stories.tsx @@ -0,0 +1,166 @@ +import Tooltip, { TooltipProps } from "../Tooltip"; +import { Hide, Menu, Subitems } from "../../Icon/Icons"; +import Button from "../../Button/Button"; +import Flex from "../../Flex/Flex"; +import IconButton from "../../IconButton/IconButton"; +import { modifiers } from "./tooltip.stories.helpers"; +import "./tooltip.stories.scss"; +import image from "./assets/tooltip-image.png"; +import { createStoryMetaSettingsDecorator } from "../../../storybook"; + +const metaSettings = createStoryMetaSettingsDecorator({ + component: Tooltip, + iconPropNamesArray: ["icon"] +}); + +export default { + title: "Popover/Tooltip", + component: Tooltip, + argTypes: metaSettings.argTypes, + decorators: metaSettings.decorators +}; + +const tooltipTemplate = (args: TooltipProps) => { + return ( +
+ +
+ +
+ ); +}; + +export const Overview = { + render: tooltipTemplate.bind({}), + name: "Overview", + args: { + shouldShowOnMount: true, + content: "I'm a tooltip" + }, + parameters: { + chromatic: { + pauseAnimationAtEnd: true + } + } +}; + +export const TooltipWithTitle = () => ( +
+ +
+ +
+); + +export const TooltipWithImage = () => ( +
+ +
+ +
+); + +export const Positions = { + render: () => { + return ( +
+
+ {/* The modifier's purpose is to prevent the tipseen from being displayed when the user scrolls the story upwards / downwards. + Therefore, there is no need to move this prop in your implementations. */} + +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ ); + }, + name: "Positions", + parameters: { + chromatic: { + pauseAnimationAtEnd: true + } + } +}; + +export const IconTooltip = () => ( + + + +); + +export const DefinitionTooltip = () => ( + + + +); + +export const ImmediateTooltips = () => ( + + + + + + + + + + + +); diff --git a/packages/core/src/storybook/components/related-components/descriptions/tooltip-description.jsx b/packages/core/src/storybook/components/related-components/descriptions/tooltip-description.jsx index 792aa64b86..c849f111ff 100644 --- a/packages/core/src/storybook/components/related-components/descriptions/tooltip-description.jsx +++ b/packages/core/src/storybook/components/related-components/descriptions/tooltip-description.jsx @@ -1,6 +1,6 @@ import { useMemo } from "react"; import { RelatedComponent } from "vibe-storybook-components"; -import TooltipLineWrapper from "../../../../components/Tooltip/__stories__/TooltipLineWrapper"; +import Tooltip from "../../../../components/Tooltip/Tooltip"; export const TooltipDescription = () => { const component = useMemo(() => { @@ -9,7 +9,9 @@ export const TooltipDescription = () => { }; return (
- + +
+
); }, []); diff --git a/packages/storybook-blocks/src/styles/tokens/colors.scss b/packages/storybook-blocks/src/styles/tokens/colors.scss index 43a1d31f5c..67c37612d2 100644 --- a/packages/storybook-blocks/src/styles/tokens/colors.scss +++ b/packages/storybook-blocks/src/styles/tokens/colors.scss @@ -26,7 +26,7 @@ --sb-text-color-fixed-dark: #323338; --sb-inverted-color-background: #323338; --sb-disabled-background-color: #ecedf5; - --sb-primary-background-hover-color: #dcdfec; + --sb-primary-background-hover-color: rgba(103, 104, 121, 0.1); --sb-dark-background-color: #f6f7fb; --sb-brand-color: #5034ff; }