diff --git a/apps/storybook/components/Examples.tsx b/apps/storybook/components/Examples.tsx index bb32f10a6a..0245d57c38 100644 --- a/apps/storybook/components/Examples.tsx +++ b/apps/storybook/components/Examples.tsx @@ -3,11 +3,12 @@ import { classNames } from "@calcom/lib"; interface ExampleProps { children: React.ReactNode; title: string; + isFullWidth?: boolean; } -export const Example = ({ children, title }: ExampleProps) => { +export const Example = ({ children, title, isFullWidth = false }: ExampleProps) => { return ( -
- {title} +
+ {title}
{children}
); diff --git a/packages/config/tailwind-preset.js b/packages/config/tailwind-preset.js index 19a7f1e16d..ec4b8c20d2 100644 --- a/packages/config/tailwind-preset.js +++ b/packages/config/tailwind-preset.js @@ -203,6 +203,9 @@ module.exports = { full: "100%", screen: "100vw", }), + backgroundImage: { + "gradient-primary": "radial-gradient(162.05% 170% at 109.58% 35%, #667593 0%, #E3E3E3 100%)", + }, }, }, plugins: [ diff --git a/packages/ui/components/index.ts b/packages/ui/components/index.ts index 119c6ef058..2d01c0ba6a 100644 --- a/packages/ui/components/index.ts +++ b/packages/ui/components/index.ts @@ -1,6 +1,8 @@ export * from "./avatar"; -export * from "./button"; -export * from "./buttonGroup"; export * from "./badge"; export * from "./breadcrumb"; +export * from "./button"; +export * from "./buttonGroup"; export * from "./form"; +export { TopBanner } from "./top-banner"; +export type { TopBannerProps } from "./top-banner"; diff --git a/packages/ui/components/top-banner/TopBanner.tsx b/packages/ui/components/top-banner/TopBanner.tsx new file mode 100644 index 0000000000..06b2916c46 --- /dev/null +++ b/packages/ui/components/top-banner/TopBanner.tsx @@ -0,0 +1,48 @@ +import { ExclamationIcon } from "@heroicons/react/outline"; +import { XIcon } from "@heroicons/react/solid"; +import classNames from "classnames"; +import noop from "lodash/noop"; +import { ReactNode } from "react"; + +export type TopBannerProps = { + text: string; + variant?: keyof typeof variantClassName; + actions?: ReactNode; + onClose?: () => void; +}; + +const variantClassName = { + default: "bg-gradient-primary", + warning: "bg-orange-400", + error: "bg-red-400", +}; + +export function TopBanner(props: TopBannerProps) { + const { variant = "default", text, actions, onClose } = props; + return ( +
+
+

+ {["warning", "error"].includes(variant) && ( +

+ {actions &&
{actions}
} +
+ {typeof onClose === "function" && ( + + )} +
+ ); +} diff --git a/packages/ui/components/top-banner/index.ts b/packages/ui/components/top-banner/index.ts new file mode 100644 index 0000000000..123eee8066 --- /dev/null +++ b/packages/ui/components/top-banner/index.ts @@ -0,0 +1,2 @@ +export { TopBanner } from "./TopBanner"; +export type { TopBannerProps } from "./TopBanner"; diff --git a/packages/ui/components/top-banner/topbanner.stories.mdx b/packages/ui/components/top-banner/topbanner.stories.mdx new file mode 100644 index 0000000000..03849a8243 --- /dev/null +++ b/packages/ui/components/top-banner/topbanner.stories.mdx @@ -0,0 +1,67 @@ +import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs'; +import { Examples, Example, Note, Title,CustomArgsTable,VariantsTable, VariantRow } from '@calcom/storybook/components' +import { Icon } from "@calcom/ui/Icon"; +import { TopBanner } from './TopBanner' + + + + + + +## Definition +Top banner will be position on the very top of the page to communicate on what’s wrong or what’s new. + + +## Structure +Each toast has a state to represent neutral, positive or negative responses. + +<CustomArgsTable of={TopBanner} /> + +<Examples title="Top Banner Style"> + <Example title="Default" isFullWidth={true} > + <TopBanner + actions={ + <button + className="border-b border-black text-sm" + onClick={() => { + console.log("test"); + }}> + Action + </button> + } + text="Something big is happening we want you to know about." + /> + </Example> + <Example title="Warning" isFullWidth={true} > + <TopBanner + actions={ + <button + className="border-b border-black text-sm" + onClick={() => { + console.log("test"); + }}> + Action + </button> + } + variant="warning" + text="An app wide warning is occuring that should be resolved." + /> + </Example> + <Example title="Error" isFullWidth={true} > + <TopBanner + actions={ + <button + className="border-b border-black text-sm" + onClick={() => { + console.log("test"); + }}> + Action + </button> + } + variant="error" + text="A major error is occuring that must be resolved." + /> + </Example> +</Examples> + + diff --git a/packages/ui/v2/core/Shell.tsx b/packages/ui/v2/core/Shell.tsx index 7ba8bd8755..32b1ce5427 100644 --- a/packages/ui/v2/core/Shell.tsx +++ b/packages/ui/v2/core/Shell.tsx @@ -143,12 +143,13 @@ const Layout = (props: LayoutProps) => { {/* todo: only run this if timezone is different */} <TimezoneChangeDialog /> - - <div className="flex h-screen overflow-hidden" data-testid="dashboard-shell"> - {props.SidebarContainer || <SideBarContainer />} - <div className="flex w-0 flex-1 flex-col overflow-hidden"> - <ImpersonatingBanner /> - <MainContainer {...props} /> + <div className="h-screen overflow-hidden"> + <div className="flex h-screen overflow-hidden" data-testid="dashboard-shell"> + {props.SidebarContainer || <SideBarContainer />} + <div className="flex w-0 flex-1 flex-col overflow-hidden"> + <ImpersonatingBanner /> + <MainContainer {...props} /> + </div> </div> </div> </>