-
Notifications
You must be signed in to change notification settings - Fork 34
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
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 blue from "./colors/blue"; | ||
|
||
interface Props { | ||
alertHeader: string; | ||
alertSubheader?: string; | ||
backgroundColor?: string; | ||
collapsable?: boolean; | ||
children?: ReactChild; | ||
Icon?: any; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can probably be a |
||
} | ||
|
||
const AlertContainer = styled.div<{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we consider going more semantic and using a details tag? |
||
backgroundColor: string; | ||
collapsable: 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<{ | ||
collapsable: boolean; | ||
}>` | ||
margin-top: ${props => (props.collapsable ? "1em" : ".5em")}; | ||
`; | ||
|
||
const Alert = ({ | ||
alertHeader, | ||
alertSubheader, | ||
backgroundColor, | ||
children, | ||
collapsable, | ||
Icon = Bell | ||
}: Props): JSX.Element => { | ||
const [expandAlert, setExpandAlert] = useState(false); | ||
return ( | ||
<AlertContainer | ||
backgroundColor={backgroundColor} | ||
expandAlert={expandAlert} | ||
collapsable={collapsable} | ||
> | ||
<Icon size={24} /> | ||
<AlertHeader>{alertHeader}</AlertHeader> | ||
<ButtonContainer> | ||
{collapsable && ( | ||
<button type="button" onClick={() => setExpandAlert(!expandAlert)}> | ||
<ChevronUp size={16} /> | ||
</button> | ||
)} | ||
</ButtonContainer> | ||
{alertSubheader && <AlertSubheader>{alertSubheader}</AlertSubheader>} | ||
{children && ( | ||
<AlertContent> | ||
<AnimateHeight | ||
duration={500} | ||
height={collapsable ? (expandAlert ? "auto" : 0) : "auto"} | ||
> | ||
<ContentPadding collapsable={collapsable}> | ||
{children} | ||
</ContentPadding> | ||
</AnimateHeight> | ||
</AlertContent> | ||
)} | ||
</AlertContainer> | ||
); | ||
}; | ||
|
||
export default Alert; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import React, { ReactElement } from "react"; | ||
import { Meta } from "@storybook/react"; | ||
import { Warning } from "@styled-icons/fluentui-system-regular/Warning"; | ||
import Alert from "../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) => { | ||
return ( | ||
<> | ||
<div key={alert.alertDescriptionText}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's maybe just use the counter/UUID. Using a huge body might be funky |
||
{`${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 CollapsableAlertWithTransitAlerts = (): ReactElement => { | ||
return ( | ||
<Alert | ||
backgroundColor={red[50]} | ||
collapsable | ||
Icon={Warning} | ||
alertHeader="Your trip has alerts" | ||
> | ||
<AlertContent /> | ||
</Alert> | ||
); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is causing a huge
yarn.lock
increase. We should probably only depend on the one icon set we need