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:
co-authored by
Peer Richelsen
Alex van Andel
Omar López
kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
parent
6af0428a18
commit
4fef7ba5e2
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -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 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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user