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

Create Alert Component #744

Merged
merged 10 commits into from
Nov 5, 2024
4 changes: 4 additions & 0 deletions packages/building-blocks/i18n/en-US.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
otpUi:
buildingBlocks:
alert:
expand: Expand
4 changes: 4 additions & 0 deletions packages/building-blocks/i18n/fr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
otpUi:
buildingBlocks:
alert:
expand: Développer
6 changes: 5 additions & 1 deletion packages/building-blocks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
},
"peerDependencies": {
"react": "^18.2.0",
"react-animate-height": "^3.0.4",
"styled-components": "^5.3.0"
},
"repository": {
Expand All @@ -27,5 +28,8 @@
"bugs": {
"url": "https://github.com/opentripplanner/otp-ui/issues"
},
"gitHead": "0af1b7cda60bd4252b219dcf893e01c2acb2ed5d"
"gitHead": "0af1b7cda60bd4252b219dcf893e01c2acb2ed5d",
"dependencies": {
"@styled-icons/bootstrap": "^10.47.0"
}
}
136 changes: 136 additions & 0 deletions packages/building-blocks/src/alert/Alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import React, { ReactChild, useState } from "react";
import styled from "styled-components";
import AnimateHeight from "react-animate-height";
import { ChevronUp } from "@styled-icons/bootstrap/ChevronUp";
import { Bell } from "@styled-icons/bootstrap/Bell";
import { StyledIcon } from "@styled-icons/styled-icon";
import { useIntl } from "react-intl";
import blue from "../colors/blue";

interface Props {
alertHeader: string;
alertSubheader?: string;
backgroundColor?: string;
collapsible?: boolean;
children?: ReactChild;
Icon?: StyledIcon;
}

const AlertContainer = styled.div<{
backgroundColor: string;
collapsible: boolean;
expandAlert: boolean;
}>`
background-color: ${props =>
props.backgroundColor ? props.backgroundColor : blue[50]};
display: grid;
grid-template-columns: 50px auto auto;
grid-template-rows: minmax(25px, auto) auto;
max-width: 715px;
padding: 1.5em 2em;

svg {
align-self: center;
grid-column: 1;
grid-row: 1 / span 2;
justify-self: start;
}

button {
background: transparent;
border: none;
width: 40px;

svg {
transform: ${props => !props.expandAlert && "rotate(180deg)"};
transition: all 0.2s ease-in;
}
}

@media (max-width: 550px) {
grid-template-columns: 40px auto auto;
padding: 1.25em 1.25em;
}
`;

const ButtonContainer = styled.span`
align-items: center;
display: flex;
justify-content: center;
justify-self: right;
`;

const AlertHeader = styled.span`
align-self: center;
font-weight: 700;
grid-column: 2;
`;

const AlertSubheader = styled(AlertHeader)`
font-weight: 400;
margin-top: 0.3em;
`;

const AlertContent = styled.div`
grid-column: 2;
grid-row: 3;
`;

const ContentPadding = styled.div<{
collapsible: boolean;
}>`
margin-top: ${props => (props.collapsible ? "1em" : ".5em")};
`;

const Alert = ({
alertHeader,
alertSubheader,
backgroundColor,
children,
collapsible,
Icon = Bell
}: Props): JSX.Element => {
const [expandAlert, setExpandAlert] = useState(false);
const intl = useIntl();
const label = intl.formatMessage({
id: "otpUi.buildingBlocks.alert.expand",
defaultMessage: "Expand"
});
return (
<AlertContainer
backgroundColor={backgroundColor}
expandAlert={expandAlert}
collapsible={collapsible}
>
<Icon size={24} />
<AlertHeader>{alertHeader}</AlertHeader>
<ButtonContainer>
{collapsible && (
<button
type="button"
onClick={() => setExpandAlert(!expandAlert)}
aria-label={label}
title={label}
>
<ChevronUp size={16} />
</button>
)}
</ButtonContainer>
{alertSubheader && <AlertSubheader>{alertSubheader}</AlertSubheader>}
{children && (
<AlertContent>
<AnimateHeight
duration={500}
height={collapsible ? (expandAlert ? "auto" : 0) : "auto"}
>
<ContentPadding collapsible={collapsible}>
{children}
</ContentPadding>
</AnimateHeight>
</AlertContent>
)}
</AlertContainer>
);
};

