Skip to content

Commit

Permalink
Move tooltips to the design package (#49544) (#49823)
Browse files Browse the repository at this point in the history
* Validation

Adds a model-level validation capability to our validation library.

* Move tooltips to the design package

They will be later required in the SlideTabs component

* Review

* Also, rename the tooltip directory

* Also, rename the tooltip component

* review

* Never return undefined from useValidation()
  • Loading branch information
bl-nero authored Dec 6, 2024
1 parent fe2746d commit 7a38323
Show file tree
Hide file tree
Showing 53 changed files with 159 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import React, { PropsWithChildren, useState } from 'react';
import styled, { useTheme } from 'styled-components';

import { Popover, Flex, Text } from 'design';
import { JustifyContentProps, FlexBasisProps } from 'design/system';

Expand Down Expand Up @@ -64,6 +65,7 @@ export const HoverTooltip: React.FC<
// whether we want to show the tooltip.
if (
target instanceof Element &&
target.parentElement &&
target.scrollWidth > target.parentElement.offsetWidth
) {
setAnchorEl(event.currentTarget);
Expand All @@ -75,7 +77,7 @@ export const HoverTooltip: React.FC<
}

function handlePopoverClose() {
setAnchorEl(null);
setAnchorEl(undefined);
}

// Don't render the tooltip if the content is undefined.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@
*/

import React from 'react';
import { Text, Flex, ButtonPrimary } from 'design';

import styled, { useTheme } from 'styled-components';

import { Text, Flex, ButtonPrimary } from 'design';
import { P } from 'design/Text/Text';
import { logos } from 'teleport/components/LogoHero/LogoHero';
import AGPLLogoLight from 'design/assets/images/agpl-light.svg';
import AGPLLogoDark from 'design/assets/images/agpl-dark.svg';

import { ToolTipInfo } from './ToolTip';
import { IconTooltip } from './IconTooltip';
import { HoverTooltip } from './HoverTooltip';

export default {
title: 'Shared/ToolTip',
title: 'Design/Tooltip',
};

export const ShortContent = () => (
Expand All @@ -36,25 +38,25 @@ export const ShortContent = () => (
<span css={{ marginRight: '4px', verticalAlign: 'middle' }}>
Hover the icon
</span>
<ToolTipInfo position="bottom">"some popover content"</ToolTipInfo>
<IconTooltip position="bottom">"some popover content"</IconTooltip>
</div>
<div style={{ gridColumn: '1/2' }}>
<span css={{ marginRight: '4px', verticalAlign: 'middle' }}>
Hover the icon
</span>
<ToolTipInfo position="right">"some popover content"</ToolTipInfo>
<IconTooltip position="right">"some popover content"</IconTooltip>
</div>
<div style={{ gridColumn: '3/4' }}>
<span css={{ marginRight: '4px', verticalAlign: 'middle' }}>
Hover the icon
</span>
<ToolTipInfo position="left">"some popover content"</ToolTipInfo>
<IconTooltip position="left">"some popover content"</IconTooltip>
</div>
<div style={{ gridColumn: '2/3' }}>
<span css={{ marginRight: '4px', verticalAlign: 'middle' }}>
Hover the icon
</span>
<ToolTipInfo position="top">"some popover content"</ToolTipInfo>
<IconTooltip position="top">"some popover content"</IconTooltip>
</div>
</Grid>
);
Expand All @@ -65,13 +67,18 @@ const Grid = styled.div`
grid-template-rows: repeat(3, 100px);
`;

const logos = {
light: AGPLLogoLight,
dark: AGPLLogoDark,
};

export const LongContent = () => {
const theme = useTheme();
return (
<>
<Flex alignItems="center" mb={3}>
<Text mr={1}>Hover the icon</Text>
<ToolTipInfo>
<IconTooltip>
<P>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
Expand All @@ -84,15 +91,15 @@ export const LongContent = () => {
cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
</P>
</ToolTipInfo>
</IconTooltip>
</Flex>
<P>
Here's some content that shouldn't interfere with the semi-transparent
background:
</P>
<P>
<div style={{ float: 'left', margin: '0 10px 10px 0' }}>
<img src={logos.oss[theme.type]} style={{ float: 'left' }} />
<img src={logos[theme.type]} style={{ float: 'left' }} />
</div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
Expand All @@ -113,7 +120,7 @@ export const WithMutedIconColor = () => (
<span css={{ marginRight: '4px', verticalAlign: 'middle' }}>
Hover the icon
</span>
<ToolTipInfo muteIconColor>"some popover content"</ToolTipInfo>
<IconTooltip muteIconColor>"some popover content"</IconTooltip>
</>
);

Expand All @@ -122,7 +129,7 @@ export const WithKindWarning = () => (
<span css={{ marginRight: '4px', verticalAlign: 'middle' }}>
Hover the icon
</span>
<ToolTipInfo kind="warning">"some popover content"</ToolTipInfo>
<IconTooltip kind="warning">"some popover content"</IconTooltip>
</>
);

Expand All @@ -131,7 +138,7 @@ export const WithKindError = () => (
<span css={{ marginRight: '4px', verticalAlign: 'middle' }}>
Hover the icon
</span>
<ToolTipInfo kind="error">"some popover content"</ToolTipInfo>
<IconTooltip kind="error">"some popover content"</IconTooltip>
</>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { anchorOriginForPosition, transformOriginForPosition } from './shared';

type ToolTipKind = 'info' | 'warning' | 'error';

export const ToolTipInfo: React.FC<
export const IconTooltip: React.FC<
PropsWithChildren<{
trigger?: 'click' | 'hover';
position?: Position;
Expand All @@ -46,15 +46,15 @@ export const ToolTipInfo: React.FC<
kind = 'info',
}) => {
const theme = useTheme();
const [anchorEl, setAnchorEl] = useState();
const [anchorEl, setAnchorEl] = useState<Element>();
const open = Boolean(anchorEl);

function handlePopoverOpen(event) {
function handlePopoverOpen(event: React.MouseEvent) {
setAnchorEl(event.currentTarget);
}

function handlePopoverClose() {
setAnchorEl(null);
setAnchorEl(undefined);
}

const triggerOnHoverProps = {
Expand Down Expand Up @@ -121,8 +121,6 @@ const ToolTipIcon = ({
return <WarningIcon $muteIconColor={muteIconColor} size="medium" />;
case 'error':
return <ErrorIcon $muteIconColor={muteIconColor} size="medium" />;
default:
kind satisfies never;
}
};

Expand Down
20 changes: 20 additions & 0 deletions web/packages/design/src/Tooltip/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Teleport
* Copyright (C) 2023 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

export { IconTooltip } from './IconTooltip';
export { HoverTooltip } from './HoverTooltip';
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
import React from 'react';
import { Flex, LabelInput, Text } from 'design';

import { IconTooltip } from 'design/Tooltip';

import Select, { Option } from 'shared/components/Select';
import { ToolTipInfo } from 'shared/components/ToolTip';

export function AccessDurationRequest({
maxDuration,
Expand All @@ -35,11 +36,11 @@ export function AccessDurationRequest({
<LabelInput color="text.slightlyMuted">
<Flex alignItems="center">
<Text mr={1}>Access Duration</Text>
<ToolTipInfo>
<IconTooltip>
How long you would be given elevated privileges. Note that the time it
takes to approve this request will be subtracted from the duration you
requested.
</ToolTipInfo>
</IconTooltip>
</Flex>
<Select
options={maxDurationOptions}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import React from 'react';
import { Flex, Text } from 'design';

import { ToolTipInfo } from 'shared/components/ToolTip';
import { IconTooltip } from 'design/Tooltip';

import { AccessRequest } from 'shared/services/accessRequests';

Expand All @@ -41,9 +41,9 @@ export function AccessDurationReview({
end: accessRequest.expires,
})}
</Text>
<ToolTipInfo>
<IconTooltip>
How long the access will be granted for after approval.
</ToolTipInfo>
</IconTooltip>
</Flex>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import React, { useState } from 'react';
import { Flex, Text, ButtonIcon, Box, LabelInput } from 'design';
import * as Icon from 'design/Icon';

import { IconTooltip } from 'design/Tooltip';

import Select, { Option } from 'shared/components/Select';
import { ToolTipInfo } from 'shared/components/ToolTip';

import { AccessRequest } from 'shared/services/accessRequests';

Expand Down Expand Up @@ -72,10 +73,10 @@ export function AdditionalOptions({
<LabelInput color="text.slightlyMuted" mb={3}>
<Flex alignItems="center">
<Text mr={1}>Request expires if not reviewed in</Text>
<ToolTipInfo>
<IconTooltip>
The request TTL which is the amount of time this request will
be in the PENDING state before it expires.
</ToolTipInfo>
</IconTooltip>
</Flex>
<Select
options={pendingRequestTtlOptions}
Expand All @@ -89,10 +90,10 @@ export function AdditionalOptions({
<LabelInput color="text.slightlyMuted">
<Flex alignItems="center">
<Text mr={1}>Access Request Lifetime</Text>
<ToolTipInfo>
<IconTooltip>
The max duration of an access request, starting from its
creation, until it expires.
</ToolTipInfo>
</IconTooltip>
</Flex>
<Text>
{getFormattedDurationTxt({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import { ArrowBack, ChevronDown, ChevronRight, Warning } from 'design/Icon';
import Table, { Cell } from 'design/DataTable';
import { Danger } from 'design/Alert';

import { HoverTooltip } from 'design/Tooltip';

import Validation, { useRule, Validator } from 'shared/components/Validation';
import { Attempt } from 'shared/hooks/useAttemptNext';
import { pluralize } from 'shared/utils/text';
Expand All @@ -47,7 +49,6 @@ import { FieldCheckbox } from 'shared/components/FieldCheckbox';
import { mergeRefs } from 'shared/libs/mergeRefs';
import { TextSelectCopyMulti } from 'shared/components/TextSelectCopy';
import { RequestableResourceKind } from 'shared/components/AccessRequests/NewRequest/resource';
import { HoverTooltip } from 'shared/components/ToolTip';

import { CreateRequest } from '../../Shared/types';
import { AssumeStartTime } from '../../AssumeStartTime/AssumeStartTime';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ import { ButtonPrimary, Text, Box, Alert, Flex, Label, H3 } from 'design';
import { Warning } from 'design/Icon';
import { Radio } from 'design/RadioGroup';

import { HoverTooltip } from 'design/Tooltip';

import Validation, { Validator } from 'shared/components/Validation';
import { FieldSelect } from 'shared/components/FieldSelect';
import { Option } from 'shared/components/Select';
import { Attempt } from 'shared/hooks/useAsync';
import { requiredField } from 'shared/components/Validation/rules';
import { HoverTooltip } from 'shared/components/ToolTip';
import { FieldTextArea } from 'shared/components/FieldTextArea';

import { AccessRequest, RequestState } from 'shared/services/accessRequests';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ import { displayDateWithPrefixedTime } from 'design/datetime';

import { LabelKind } from 'design/LabelState/LabelState';

import { HoverTooltip } from 'shared/components/ToolTip';
import { HoverTooltip } from 'design/Tooltip';

import { hasFinished, Attempt } from 'shared/hooks/useAsync';

import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import { ButtonPrimary, Text, Box, ButtonIcon, Menu } from 'design';
import { Info } from 'design/Icon';
import { displayDateWithPrefixedTime } from 'design/datetime';

import { HoverTooltip } from 'shared/components/ToolTip';
import { HoverTooltip } from 'design/Tooltip';

import { AccessRequest } from 'shared/services/accessRequests';

export function PromotedMessage({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { Text, Toggle, Link, Flex, H2 } from 'design';

import { P } from 'design/Text/Text';

import { ToolTipInfo } from 'shared/components/ToolTip';
import { IconTooltip } from 'design/Tooltip';

const GUIDE_URL =
'https://goteleport.com/docs/reference/predicate-language/#resource-filtering';
Expand All @@ -44,9 +44,9 @@ export function AdvancedSearchToggle(props: {
>
<Toggle isToggled={props.isToggled} onToggle={props.onToggle} />
<Text typography="body3">Advanced</Text>
<ToolTipInfo trigger="click">
<IconTooltip trigger="click">
<PredicateDocumentation />
</ToolTipInfo>
</IconTooltip>
</Flex>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { ChevronDown } from 'design/Icon';
import cfg from 'teleport/config';
import { Cluster } from 'teleport/services/clusters';

import { HoverTooltip } from 'shared/components/ToolTip';
import { HoverTooltip } from 'design/Tooltip';

export interface ClusterDropdownProps {
clusterLoader: ClusterLoader;
Expand Down
5 changes: 3 additions & 2 deletions web/packages/shared/components/FieldInput/FieldInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ import styled, { useTheme } from 'styled-components';
import { IconProps } from 'design/Icon/Icon';
import { InputMode, InputSize, InputType } from 'design/Input';

import { IconTooltip } from 'design/Tooltip';

import { useRule } from 'shared/components/Validation';
import { ToolTipInfo } from 'shared/components/ToolTip';

const FieldInput = forwardRef<HTMLInputElement, FieldInputProps>(
(
Expand Down Expand Up @@ -113,7 +114,7 @@ const FieldInput = forwardRef<HTMLInputElement, FieldInputProps>(
>
{label}
</span>
<ToolTipInfo children={toolTipContent} />
<IconTooltip children={toolTipContent} />
</>
) : (
<>{label}</>
Expand Down
Loading

0 comments on commit 7a38323

Please sign in to comment.