diff --git a/site/src/components/CodeExample/CodeExample.tsx b/site/src/components/CodeExample/CodeExample.tsx index 95adc25ad4fc3..6736c103a4b09 100644 --- a/site/src/components/CodeExample/CodeExample.tsx +++ b/site/src/components/CodeExample/CodeExample.tsx @@ -8,18 +8,28 @@ export interface CodeExampleProps { code: string className?: string buttonClassName?: string + tooltipTitle?: string } /** * Component to show single-line code examples, with a copy button */ -export const CodeExample: FC = ({ code, className, buttonClassName }) => { +export const CodeExample: FC = ({ + code, + className, + buttonClassName, + tooltipTitle, +}) => { const styles = useStyles() return (
{code} - +
) } diff --git a/site/src/components/CopyButton/CopyButton.tsx b/site/src/components/CopyButton/CopyButton.tsx index 030ca4623a59a..fee7a09fd8a07 100644 --- a/site/src/components/CopyButton/CopyButton.tsx +++ b/site/src/components/CopyButton/CopyButton.tsx @@ -11,6 +11,12 @@ interface CopyButtonProps { ctaCopy?: string wrapperClassName?: string buttonClassName?: string + tooltipTitle?: string +} + +export const Language = { + tooltipTitle: "Copy to clipboard", + ariaLabel: "Copy to clipboard", } /** @@ -21,6 +27,7 @@ export const CopyButton: React.FC = ({ ctaCopy, wrapperClassName = "", buttonClassName = "", + tooltipTitle = Language.tooltipTitle, }) => { const styles = useStyles() const [isCopied, setIsCopied] = useState(false) @@ -56,12 +63,13 @@ export const CopyButton: React.FC = ({ } return ( - +
{isCopied ? ( diff --git a/site/src/components/Stack/Stack.tsx b/site/src/components/Stack/Stack.tsx index a6614f1243e5f..87e3a0a8a0dc5 100644 --- a/site/src/components/Stack/Stack.tsx +++ b/site/src/components/Stack/Stack.tsx @@ -5,18 +5,23 @@ import { combineClasses } from "../../util/combineClasses" type Direction = "column" | "row" -interface StyleProps { - direction: Direction - spacing: number +export interface StackProps { + className?: string + direction?: Direction + spacing?: number alignItems?: CSSProperties["alignItems"] + justifyContent?: CSSProperties["justifyContent"] } +type StyleProps = Omit + const useStyles = makeStyles((theme) => ({ stack: { display: "flex", flexDirection: ({ direction }: StyleProps) => direction, - gap: ({ spacing }: StyleProps) => theme.spacing(spacing), + gap: ({ spacing }: StyleProps) => spacing && theme.spacing(spacing), alignItems: ({ alignItems }: StyleProps) => alignItems, + justifyContent: ({ justifyContent }: StyleProps) => justifyContent, [theme.breakpoints.down("sm")]: { width: "100%", @@ -24,21 +29,15 @@ const useStyles = makeStyles((theme) => ({ }, })) -export interface StackProps { - className?: string - direction?: Direction - spacing?: number - alignItems?: CSSProperties["alignItems"] -} - export const Stack: FC = ({ children, className, direction = "column", spacing = 2, alignItems, + justifyContent, }) => { - const styles = useStyles({ spacing, direction, alignItems }) + const styles = useStyles({ spacing, direction, alignItems, justifyContent }) return
{children}
} diff --git a/site/src/components/Tooltips/AuditHelpTooltip.tsx b/site/src/components/Tooltips/AuditHelpTooltip.tsx new file mode 100644 index 0000000000000..33305668f2f9f --- /dev/null +++ b/site/src/components/Tooltips/AuditHelpTooltip.tsx @@ -0,0 +1,16 @@ +import { FC } from "react" +import { HelpTooltip, HelpTooltipText, HelpTooltipTitle } from "./HelpTooltip" + +export const Language = { + title: "What is an audit log?", + body: "An audit log is a record of events and changes made throughout a system.", +} + +export const AuditHelpTooltip: FC = () => { + return ( + + {Language.title} + {Language.body} + + ) +} diff --git a/site/src/components/Tooltips/HelpTooltip/HelpTooltip.tsx b/site/src/components/Tooltips/HelpTooltip/HelpTooltip.tsx index 7c70d9146743a..3bbfc4dab4558 100644 --- a/site/src/components/Tooltips/HelpTooltip/HelpTooltip.tsx +++ b/site/src/components/Tooltips/HelpTooltip/HelpTooltip.tsx @@ -15,6 +15,10 @@ export interface HelpTooltipProps { size?: Size } +export const Language = { + ariaLabel: "tooltip", +} + const HelpTooltipContext = createContext<{ open: boolean; onClose: () => void } | undefined>( undefined, ) @@ -52,6 +56,7 @@ export const HelpTooltip: React.FC = ({ children, open, size = onMouseEnter={() => { setIsOpen(true) }} + aria-label={Language.ariaLabel} > diff --git a/site/src/components/Tooltips/index.ts b/site/src/components/Tooltips/index.ts index f2813adc68f0c..4f7eabac682c7 100644 --- a/site/src/components/Tooltips/index.ts +++ b/site/src/components/Tooltips/index.ts @@ -1,4 +1,5 @@ export { AgentHelpTooltip } from "./AgentHelpTooltip" +export { AuditHelpTooltip } from "./AuditHelpTooltip" export { OutdatedHelpTooltip } from "./OutdatedHelpTooltip" export { ResourcesHelpTooltip } from "./ResourcesHelpTooltip" export { WorkspaceHelpTooltip } from "./WorkspaceHelpTooltip" diff --git a/site/src/pages/AuditPage/AuditPage.test.tsx b/site/src/pages/AuditPage/AuditPage.test.tsx new file mode 100644 index 0000000000000..8c98281207e86 --- /dev/null +++ b/site/src/pages/AuditPage/AuditPage.test.tsx @@ -0,0 +1,32 @@ +import { fireEvent, screen } from "@testing-library/react" +import { Language as CopyButtonLanguage } from "components/CopyButton/CopyButton" +import { Language as AuditTooltipLanguage } from "components/Tooltips/AuditHelpTooltip" +import { Language as TooltipLanguage } from "components/Tooltips/HelpTooltip/HelpTooltip" +import { render } from "testHelpers/renderHelpers" +import AuditPage from "./AuditPage" +import { Language as AuditViewLanguage } from "./AuditPageView" + +describe("AuditPage", () => { + it("renders a page with a title and subtitle", async () => { + // When + render() + + // Then + await screen.findByText(AuditViewLanguage.title) + await screen.findByText(AuditViewLanguage.subtitle) + const tooltipIcon = await screen.findByRole("button", { name: TooltipLanguage.ariaLabel }) + fireEvent.mouseOver(tooltipIcon) + expect(await screen.findByText(AuditTooltipLanguage.title)).toBeInTheDocument() + }) + + it("describes the CLI command", async () => { + // When + render() + + // Then + await screen.findByText("coder audit [organization_ID]") // CLI command; untranslated + const copyIcon = await screen.findByRole("button", { name: CopyButtonLanguage.ariaLabel }) + fireEvent.mouseOver(copyIcon) + expect(await screen.findByText(AuditViewLanguage.tooltipTitle)).toBeInTheDocument() + }) +}) diff --git a/site/src/pages/AuditPage/AuditPage.tsx b/site/src/pages/AuditPage/AuditPage.tsx index c285ea2176eed..1ee1f465b67cf 100644 --- a/site/src/pages/AuditPage/AuditPage.tsx +++ b/site/src/pages/AuditPage/AuditPage.tsx @@ -1,8 +1,9 @@ import { FC } from "react" +import { AuditPageView } from "./AuditPageView" // REMARK: This page is in-progress and hidden from users const AuditPage: FC = () => { - return
Audit
+ return } export default AuditPage diff --git a/site/src/pages/AuditPage/AuditPageView.stories.tsx b/site/src/pages/AuditPage/AuditPageView.stories.tsx new file mode 100644 index 0000000000000..7ad3725855264 --- /dev/null +++ b/site/src/pages/AuditPage/AuditPageView.stories.tsx @@ -0,0 +1,16 @@ +import { ComponentMeta, Story } from "@storybook/react" +import { AuditPageView } from "./AuditPageView" + +export default { + title: "pages/AuditPageView", + component: AuditPageView, +} as ComponentMeta + +const Template: Story = (args) => + +export const AuditPage = Template.bind({}) + +export const AuditPageSmallViewport = Template.bind({}) +AuditPageSmallViewport.parameters = { + chromatic: { viewports: [600] }, +} diff --git a/site/src/pages/AuditPage/AuditPageView.tsx b/site/src/pages/AuditPage/AuditPageView.tsx new file mode 100644 index 0000000000000..c284717fe2c9c --- /dev/null +++ b/site/src/pages/AuditPage/AuditPageView.tsx @@ -0,0 +1,59 @@ +import { makeStyles } from "@material-ui/core/styles" +import { CodeExample } from "components/CodeExample/CodeExample" +import { Margins } from "components/Margins/Margins" +import { PageHeader, PageHeaderSubtitle, PageHeaderTitle } from "components/PageHeader/PageHeader" +import { Stack } from "components/Stack/Stack" +import { AuditHelpTooltip } from "components/Tooltips" +import { FC } from "react" + +export const Language = { + title: "Audit", + subtitle: "View events in your audit log.", + tooltipTitle: "Copy to clipboard and try the Coder CLI", +} + +export const AuditPageView: FC = () => { + const styles = useStyles() + + return ( + + + + + + {Language.title} + + + + {Language.subtitle} + + + + + ) +} + +const useStyles = makeStyles((theme) => ({ + headingContainer: { + marginTop: theme.spacing(6), + marginBottom: theme.spacing(5), + flexDirection: "row", + alignItems: "center", + + [theme.breakpoints.down("sm")]: { + flexDirection: "column", + alignItems: "start", + }, + }, + headingStyles: { + paddingTop: "0px", + paddingBottom: "0px", + }, + codeExampleStyles: { + height: "fit-content", + }, +}))