export default Alert;
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Building-Blocks/Alert BasicAlert smoke-test 1`] = `
<div class="Alert__AlertContainer-sc-2vlo3n-0 gPtodQ">
<svg viewbox="0 0 16 16"
height="24"
width="24"
aria-hidden="true"
focusable="false"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
class="StyledIconBase-sc-ea9ulj-0 kcHuPT"
>
<path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z">
</path>
</svg>
<span class="Alert__AlertHeader-sc-2vlo3n-2 eDIciz">
Next trip starts on Wednesday April 17th
</span>
<span class="Alert__ButtonContainer-sc-2vlo3n-1 jSUXYc">
</span>
<span class="Alert__AlertHeader-sc-2vlo3n-2 Alert__AlertSubheader-sc-2vlo3n-3 eDIciz dtxEUe">
Trip is due to begin at 7:43 AM (Realtime monitoring will being at 7:13 AM)
</span>
<div class="Alert__AlertContent-sc-2vlo3n-4 hzBuor">
<div aria-hidden="false"
class="rah-static rah-static--height-auto "
style="height: auto; overflow: visible;"
>
<div>
<div class="Alert__ContentPadding-sc-2vlo3n-5 guzSYn">
Here is more content
</div>
</div>
</div>
</div>
</div>
`;

exports[`Building-Blocks/Alert CollapsibleAlertWithTransitAlerts smoke-test 1`] = `
<div class="Alert__AlertContainer-sc-2vlo3n-0 dxIAKf">
<svg viewbox="0 0 16 16"
height="24"
width="24"
aria-hidden="true"
focusable="false"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
class="StyledIconBase-sc-ea9ulj-0 kcHuPT"
>
<path d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.146.146 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.163.163 0 0 1-.054.06.116.116 0 0 1-.066.017H1.146a.115.115 0 0 1-.066-.017.163.163 0 0 1-.054-.06.176.176 0 0 1 .002-.183L7.884 2.073a.147.147 0 0 1 .054-.057zm1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566z">
</path>
<path d="M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995z">
</path>
</svg>
<span class="Alert__AlertHeader-sc-2vlo3n-2 eDIciz">
Your trip has alerts
</span>
<span class="Alert__ButtonContainer-sc-2vlo3n-1 jSUXYc">
<button type="button"
aria-label="Expand"
title="Expand"
>
<svg viewbox="0 0 16 16"
height="16"
width="16"
aria-hidden="true"
focusable="false"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
class="StyledIconBase-sc-ea9ulj-0 kcHuPT"
>
<path fill-rule="evenodd"
d="M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708l6-6z"
>
</path>
</svg>
</button>
</span>
<div class="Alert__AlertContent-sc-2vlo3n-4 hzBuor">
<div aria-hidden="true"
class="rah-static rah-static--height-zero "
style="height: 0px; overflow: hidden;"
>
<div style="display: none;">
<div class="Alert__ContentPadding-sc-2vlo3n-5 frerzB">
<div>
1) TriMet Customer Service will be unavailable to serve text messages or Twitter responses from 9:00 p.m.- 11:30 p.m. For immediate assistance regarding safety or security concerns, please contact the police via 911.
</div>
<br>
<div>
2) The Park and Ride garage elevator at Sunset Transit Center is closed for approximately 3 months for improvements. During this time garage users must use the stairs or find alternate parking. Visit trimet.org/parkandride for a complete list of Park and Ride garages.
</div>
<br>
<div>
3) The west elevators at the Washington Park MAX Station are out of service. Please use east elevators to access street level and platforms.
</div>
<br>
</div>
</div>
</div>
</div>
</div>
`;
77 changes: 77 additions & 0 deletions packages/building-blocks/src/stories/alerts.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React, { ReactElement } from "react";
import { Meta } from "@storybook/react";
import { ExclamationTriangle } from "@styled-icons/bootstrap/ExclamationTriangle";
import Alert from "../alert/Alert";
import red from "../colors/red";

const meta: Meta<typeof Alert> = {
title: "Building-Blocks/Alert",
component: Alert
};

export default meta;

const alerts = [
{
alertUrl: "http://trimet.org/alerts/",
effectiveStartDate: 1576471800,
alertDescriptionText:
"TriMet Customer Service will be unavailable to serve text messages or Twitter responses from 9:00 p.m.- 11:30 p.m. For immediate assistance regarding safety or security concerns, please contact the police via 911."
},
{
alertUrl:
"https://news.trimet.org/2019/11/next-up-for-elevator-improvements-sunset-transit-center-park-ride/",
effectiveStartDate: 1573083439,
alertDescriptionText:
"The Park and Ride garage elevator at Sunset Transit Center is closed for approximately 3 months for improvements. During this time garage users must use the stairs or find alternate parking. Visit trimet.org/parkandride for a complete list of Park and Ride garages."
},
{
alertUrl: "http://trimet.org/alerts/",
effectiveStartDate: 1572827580,
alertDescriptionText:
"The west elevators at the Washington Park MAX Station are out of service. Please use east elevators to access street level and platforms. "
}
];

const AlertContent = () => {
return (
<>
{alerts.map((alert, i) => {
const alertKey = crypto.randomUUID();
return (
<>
<div key={alertKey}>
{`${i + 1}) `}
{alert.alertDescriptionText}
</div>
<br />
</>
);
})}
</>
);
};

export const BasicAlert = (): ReactElement => {
return (
<Alert
alertHeader="Next trip starts on Wednesday April 17th"
alertSubheader="Trip is due to begin at 7:43 AM (Realtime monitoring will being at 7:13 AM)"
>
Here is more content
</Alert>
);
};

export const CollapsibleAlertWithTransitAlerts = (): ReactElement => {
return (
<Alert
backgroundColor={red[50]}
collapsible
Icon={ExclamationTriangle}
alertHeader="Your trip has alerts"
>
<AlertContent />
</Alert>
);
};
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6168,6 +6168,14 @@
"@babel/runtime" "^7.14.0"
"@styled-icons/styled-icon" "^10.6.3"

"@styled-icons/bootstrap@^10.47.0":
version "10.47.0"
resolved "https://registry.yarnpkg.com/@styled-icons/bootstrap/-/bootstrap-10.47.0.tgz#c3e363dfe87b732a5da818f320f90f5ab4961b84"
integrity sha512-xpnPdrLhAhpTRE4iljQIEK73twVj7VPglwHSL+8nQdH7EsW5RJIOWsmlkZMyqhQHN0H7fGmT10F3/6OQhSpfGg==
dependencies:
"@babel/runtime" "^7.20.7"
"@styled-icons/styled-icon" "^10.7.0"

"@styled-icons/[email protected]":
version "10.38.0"
resolved "https://registry.yarnpkg.com/@styled-icons/boxicons-logos/-/boxicons-logos-10.38.0.tgz#f51442c49f1a28c61927d6d2f8c1e2d7946faf46"
Expand Down
Loading