Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add alert banner component #497

Merged
merged 27 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e2c84f9
roughing out AlertBanner component
mkernohanbc Oct 29, 2024
7cb6660
styling
mkernohanbc Oct 29, 2024
8d3b1e4
finishing initial styling and theming
mkernohanbc Oct 30, 2024
f17ce7d
implement close function with useState on AlertBanner examples
mkernohanbc Oct 30, 2024
f50ce49
add BC outline icon as new component
mkernohanbc Oct 30, 2024
06e3312
scaffolding AlertBanner in storybook
mkernohanbc Oct 30, 2024
9191953
stories and styling
mkernohanbc Oct 30, 2024
4716d3b
styling, stories and docs
mkernohanbc Oct 31, 2024
29cdaa0
change default ARIA role to status
mkernohanbc Oct 31, 2024
fbef998
adding defaults to AlertBanner story template
mkernohanbc Oct 31, 2024
e2e0cb7
docs and stories
mkernohanbc Oct 31, 2024
3ca279f
add SvgBetaIcon component
mkernohanbc Oct 31, 2024
ff0d9da
add source/attribution comments to icon components
mkernohanbc Oct 31, 2024
f7ffca9
add beta theme to AlertBanner
mkernohanbc Oct 31, 2024
8f8c636
fix colour contrast
mkernohanbc Oct 31, 2024
af6787c
rename 'dark' theme to 'black' to prevent conflict with future dark mode
mkernohanbc Oct 31, 2024
50f8cc9
reworking example banners on vite
mkernohanbc Oct 31, 2024
f87b5eb
riffing on beta theme
mkernohanbc Nov 1, 2024
494af46
add missing prop definition to storybook
mkernohanbc Nov 1, 2024
d4682d2
story tweak
mkernohanbc Nov 1, 2024
305c6e9
reorder stories
mkernohanbc Nov 1, 2024
3a6eac5
refit alert banner layout to match sizing/spacing of header
mkernohanbc Nov 4, 2024
eb6064c
simplify padding
mkernohanbc Nov 5, 2024
9186e5d
tweak alert banner demo on vite
mkernohanbc Nov 7, 2024
60ea821
update docs link
mkernohanbc Nov 18, 2024
542538b
remove WIP "beta" theme
mkernohanbc Nov 19, 2024
3962e0f
remove alert banner story
mkernohanbc Nov 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/react-components/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import "@bcgov/bc-sans/css/BC_Sans.css";
import { Button, Footer, FooterLinks, Header } from "@/components";
import useWindowDimensions from "@/hooks/useWindowDimensions";
import {
AlertBannerPage,
ButtonPage,
ButtonGroupPage,
CheckboxGroupPage,
Expand Down Expand Up @@ -149,6 +150,7 @@ function App() {
</div>
</Header>
<Header />
<AlertBannerPage />
<main>
<h1>Components</h1>
<ButtonPage />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
.bcds-Alert-Banner {
box-sizing: border-box;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
width: 100%;
padding: var(--layout-padding-none) var(--layout-padding-medium);
}

.bcds-Alert-Banner--Container {
flex-grow: 1;
display: flex;
flex-direction: row;
align-items: center;
gap: var(--layout-padding-medium);
max-width: 1100px;
padding: var(--layout-padding-small) var(--layout-padding-none);
}

.bcds-Alert-Banner--Icon {
align-self: first baseline;
justify-self: flex-start;
padding-top: var(--layout-padding-xsmall);
color: var(--icons-color-primary-invert);
}

.bcds-Alert-Banner--Content {
display: inline-flex;
gap: var(--layout-margin-medium);
align-items: first baseline;
flex-grow: 1;
flex-wrap: wrap;
font: var(--typography-regular-body);
color: var(--typography-color-primary-invert);
}

.bcds-Alert-Banner--closeIcon {
align-self: first baseline;
}

.bcds-Alert-Banner--closeIcon > .bcds-react-aria-Button[data-hovered] svg {
color: var(--icons-color-primary);
}

.bcds-Alert-Banner--closeIcon svg {
color: var(--icons-color-primary-invert);
}

/* Variants */

/* Info theme */
.bcds-Alert-Banner.info {
background-color: var(--surface-color-background-dark-blue);
}

/* Success theme */
.bcds-Alert-Banner.success {
background-color: var(--support-border-color-success);
}

/* Warning theme */
.bcds-Alert-Banner.warning {
background-color: var(--support-border-color-warning);
}

.bcds-Alert-Banner.warning .bcds-Alert-Banner--Icon {
color: var(--icons-color-primary);
}

.bcds-Alert-Banner.warning .bcds-Alert-Banner--Content {
color: var(--typography-color-primary);
}

.bcds-Alert-Banner.warning .bcds-Alert-Banner--closeIcon svg {
color: var(--icons-color-primary);
}

/* Danger theme */
.bcds-Alert-Banner.danger {
background-color: var(--support-border-color-danger);
}

/* Black theme */

.bcds-Alert-Banner.black {
background-color: var(--theme-gray-110);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import "./AlertBanner.css";
import Button from "../Button";
import SvgCheckCircleIcon from "../Icons/SvgCheckCircleIcon";
import SvgCloseIcon from "../Icons/SvgCloseIcon";
import SvgExclamationCircleIcon from "../Icons/SvgExclamationCircleIcon";
import SvgExclamationIcon from "../Icons/SvgExclamationIcon";
import SvgInfoIcon from "../Icons/SvgInfoIcon";

export interface AlertBannerProps extends React.PropsWithChildren {
/* Sets banner theme */
variant?: "info" | "success" | "warning" | "danger" | "black";
/* Hides icon */
isIconHidden?: boolean;
/* Toggles display of close button */
isCloseable?: boolean;
/* Sets ARIA role, defaults to 'status' */
role?: React.AriaRole | undefined;
/* Overrides theme icon */
customIcon?: React.ReactNode;
/* Controls behaviour of close button */
onClose?: () => void;
}

/* Sets correct icon for theme */
function getIcon(variant: string) {
switch (variant) {
case "info":
return <SvgInfoIcon />;
case "black":
return <SvgInfoIcon />;
case "success":
return <SvgCheckCircleIcon />;
case "warning":
return <SvgExclamationIcon />;
case "danger":
return <SvgExclamationCircleIcon />;
default:
return;
}
}

export default function AlertBanner({
variant = "info",
isIconHidden = false,
isCloseable = true,
role = "status",
onClose,
children,
customIcon,
...props
}: AlertBannerProps) {
return (
<div className={`bcds-Alert-Banner ${variant}`} {...props}>
<div className="bcds-Alert-Banner--Container">
{" "}
{!isIconHidden && (
<span className="bcds-Alert-Banner--Icon">
{customIcon ? customIcon : getIcon(variant)}
</span>
)}
<div className="bcds-Alert-Banner--Content" role={role}>
{children}
</div>
{isCloseable && (
<span className="bcds-Alert-Banner--closeIcon">
<Button
variant="tertiary"
isIconButton
size="small"
aria-label="Close this alert"
type="button"
onPress={onClose}
>
<SvgCloseIcon />
</Button>
</span>
)}
</div>
</div>
);
}
2 changes: 2 additions & 0 deletions packages/react-components/src/components/AlertBanner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from "./AlertBanner";
export type { AlertBannerProps } from "./AlertBanner";
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export default function SvgBcOutlineIcon({ id = "bc-outline-icon" }) {
return (
<svg
id={id}
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 18 18"
fill="currentColor"
>
<g>
<path
d="M8.55494 17.9955C8.48489 17.9953 8.4157 17.9801 8.35199 17.951C8.28827 17.9219 8.23149 17.8795 8.18543 17.8268L7.40648 16.9832L6.22541 16.0636L5.199 15.4961C5.11007 15.4438 5.03665 15.3688 4.98625 15.2788C4.93585 15.1887 4.91028 15.0869 4.91217 14.9838V13.6103C4.90822 13.4748 4.9534 13.3423 5.03939 13.2374C5.12538 13.1325 5.24638 13.0622 5.3801 13.0395L5.90315 12.9832C5.85315 12.9105 5.81957 12.8278 5.80473 12.7408L5.47065 10.7162L4.85199 9.65994C4.77992 9.54214 4.75071 9.40308 4.76932 9.26624L5.06009 7.19318L4.03761 6.7708C3.97024 6.74182 3.90941 6.69953 3.85878 6.64647C3.80814 6.59342 3.76873 6.53069 3.74291 6.46204L2.8481 4.13645L2.06072 4.06615C1.97763 4.05479 1.89849 4.02362 1.82998 3.97527C1.76146 3.92691 1.70557 3.86279 1.66703 3.78831L0.0922668 0.863752C0.0326295 0.767506 0.000706201 0.65667 1.15824e-05 0.543447C-0.000683036 0.430224 0.0298779 0.319005 0.0883299 0.222035C0.14711 0.132622 0.233402 0.0647766 0.33416 0.0287553C0.434919 -0.00726609 0.544665 -0.00950484 0.646809 0.0223775C0.717673 0.042062 7.83223 2.31085 11.7298 1.5634C11.7994 1.5514 11.8709 1.55502 11.9389 1.57398C12.007 1.59295 12.0701 1.62679 12.1235 1.67307C12.2388 1.77389 12.3119 1.91446 12.3282 2.06676L13.0245 9.77692L13.6994 10.2111C13.7984 10.2792 13.8741 10.3762 13.9159 10.4889L14.1836 11.2324L15.3647 11.7251C15.4523 11.7653 15.5285 11.8268 15.5862 11.904C15.6439 11.9812 15.6812 12.0717 15.6948 12.1672L15.8326 13.0749L16.5131 13.5249C16.5697 13.5613 16.6179 13.6092 16.6549 13.6655L17.8922 15.4179C17.9503 15.5022 17.9865 15.5996 17.9975 15.7013C18.0085 15.803 17.9939 15.9059 17.9552 16.0006C17.9216 16.0925 17.8628 16.1731 17.7857 16.2333C17.7085 16.2934 17.616 16.3307 17.5187 16.3409L10.2529 16.9123C10.2067 17.0062 10.136 17.0859 10.0482 17.1429L8.81084 17.9252C8.73397 17.9725 8.64519 17.9969 8.55494 17.9955ZM5.97851 14.6356L6.76589 15.0619C6.79052 15.0739 6.81311 15.0896 6.83282 15.1086L8.07014 16.0827L8.13706 16.139L8.65224 16.7098L9.43962 16.2211L9.11342 15.5642L8.32604 14.8893L7.08872 14.0367L5.96389 14.1581L5.97851 14.6356ZM7.22539 12.8595C7.32381 12.8587 7.42002 12.8888 7.50041 12.9456L8.91601 13.9197L8.96719 13.959L9.85187 14.7414C9.91189 14.7939 9.95904 14.8595 9.98966 14.9331L10.3834 15.7588L16.4957 15.2768L15.9136 14.4551L15.1262 13.923C15.0604 13.8776 15.0044 13.8193 14.9618 13.7517C14.9191 13.684 14.8907 13.6084 14.8782 13.5294L14.7522 12.6857L13.6156 12.2161C13.5437 12.1851 13.4791 12.1395 13.4256 12.0823C13.3722 12.0251 13.3312 11.9575 13.3051 11.8837L13.0183 11.1014L12.2826 10.6166C12.2115 10.567 12.1521 10.5025 12.1085 10.4274C12.065 10.3524 12.0384 10.2688 12.0307 10.1824L11.3631 2.78271C8.21693 3.17641 3.76484 2.09432 1.6136 1.48916L2.40098 2.94413L3.24461 3.01837C3.34242 3.03086 3.43481 3.07037 3.5114 3.13246C3.588 3.19455 3.64577 3.27677 3.67823 3.36988L4.61015 5.78826L5.83341 6.27307C5.94925 6.32592 6.04441 6.41555 6.10411 6.52802C6.1638 6.6405 6.1847 6.76953 6.16355 6.8951L5.83341 9.20719L6.42844 10.192C6.46921 10.2576 6.49601 10.3309 6.50718 10.4074L6.86094 12.5513C6.8826 12.6703 6.8675 12.7932 6.81764 12.9034L7.18321 12.8601L7.22539 12.8595Z"
fill="currentColor"
/>
<path
d="M4.04436 12.2499C3.95082 12.2486 3.8594 12.2218 3.78006 12.1722C3.70073 12.1226 3.63652 12.0522 3.59443 11.9687L2.23676 9.43722C2.19774 9.36465 2.17379 9.28495 2.16634 9.20289C2.1589 9.12084 2.16812 9.03813 2.19345 8.95973C2.21557 8.8832 2.2541 8.81242 2.30636 8.7523C2.35861 8.69218 2.42334 8.64416 2.49603 8.61159L3.4004 8.2179C3.46575 8.19146 3.53591 8.17896 3.60637 8.1812C3.67684 8.18345 3.74606 8.20039 3.80959 8.23094C3.87313 8.26149 3.92959 8.30498 3.97534 8.35862C4.02109 8.41225 4.05514 8.47486 4.0753 8.54241C4.12772 8.68078 4.12656 8.83374 4.07204 8.97129C4.01752 9.10884 3.91357 9.22106 3.78059 9.28593L3.44314 9.43047L4.48923 11.3866C4.56015 11.5165 4.58089 11.6679 4.54751 11.8122C4.51412 11.9564 4.42894 12.0833 4.30814 12.1689C4.23031 12.2217 4.13841 12.2499 4.04436 12.2499Z"
fill="currentColor"
/>
</g>
</svg>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./SvgBcOutlineIcon";
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* The component implements the Flask icon from Font Awesome: https://fontawesome.com/icons/flask */
export default function SvgBetaIcon({ id = "beta-icon" }) {
return (
<svg
id={id}
width="20"
height="20"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<g>
<path
d="M288 0L160 0 128 0C110.3 0 96 14.3 96 32s14.3 32 32 32l0 132.8c0 11.8-3.3 23.5-9.5 33.5L10.3 406.2C3.6 417.2 0 429.7 0 442.6C0 480.9 31.1 512 69.4 512l309.2 0c38.3 0 69.4-31.1 69.4-69.4c0-12.8-3.6-25.4-10.3-36.4L329.5 230.4c-6.2-10.1-9.5-21.7-9.5-33.5L320 64c17.7 0 32-14.3 32-32s-14.3-32-32-32L288 0zM192 196.8L192 64l64 0 0 132.8c0 23.7 6.6 46.9 19 67.1L309.5 320l-171 0L173 263.9c12.4-20.2 19-43.4 19-67.1z"
fill="currentColor"
/>
</g>
</svg>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./SvgBetaIcon";
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* The component implements the Circle Check icon from Font Awesome: https://fontawesome.com/icons/circle-check */
export default function SvgCheckCircleIcon({ id = "check-icon" }) {
return (
<svg
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* The component implements the Check icon from Font Awesome: https://fontawesome.com/icons/check */
export default function SvgCheckIcon({ id = "check-icon" }) {
return (
<svg
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* The component implements the Chevron Down icon from Font Awesome: https://fontawesome.com/icons/chevron-down */
export default function SvgChevronDownIcon({ id = "chevron-down-icon" }) {
return (
<svg
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* The component implements the Chevron Up icon from Font Awesome: https://fontawesome.com/icons/chevron-up */
export default function SvgChevronUpIcon({ id = "chevron-up-icon" }) {
return (
<svg
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* The component implements the X Mark icon from Font Awesome: https://fontawesome.com/icons/xmark */
export default function SvgCloseIcon({ id = "close-icon" }) {
return (
<svg
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* The component implements the Circle Exclamation icon from Font Awesome: https://fontawesome.com/icons/circle-exclamation */
export default function SvgExclamationCircleIcon({
id = "exclamation-icon-circle",
}) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This icon is available as a plain SVG at src/assets/icon-exclamation.svg
/* The component implements the Triangle Exclamation icon from Font Awesome: https://fontawesome.com/icons/triangle-exclamation */
export default function SvgExclamationIcon({ id = "exclamation-icon" }) {
return (
<svg
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* The component implements the Circle Info icon from Font Awesome: https://fontawesome.com/icons/circle-info */
export default function SvgInfoIcon({ id = "information-icon" }) {
return (
<svg
Expand Down
3 changes: 3 additions & 0 deletions packages/react-components/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "@bcgov/design-tokens/css/variables.css";

export { default as AlertBanner } from "./AlertBanner";
export { default as AlertDialog } from "./AlertDialog";
export { default as Button } from "./Button";
export { default as ButtonGroup } from "./ButtonGroup";
Expand All @@ -15,6 +16,8 @@ export { default as Radio } from "./Radio";
export { default as RadioGroup } from "./RadioGroup";
export { default as Select } from "./Select";
export { default as SvgBcLogo } from "./Icons/SvgBcLogo";
export { default as SvgBcOutlineIcon } from "./Icons/SvgBcOutlineIcon";
export { default as SvgBetaIcon } from "./Icons/SvgBetaIcon";
export { default as SvgCheckIcon } from "./Icons/SvgCheckIcon";
export { default as SvgCheckCircleIcon } from "./Icons/SvgCheckCircleIcon";
export { default as SvgDashIcon } from "./Icons/SvgDashIcon";
Expand Down
66 changes: 66 additions & 0 deletions packages/react-components/src/pages/AlertBanner/AlertBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { AlertBanner } from "@/components";
import { Button } from "@/components";
import { SvgBcOutlineIcon } from "@/components";
import { useState } from "react";

interface BannerState {
[key: string]: boolean;
}

export default function AlertBannerPage() {
const [banners, setBanners] = useState<BannerState>({
banner1: true,
banner2: true,
banner3: true,
banner4: true,
banner5: true,
banner6: true,
});

const handleClose = (bannerId: string) => {
setBanners((prev) => ({
...prev,
[bannerId]: false,
}));
};
return (
<>
{banners.banner1 && (
<AlertBanner onClose={() => handleClose("banner1")}>
Alert banner in its default configuration
</AlertBanner>
)}
{banners.banner2 && (
<AlertBanner variant="success" onClose={() => handleClose("banner2")}>
Success theme
</AlertBanner>
)}
{banners.banner3 && (
<AlertBanner variant="warning" onClose={() => handleClose("banner3")}>
Warning theme with an additional call-to-action button
<Button variant="secondary" size="small">
Take an action
</Button>
</AlertBanner>
)}
{banners.banner4 && (
<AlertBanner
variant="danger"
isCloseable={false}
onClose={() => handleClose("banner4")}
>
Danger theme with close button disabled
</AlertBanner>
)}
{banners.banner5 && (
<AlertBanner
variant="black"
customIcon={<SvgBcOutlineIcon />}
onClose={() => handleClose("banner5")}
>
Dark theme with a custom icon
</AlertBanner>
)}
</>
);
}
3 changes: 3 additions & 0 deletions packages/react-components/src/pages/AlertBanner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import AlertBannerPage from "./AlertBanner";

export default AlertBannerPage;
2 changes: 2 additions & 0 deletions packages/react-components/src/pages/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import AlertBannerPage from "./AlertBanner";
import ButtonPage from "./Button";
import ButtonGroupPage from "./ButtonGroup";
import CheckboxGroupPage from "./CheckboxGroup";
Expand All @@ -12,6 +13,7 @@ import SwitchPage from "./Switch";
import TooltipPage from "./Tooltip";

export {
AlertBannerPage,
ButtonPage,
ButtonGroupPage,
CheckboxGroupPage,
Expand Down
Loading
Loading