Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add helpful tooltips for the key features (#2097)
- Loading branch information
1 parent
6d96696
commit eedd293
Showing
16 changed files
with
726 additions
and
395 deletions.
There are no files selected for viewing
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,35 @@ | ||
import { ComponentMeta, Story } from "@storybook/react" | ||
import { | ||
HelpTooltip, | ||
HelpTooltipLink, | ||
HelpTooltipLinksGroup, | ||
HelpTooltipProps, | ||
HelpTooltipText, | ||
HelpTooltipTitle, | ||
} from "./HelpTooltip" | ||
|
||
export default { | ||
title: "components/HelpTooltip", | ||
component: HelpTooltip, | ||
} as ComponentMeta<typeof HelpTooltip> | ||
|
||
const Template: Story<HelpTooltipProps> = (args) => ( | ||
<HelpTooltip {...args}> | ||
<HelpTooltipTitle>What is template?</HelpTooltipTitle> | ||
<HelpTooltipText> | ||
With templates you can create a common configuration for your workspaces using Terraform. So, you and your team | ||
can use the same environment to deliver great software. | ||
</HelpTooltipText> | ||
<HelpTooltipLinksGroup> | ||
<HelpTooltipLink href="https://github.com/coder/coder/">Creating a template</HelpTooltipLink> | ||
<HelpTooltipLink href="https://github.com/coder/coder/">Updating a template</HelpTooltipLink> | ||
</HelpTooltipLinksGroup> | ||
</HelpTooltip> | ||
) | ||
|
||
export const Close = Template.bind({}) | ||
|
||
export const Open = Template.bind({}) | ||
Open.args = { | ||
open: true, | ||
} |
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,159 @@ | ||
import Link from "@material-ui/core/Link" | ||
import Popover from "@material-ui/core/Popover" | ||
import { makeStyles } from "@material-ui/core/styles" | ||
import HelpIcon from "@material-ui/icons/HelpOutline" | ||
import OpenInNewIcon from "@material-ui/icons/OpenInNew" | ||
import { useState } from "react" | ||
import { Stack } from "../Stack/Stack" | ||
|
||
type Size = "small" | "medium" | ||
export interface HelpTooltipProps { | ||
// Useful to test on storybook | ||
open?: boolean | ||
size?: Size | ||
} | ||
|
||
export const HelpTooltip: React.FC<HelpTooltipProps> = ({ children, open, size = "medium" }) => { | ||
const styles = useStyles({ size }) | ||
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null) | ||
open = open ?? Boolean(anchorEl) | ||
const id = open ? "help-popover" : undefined | ||
|
||
return ( | ||
<> | ||
<button aria-describedby={id} className={styles.button} onClick={(event) => setAnchorEl(event.currentTarget)}> | ||
<HelpIcon className={styles.icon} /> | ||
</button> | ||
<Popover | ||
classes={{ paper: styles.popoverPaper }} | ||
id={id} | ||
open={open} | ||
anchorEl={anchorEl} | ||
onClose={() => { | ||
setAnchorEl(null) | ||
}} | ||
anchorOrigin={{ | ||
vertical: "bottom", | ||
horizontal: "left", | ||
}} | ||
transformOrigin={{ | ||
vertical: "top", | ||
horizontal: "left", | ||
}} | ||
> | ||
{children} | ||
</Popover> | ||
</> | ||
) | ||
} | ||
|
||
export const HelpTooltipTitle: React.FC = ({ children }) => { | ||
const styles = useStyles() | ||
|
||
return <h4 className={styles.title}>{children}</h4> | ||
} | ||
|
||
export const HelpTooltipText: React.FC = ({ children }) => { | ||
const styles = useStyles() | ||
|
||
return <p className={styles.text}>{children}</p> | ||
} | ||
|
||
export const HelpTooltipLink: React.FC<{ href: string }> = ({ children, href }) => { | ||
const styles = useStyles() | ||
|
||
return ( | ||
<Link href={href} target="_blank" rel="noreferrer" className={styles.link}> | ||
<OpenInNewIcon className={styles.linkIcon} /> | ||
{children} | ||
</Link> | ||
) | ||
} | ||
|
||
export const HelpTooltipLinksGroup: React.FC = ({ children }) => { | ||
const styles = useStyles() | ||
|
||
return ( | ||
<Stack spacing={1} className={styles.linksGroup}> | ||
{children} | ||
</Stack> | ||
) | ||
} | ||
|
||
const getButtonSpacingFromSize = (size?: Size): number => { | ||
switch (size) { | ||
case "small": | ||
return 2.75 | ||
case "medium": | ||
default: | ||
return 3 | ||
} | ||
} | ||
|
||
const getIconSpacingFromSize = (size?: Size): number => { | ||
switch (size) { | ||
case "small": | ||
return 1.75 | ||
case "medium": | ||
default: | ||
return 2 | ||
} | ||
} | ||
|
||
const useStyles = makeStyles((theme) => ({ | ||
button: { | ||
display: "flex", | ||
alignItems: "center", | ||
justifyContent: "center", | ||
width: ({ size }: { size?: Size }) => theme.spacing(getButtonSpacingFromSize(size)), | ||
height: ({ size }: { size?: Size }) => theme.spacing(getButtonSpacingFromSize(size)), | ||
padding: 0, | ||
border: 0, | ||
background: "transparent", | ||
color: theme.palette.text.secondary, | ||
cursor: "pointer", | ||
|
||
"&:hover": { | ||
color: theme.palette.text.primary, | ||
}, | ||
}, | ||
|
||
icon: { | ||
width: ({ size }: { size?: Size }) => theme.spacing(getIconSpacingFromSize(size)), | ||
height: ({ size }: { size?: Size }) => theme.spacing(getIconSpacingFromSize(size)), | ||
}, | ||
|
||
popoverPaper: { | ||
marginTop: theme.spacing(0.5), | ||
width: theme.spacing(38), | ||
padding: theme.spacing(2.5), | ||
color: theme.palette.text.secondary, | ||
}, | ||
|
||
title: { | ||
marginTop: 0, | ||
marginBottom: theme.spacing(1), | ||
color: theme.palette.text.primary, | ||
}, | ||
|
||
text: { | ||
marginTop: theme.spacing(0.5), | ||
marginBottom: theme.spacing(0.5), | ||
}, | ||
|
||
link: { | ||
display: "flex", | ||
alignItems: "center", | ||
}, | ||
|
||
linkIcon: { | ||
color: "inherit", | ||
width: 14, | ||
height: 14, | ||
marginRight: theme.spacing(1), | ||
}, | ||
|
||
linksGroup: { | ||
marginTop: theme.spacing(2), | ||
}, | ||
})) |
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,15 @@ | ||
import { ComponentMeta, Story } from "@storybook/react" | ||
import { PageHeader, PageHeaderTitle } from "./PageHeader" | ||
|
||
export default { | ||
title: "components/PageHeader", | ||
component: PageHeader, | ||
} as ComponentMeta<typeof PageHeader> | ||
|
||
const Template: Story = () => ( | ||
<PageHeader> | ||
<PageHeaderTitle>Templates</PageHeaderTitle> | ||
</PageHeader> | ||
) | ||
|
||
export const Example = Template.bind({}) |
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,62 @@ | ||
import { makeStyles } from "@material-ui/core/styles" | ||
import { Stack } from "../Stack/Stack" | ||
|
||
export interface PageHeaderProps { | ||
actions?: JSX.Element | ||
} | ||
|
||
export const PageHeader: React.FC<PageHeaderProps> = ({ children, actions }) => { | ||
const styles = useStyles() | ||
|
||
return ( | ||
<div className={styles.root}> | ||
<hgroup>{children}</hgroup> | ||
<Stack direction="row" className={styles.actions}> | ||
{actions} | ||
</Stack> | ||
</div> | ||
) | ||
} | ||
|
||
export const PageHeaderTitle: React.FC = ({ children }) => { | ||
const styles = useStyles() | ||
|
||
return <h1 className={styles.title}>{children}</h1> | ||
} | ||
|
||
export const PageHeaderSubtitle: React.FC = ({ children }) => { | ||
const styles = useStyles() | ||
|
||
return <h2 className={styles.subtitle}>{children}</h2> | ||
} | ||
|
||
const useStyles = makeStyles((theme) => ({ | ||
root: { | ||
display: "flex", | ||
alignItems: "center", | ||
paddingTop: theme.spacing(6), | ||
paddingBottom: theme.spacing(5), | ||
}, | ||
|
||
title: { | ||
fontSize: theme.spacing(4), | ||
fontWeight: 400, | ||
margin: 0, | ||
display: "flex", | ||
alignItems: "center", | ||
lineHeight: "140%", | ||
}, | ||
|
||
subtitle: { | ||
fontSize: theme.spacing(2.5), | ||
color: theme.palette.text.secondary, | ||
fontWeight: 400, | ||
display: "block", | ||
margin: 0, | ||
marginTop: theme.spacing(1), | ||
}, | ||
|
||
actions: { | ||
marginLeft: "auto", | ||
}, | ||
})) |
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
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
Oops, something went wrong.