diff --git a/packages/dropdownable/components/Dropdownable.tsx b/packages/dropdownable/components/Dropdownable.tsx index 2db0fcd6c..886052688 100644 --- a/packages/dropdownable/components/Dropdownable.tsx +++ b/packages/dropdownable/components/Dropdownable.tsx @@ -173,6 +173,7 @@ class Dropdownable extends React.Component { windowDimensions ): Direction { // Determine if there is enough space in each direction to fit dropdown + const triggerCenter = childBounds.width / 2 + childBounds.left; const possibleVertDirections = { top: dropdownDimensions.height <= childBounds.top, bottom: @@ -181,7 +182,10 @@ class Dropdownable extends React.Component { }; const possibleHorizDirections = { left: dropdownDimensions.width >= childBounds.right, - right: dropdownDimensions.width <= childBounds.right + right: dropdownDimensions.width <= childBounds.right, + center: + triggerCenter - dropdownDimensions.width / 2 > 0 && + triggerCenter + dropdownDimensions.width / 2 < windowDimensions.width }; // Pick the first available preference diff --git a/packages/segmentedControl/README.md b/packages/segmentedControl/README.md index 66b81ef8e..dc56a2ffe 100644 --- a/packages/segmentedControl/README.md +++ b/packages/segmentedControl/README.md @@ -4,10 +4,13 @@ A segmented control is group of two or more buttons that represent a list of opt A segmented control can be a good alternative to a dropdown or a select input because it requires less interactions to make a selection. They can be a good alternative to a group of radio buttons when there are space limitations or if form controls look visually awkward. +## Segment tooltips +Each segmented control button can also render a tooltip when the user hovers. Show tooltip content to show "nice-to-have" information about a segment button. + ## Icons in button labels Button labels can contain icons. When using an icon in a button label, the default icon size to use is `iconSizeXs`. -When an icon is the only button label content, be sure to provide text content to keep the buttons screenreader accessible. If you're using the `Icon` component to render the icon, this is as simple as passing a string to the `ariaLabel` prop. +When an icon is the only button label content, be sure to provide text content to keep the buttons screenreader accessible. If you're using the `Icon` component to render the icon, this is as simple as passing a string to the `ariaLabel` prop. It's also recommended to show a tooltip when an icon is the only button label content. ## Do's and Dont's @@ -18,3 +21,4 @@ When an icon is the only button label content, be sure to provide text content t ### Don't - Use a segmented control for navigation instead of Tabs - Put long strings in the segments +- Rely completely on the tooltip content to convey what a segment button does diff --git a/packages/segmentedControl/components/SegmentedControlButton.tsx b/packages/segmentedControl/components/SegmentedControlButton.tsx index 8ae18883c..3e366b7f9 100644 --- a/packages/segmentedControl/components/SegmentedControlButton.tsx +++ b/packages/segmentedControl/components/SegmentedControlButton.tsx @@ -4,10 +4,12 @@ import shortid from "shortid"; import { segmentedControlButton, segmentedControlButtonActive, - staticKeyboardFocusClassname + staticKeyboardFocusClassname, + segmentedControlButtonInner } from "../style"; import { visuallyHidden, display } from "../../shared/styles/styleUtils"; import FocusStyleManager from "../../shared/components/FocusStyleManager"; +import { Tooltip } from "../../tooltip"; export interface SegmentedControlButtonProps { /** @@ -30,12 +32,35 @@ export interface SegmentedControlButtonProps { * The value of the input */ value: string; + /** + * Content that appears in a Tooltip when a users hovers the button + */ + tooltipContent?: React.ReactNode; } const SegmentedControlButton: React.SFC< SegmentedControlButtonProps > = props => { - const { id = shortid.generate(), isActive, onChange, name, value } = props; + const { + id = shortid.generate(), + isActive, + onChange, + name, + value, + tooltipContent, + children + } = props; + const segmentChildren = tooltipContent ? ( + {children}} + > + {tooltipContent} + + ) : ( +
{children}
+ ); + return ( {/* @@ -60,7 +85,7 @@ const SegmentedControlButton: React.SFC< checked={isActive} onChange={onChange} /> - {props.children} + {segmentChildren} diff --git a/packages/segmentedControl/stories/SegmentedControl.stories.tsx b/packages/segmentedControl/stories/SegmentedControl.stories.tsx index 03fc59adf..340d41631 100644 --- a/packages/segmentedControl/stories/SegmentedControl.stories.tsx +++ b/packages/segmentedControl/stories/SegmentedControl.stories.tsx @@ -86,6 +86,38 @@ storiesOf("SegmentedControl", module) )} )) + .add("with tooltip content", () => ( + + {({ changeHandler, selectedSegment }) => ( + + + + + + + + + )} + + )) .add( "custom SegmentedControlButton id prop", () => ( diff --git a/packages/segmentedControl/style.ts b/packages/segmentedControl/style.ts index 06c617e0a..90490648f 100644 --- a/packages/segmentedControl/style.ts +++ b/packages/segmentedControl/style.ts @@ -23,7 +23,6 @@ export const segmentedControlButton = css` border-style: solid; border-right-width: 0; cursor: pointer; - padding: ${buttonPadding.vert} ${buttonPadding.horiz}; &:first-child { border-radius: ${borderRadiusDefault} 0 0 ${borderRadiusDefault}; @@ -45,6 +44,10 @@ export const segmentedControlButton = css` } `; +export const segmentedControlButtonInner = css` + padding: ${buttonPadding.vert} ${buttonPadding.horiz}; +`; + export const segmentedControlButtonActive = css` background-color: ${themeBorder}; border-color: ${themeBorder}; diff --git a/packages/tooltip/components/Tooltip.tsx b/packages/tooltip/components/Tooltip.tsx index 105965b21..8778766d6 100644 --- a/packages/tooltip/components/Tooltip.tsx +++ b/packages/tooltip/components/Tooltip.tsx @@ -74,7 +74,14 @@ class Tooltip extends React.PureComponent { } preferredDirections={ - preferredDirections || [Direction.TopCenter, Direction.BottomCenter] + preferredDirections || [ + Direction.TopCenter, + Direction.TopLeft, + Direction.TopRight, + Direction.BottomCenter, + Direction.BottomLeft, + Direction.BottomRight + ] } > {trigger} diff --git a/packages/tooltip/tests/__snapshots__/Tooltip.test.tsx.snap b/packages/tooltip/tests/__snapshots__/Tooltip.test.tsx.snap index 2e955d1f9..2c441c8b1 100644 --- a/packages/tooltip/tests/__snapshots__/Tooltip.test.tsx.snap +++ b/packages/tooltip/tests/__snapshots__/Tooltip.test.tsx.snap @@ -1,6 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Tooltip renders 1`] = ` +.emotion-3 { + top: 0px; + left: 0px; + position: absolute; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + opacity: 0; + z-index: 2; +} + .emotion-5 { position: relative; } @@ -21,17 +32,6 @@ exports[`Tooltip renders 1`] = ` position: absolute; } -.emotion-3 { - top: 0px; - left: NaNpx; - position: absolute; - -webkit-transform: scale(0); - -ms-transform: scale(0); - transform: scale(0); - opacity: 0; - z-index: 2; -} - @@ -73,7 +77,18 @@ exports[`Tooltip renders 1`] = `
@@ -214,7 +218,7 @@ exports[`Tooltip renders open tooltip 1`] = ` .emotion-3 { top: 0px; - left: NaNpx; + left: 0px; position: absolute; -webkit-transform: scale(1); -ms-transform: scale(1); @@ -251,7 +255,11 @@ exports[`Tooltip renders open tooltip 1`] = ` preferredDirections={ Array [ "top-center", + "top-left", + "top-right", "bottom-center", + "bottom-left", + "bottom-right", ] } > @@ -268,7 +276,7 @@ exports[`Tooltip renders open tooltip 1`] = `
@@ -482,15 +490,14 @@ exports[`Tooltip renders with preferred directions 1`] = `