Feat/top banner (#5443)

* wip

* wip

* chore: remove unused import

* feat: top banner component added

* feat: top banner stories added

* fix: icon bug

* Update packages/ui/components/topbanner/TopBanner.tsx

Co-authored-by: Omar López <zomars@me.com>

* Apply suggestions from code review

* Export fixes

* Feedback

* Type fixes

* Fixes

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Udit Takkar
2022-11-15 12:33:59 -07:00
committed by GitHub
co-authored by Peer Richelsen Alex van Andel Omar López kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
parent 6af0428a18
commit 4fef7ba5e2
7 changed files with 135 additions and 11 deletions
+4 -3
View File
@@ -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 (
<div className="examples-item">
<span className="examples-item-title">{title}</span>
<div className={classNames("examples-item", isFullWidth && "w-full")}>
<span className={classNames("examples-item-title", isFullWidth && "mb-0 mt-2")}>{title}</span>
<div className="examples-item-content">{children}</div>
</div>
);
+3
View File
@@ -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: [
+4 -2
View File
@@ -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";
@@ -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 (
<div
data-testid="banner"
className={classNames(
" z-50 flex h-[40px] w-full items-start justify-between gap-8 bg-gray-50 px-4 text-center sm:items-center",
variantClassName[variant]
)}>
<div className="flex flex-1 items-center justify-center gap-2">
<p className="flex items-center justify-center gap-2 font-sans text-sm font-medium leading-4 text-gray-900">
{["warning", "error"].includes(variant) && (
<ExclamationIcon className="h-5 w-5 text-black" aria-hidden="true" />
)}
{text}
</p>
{actions && <div className="text-sm">{actions}</div>}
</div>
{typeof onClose === "function" && (
<button
type="button"
onClick={noop}
className="hover:bg-gray-20 flex items-center rounded-lg p-1.5 text-sm text-gray-400">
<XIcon className="h-4 w-4 text-black" />
</button>
)}
</div>
);
}
@@ -0,0 +1,2 @@
export { TopBanner } from "./TopBanner";
export type { TopBannerProps } from "./TopBanner";
@@ -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'
<Meta title="UI/TopBanner" component={TopBanner} />
<Title title="TopBanner" suffix="Brief" />
## Definition
Top banner will be position on the very top of the page to communicate on whats wrong or whats 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>
+7 -6
View File
@@ -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>
</>