diff --git a/packages/react/src/components/Tooltip/next/DefinitionTooltip.js b/packages/react/src/components/Tooltip/next/DefinitionTooltip.js new file mode 100644 index 000000000000..49bea88f49ae --- /dev/null +++ b/packages/react/src/components/Tooltip/next/DefinitionTooltip.js @@ -0,0 +1,70 @@ +/** + * Copyright IBM Corp. 2016, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import PropTypes from 'prop-types'; +import React, { useState } from 'react'; +import { Popover, PopoverContent } from '../../Popover'; +import { match, keys } from '../../../internal/keyboard'; +import { usePrefix } from '../../../internal/usePrefix'; +import { useId } from '../../../internal/useId'; + +function DefinitionTooltip({ children, definition, ...rest }) { + const [isOpen, setOpen] = useState(false); + const prefix = usePrefix(); + const id = useId(); + + function handleKeyDown(event) { + if (isOpen && match(event, keys.Escape)) { + event.stopPropagation(); + setOpen(false); + } + } + + return ( + { + setOpen(false); + }} + open={isOpen}> + + + {definition} + + + ); +} + +DefinitionTooltip.propTypes = { + /** + * Provide the content being defined + */ + children: PropTypes.node, + + /** + * Provide the content being defined + */ + definition: PropTypes.string.isRequired, +}; + +export { DefinitionTooltip }; diff --git a/packages/react/src/components/Tooltip/next/Tooltip.stories.js b/packages/react/src/components/Tooltip/next/Tooltip.stories.js index ff23db16a297..e0abfcda687d 100644 --- a/packages/react/src/components/Tooltip/next/Tooltip.stories.js +++ b/packages/react/src/components/Tooltip/next/Tooltip.stories.js @@ -10,6 +10,7 @@ import './story.scss'; import { Checkbox16 } from '@carbon/icons-react'; import React from 'react'; import { Tooltip } from '../next'; +import { DefinitionTooltip } from './DefinitionTooltip.js'; export default { title: 'Experimental/unstable_Tooltip', @@ -68,6 +69,22 @@ export const Duration = () => { ); }; +export const Definition = () => { + const definition = + 'Uniform Resource Locator; the address of a resource (such as a document or website) on the Internet.'; + return ( +
+

+ Custom domains direct requests for your apps in this Cloud Foundry + organization to a{' '} + URL that + you own. A custom domain can be a shared domain, a shared subdomain, or + a shared domain and host. +

+
+ ); +}; + const PlaygroundStory = (props) => { const { align, diff --git a/packages/react/src/components/Tooltip/next/__tests__/DefinitionTooltip-test.js b/packages/react/src/components/Tooltip/next/__tests__/DefinitionTooltip-test.js new file mode 100644 index 000000000000..d2eeaa9c7a49 --- /dev/null +++ b/packages/react/src/components/Tooltip/next/__tests__/DefinitionTooltip-test.js @@ -0,0 +1,50 @@ +/** + * Copyright IBM Corp. 2016, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import { DefinitionTooltip } from '../../next/DefinitionTooltip'; + +describe('DefintiionTooltip', () => { + it('should support a custom className with the `className` prop', () => { + const definition = 'Uniform Resource Locator'; + render( + + URL + + ); + expect(screen.getByText('URL')).toHaveClass('tooltip-class'); + }); + + it('should apply additional props to the outermost element', () => { + const definition = 'Uniform Resource Locator'; + render( + + URL + + ); + expect(screen.getByText('URL')).toHaveAttribute('data-testid', 'test'); + }); + + it('should display onClick a defintion provided via prop', () => { + const definition = 'Uniform Resource Locator'; + render( + + URL + + ); + userEvent.click(screen.getByText('URL')); + expect(screen.getByText(definition)).toHaveTextContent(definition); + }); +}); diff --git a/packages/styles/scss/components/tooltip/_index.scss b/packages/styles/scss/components/tooltip/_index.scss index a8d2eef640b9..3f06a3a645f8 100644 --- a/packages/styles/scss/components/tooltip/_index.scss +++ b/packages/styles/scss/components/tooltip/_index.scss @@ -10,3 +10,4 @@ @include tooltip.tooltip; @include tooltip.icon-tooltip; +@include tooltip.definition-tooltip; diff --git a/packages/styles/scss/components/tooltip/_tooltip.scss b/packages/styles/scss/components/tooltip/_tooltip.scss index 1b9154810811..2986026106cd 100644 --- a/packages/styles/scss/components/tooltip/_tooltip.scss +++ b/packages/styles/scss/components/tooltip/_tooltip.scss @@ -11,6 +11,8 @@ @use '../../type'; @use '../../utilities/custom-property'; @use '../../utilities/convert'; +@use '../../utilities/button-reset'; +@use '../../utilities/focus-outline'; $tooltip-padding-block: custom-property.get-var( 'tooltip-padding-block', @@ -37,6 +39,34 @@ $tooltip-padding-inline: custom-property.get-var( } } +@mixin definition-tooltip { + .#{$prefix}--definition-term { + @include button-reset.reset; + + border-bottom: 1px dotted theme.$border-strong; + border-radius: 0; + + color: theme.$text-primary; + } + + .#{$prefix}--definition-term:focus { + @include focus-outline.focus-outline; + + border-bottom-color: theme.$border-interactive; + } + + .#{$prefix}--definition-term:hover { + border-bottom-color: theme.$border-interactive; + } + + .#{$prefix}--definition-tooltip { + @include type.type-style('body-long-01'); + + max-width: convert.rem(176px); + padding: convert.rem(8px) convert.rem(16px); + } +} + @mixin icon-tooltip { .#{$prefix}--icon-tooltip { @include custom-property.declaration(