-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(react): add toggletip component (#10365)
* feat(react): add toggletip component * chore: check-in work * feat(react): add toggletip component * chore: revert icon button changes and update custom property usage * Update packages/react/src/components/Toggletip/index.js Co-authored-by: Taylor Jones <[email protected]> * feat(styles): update link tokens, toggletip styles * feat(button,toggletip): add button-focus-color component token Co-authored-by: Taylor Jones <[email protected]> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
- Loading branch information
1 parent
a7112be
commit 7ef288a
Showing
14 changed files
with
618 additions
and
6 deletions.
There are no files selected for viewing
26 changes: 26 additions & 0 deletions
26
packages/react/src/components/Toggletip/__tests__/Toggletip-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/** | ||
* 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. | ||
*/ | ||
|
||
describe('Toggletip', () => { | ||
describe('accessibility', () => { | ||
test.todo('accessibility-checker'); | ||
test.todo('axe'); | ||
}); | ||
|
||
// Usage | ||
it.todo('should toggle visibility on click'); | ||
it.todo('should toggle visibility on Enter and Space'); | ||
it.todo('should close on Escape'); | ||
it.todo('should close if an element outside of the toggletip is clicked'); | ||
|
||
describe('Component API', () => { | ||
it.todo('should support custom elements with the `as` prop'); | ||
it.todo('should support a custom class name with the `className` prop'); | ||
it.todo('should support different alignments with the `align` prop'); | ||
it.todo('should initially be open if `defaultOpen` is set to true'); | ||
}); | ||
}); |
12 changes: 12 additions & 0 deletions
12
packages/react/src/components/Toggletip/__tests__/ToggletipActions-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/** | ||
* 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. | ||
*/ | ||
|
||
describe('ToggletipActions', () => { | ||
describe('Component API', () => { | ||
it.todo('should support a custom class name with the `className` prop'); | ||
}); | ||
}); |
13 changes: 13 additions & 0 deletions
13
packages/react/src/components/Toggletip/__tests__/ToggletipButton.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* 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. | ||
*/ | ||
|
||
describe('ToggletipButton', () => { | ||
describe('Component API', () => { | ||
it.todo('should support a custom class name with the `className` prop'); | ||
it.todo('should use the `label` prop as the label for the <button>'); | ||
}); | ||
}); |
12 changes: 12 additions & 0 deletions
12
packages/react/src/components/Toggletip/__tests__/ToggletipContent-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/** | ||
* 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. | ||
*/ | ||
|
||
describe('ToggletipContent', () => { | ||
describe('Component API', () => { | ||
it.todo('should support a custom class name with the `className` prop'); | ||
}); | ||
}); |
13 changes: 13 additions & 0 deletions
13
packages/react/src/components/Toggletip/__tests__/ToggletipLabel-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* 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. | ||
*/ | ||
|
||
describe('ToggletipLabel', () => { | ||
describe('Component API', () => { | ||
it.todo('should support custom elements with the `as` prop'); | ||
it.todo('should support a custom class name with the `className` prop'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
/** | ||
* 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 cx from 'classnames'; | ||
import PropTypes from 'prop-types'; | ||
import React, { useContext, useRef, useState } from 'react'; | ||
import { Popover, PopoverContent } from '../Popover'; | ||
import { match, keys } from '../../internal/keyboard'; | ||
import { useWindowEvent } from '../../internal/useEvent'; | ||
import { useId } from '../../internal/useId'; | ||
import { usePrefix } from '../../internal/usePrefix'; | ||
|
||
/** | ||
* Used to render the label for a Toggletip | ||
*/ | ||
function ToggletipLabel({ | ||
as: BaseComponent = 'span', | ||
children, | ||
className: customClassName, | ||
}) { | ||
const prefix = usePrefix(); | ||
const className = cx(`${prefix}--toggletip-label`, customClassName); | ||
return <BaseComponent className={className}>{children}</BaseComponent>; | ||
} | ||
|
||
ToggletipLabel.propTypes = { | ||
/** | ||
* Provide a custom element or component to render the top-level node for the | ||
* component. | ||
*/ | ||
as: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType]), | ||
|
||
/** | ||
* Custom children to be rendered as the content of the label | ||
*/ | ||
children: PropTypes.node, | ||
|
||
/** | ||
* Provide a custom class name to be added to the outermost node in the | ||
* component | ||
*/ | ||
className: PropTypes.string, | ||
}; | ||
|
||
// Used to coordinate accessibility props between button and content along with | ||
// the actions to open and close the toggletip | ||
const ToggletipContext = React.createContext(); | ||
|
||
function useToggletip() { | ||
return useContext(ToggletipContext); | ||
} | ||
|
||
/** | ||
* Used as a container for the button and content of a toggletip. This component | ||
* is responsible for coordinating between interactions with the button and the | ||
* visibility of the content | ||
*/ | ||
function Toggletip({ | ||
align, | ||
as, | ||
className: customClassName, | ||
children, | ||
defaultOpen = false, | ||
}) { | ||
const ref = useRef(); | ||
const [open, setOpen] = useState(defaultOpen); | ||
const prefix = usePrefix(); | ||
const id = useId(); | ||
const className = cx(`${prefix}--toggletip`, customClassName, { | ||
[`${prefix}--toggletip--open`]: open, | ||
}); | ||
const actions = { | ||
toggle: () => { | ||
setOpen(!open); | ||
}, | ||
close: () => { | ||
setOpen(false); | ||
}, | ||
}; | ||
const value = { | ||
buttonProps: { | ||
'aria-expanded': open, | ||
'aria-controls': id, | ||
onClick: actions.toggle, | ||
}, | ||
contentProps: { | ||
id, | ||
}, | ||
}; | ||
|
||
function onKeyDown(event) { | ||
if (open && match(event, keys.Escape)) { | ||
actions.close(); | ||
} | ||
} | ||
|
||
useWindowEvent('click', (event) => { | ||
if (open && !ref.current.contains(event.target)) { | ||
actions.close(); | ||
} | ||
}); | ||
|
||
return ( | ||
<ToggletipContext.Provider value={value}> | ||
<Popover | ||
align={align} | ||
as={as} | ||
caret | ||
className={className} | ||
dropShadow={false} | ||
highContrast | ||
open={open} | ||
onKeyDown={onKeyDown} | ||
ref={ref}> | ||
{children} | ||
</Popover> | ||
</ToggletipContext.Provider> | ||
); | ||
} | ||
|
||
Toggletip.propTypes = { | ||
/** | ||
* Specify how the toggletip should align with the button | ||
*/ | ||
align: PropTypes.oneOf(['top', 'bottom', 'left', 'right']), | ||
|
||
/** | ||
* Provide a custom element or component to render the top-level node for the | ||
* component. | ||
*/ | ||
as: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType]), | ||
|
||
/** | ||
* Custom children to be rendered as the content of the label | ||
*/ | ||
children: PropTypes.node, | ||
|
||
/** | ||
* Provide a custom class name to be added to the outermost node in the | ||
* component | ||
*/ | ||
className: PropTypes.string, | ||
|
||
/** | ||
* Specify if the toggletip should be open by default | ||
*/ | ||
defaultOpen: PropTypes.bool, | ||
}; | ||
|
||
/** | ||
* `ToggletipButton` controls the visibility of the Toggletip through mouse | ||
* clicks and keyboard interactions. | ||
*/ | ||
function ToggletipButton({ | ||
children, | ||
className: customClassName, | ||
label = 'Show information', | ||
}) { | ||
const toggletip = useToggletip(); | ||
const prefix = usePrefix(); | ||
const className = cx(`${prefix}--toggletip-button`, customClassName); | ||
return ( | ||
<button | ||
{...toggletip.buttonProps} | ||
aria-label={label} | ||
type="button" | ||
className={className}> | ||
{children} | ||
</button> | ||
); | ||
} | ||
|
||
ToggletipButton.propTypes = { | ||
/** | ||
* Custom children to be rendered as the content of the label | ||
*/ | ||
children: PropTypes.node, | ||
|
||
/** | ||
* Provide a custom class name to be added to the outermost node in the | ||
* component | ||
*/ | ||
className: PropTypes.string, | ||
|
||
/** | ||
* Provide an accessible label for this button | ||
*/ | ||
label: PropTypes.string, | ||
}; | ||
|
||
/** | ||
* `ToggletipContent` is a wrapper around `PopoverContent`. It places the | ||
* `children` passed in as a prop inside of `PopoverContent` so that they will | ||
* be rendered inside of the popover for this component. | ||
*/ | ||
function ToggletipContent({ children, className: customClassName }) { | ||
const toggletip = useToggletip(); | ||
const prefix = usePrefix(); | ||
return ( | ||
<PopoverContent className={customClassName} {...toggletip.contentProps}> | ||
<div className={`${prefix}--toggletip-content`}>{children}</div> | ||
</PopoverContent> | ||
); | ||
} | ||
|
||
ToggletipContent.propTypes = { | ||
/** | ||
* Custom children to be rendered as the content of the label | ||
*/ | ||
children: PropTypes.node, | ||
|
||
/** | ||
* Provide a custom class name to be added to the outermost node in the | ||
* component | ||
*/ | ||
className: PropTypes.string, | ||
}; | ||
|
||
/** | ||
* `ToggletipActions` is a container for one or two actions present at the base | ||
* of a toggletip. It is used for layout of these items. | ||
*/ | ||
function ToggletipActions({ children, className: customClassName }) { | ||
const prefix = usePrefix(); | ||
const className = cx(`${prefix}--toggletip-actions`, customClassName); | ||
return <div className={className}>{children}</div>; | ||
} | ||
|
||
ToggletipActions.propTypes = { | ||
/** | ||
* Custom children to be rendered as the content of the label | ||
*/ | ||
children: PropTypes.node, | ||
|
||
/** | ||
* Provide a custom class name to be added to the outermost node in the | ||
* component | ||
*/ | ||
className: PropTypes.string, | ||
}; | ||
|
||
export { | ||
ToggletipLabel, | ||
Toggletip, | ||
ToggletipButton, | ||
ToggletipContent, | ||
ToggletipActions, | ||
}; |
29 changes: 29 additions & 0 deletions
29
packages/react/src/components/Toggletip/next/Toggletip.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Preview, Props, Story } from '@storybook/addon-docs/blocks'; | ||
|
||
# Toggletip | ||
|
||
[Source code](https://github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/Toggletip) | ||
|
||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
|
||
## Table of Contents | ||
|
||
- [Overview](#overview) | ||
- [Component API](#component-api) | ||
- [Feedback](#feedback) | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
|
||
## Overview | ||
|
||
## Component API | ||
|
||
<Props /> | ||
|
||
## Feedback | ||
|
||
Help us improve this component by providing feedback, asking questions on Slack, | ||
or updating this file on | ||
[GitHub](https://github.com/carbon-design-system/carbon/edit/main/packages/react/src/components/Toggletip/next/Toggletip.mdx). | ||
|
Oops, something went wrong.