Skip to content

Commit 583898a

Browse files
Merge branch 'dev' into a11y-search-form
2 parents d464458 + f8fd93e commit 583898a

25 files changed

+550
-314
lines changed

Diff for: i18n/en-US.yml

+3
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,9 @@ components:
557557
bicyclesAllowed: Allowed
558558
header: Trip Viewer
559559
listOfRouteStops: List of stops on this route
560+
tripDescription: Board at {boardAtStop} and disembark at {disembarkAtStop}
561+
startOfTrip: Trip begins here
562+
endOfTrip: Trip ends here
560563
routeHeader: "Route: <strong>{routeShortName}</strong> {routeLongName}"
561564
viewStop: View
562565
UserAccountScreen:

Diff for: index.css

+8
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,14 @@ input[type="text"]::-ms-clear {
165165
padding: 1rem 0;
166166
}
167167

168+
/* Header image or title */
169+
/* If an icon is used, visually-hide the title (but keep it visible to screen readers). */
170+
.with-icon div.navbar-title {
171+
height: 0;
172+
overflow: hidden;
173+
width: 0;
174+
}
175+
168176
/* Buttons */
169177

170178
button.header,

Diff for: lib/actions/ui.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export function setViewedRoute(payload) {
123123
/**
124124
* Sets the main panel content according to the payload (one of the enum values
125125
* of MainPanelContent) and routes the application to the correct path.
126-
* @param {number} payload MainPanelContent value
126+
* @param {number|null} payload MainPanelContent value
127127
*/
128128
export function setMainPanelContent(payload) {
129129
return function (dispatch, getState) {

Diff for: lib/components/app/app-frame.js

-41
This file was deleted.

Diff for: lib/components/app/app-frame.tsx

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Col, Row } from 'react-bootstrap'
2+
import React, { ComponentType, FC, HTMLAttributes } from 'react'
3+
4+
import DesktopNav from './desktop-nav'
5+
import NotFound from './not-found'
6+
7+
interface Props extends HTMLAttributes<HTMLDivElement> {
8+
SubNav?: ComponentType
9+
}
10+
11+
/**
12+
* This component defines the general application frame, to which
13+
* content and an optional sub-navigation component can be inserted.
14+
*/
15+
const AppFrame = ({ children, SubNav }: Props): JSX.Element => (
16+
<div className="otp" id="otp">
17+
{/* TODO: Do mobile view. */}
18+
<DesktopNav />
19+
{SubNav && <SubNav />}
20+
{/* Create a main region here so that the DesktopNav, which contains a "banner" landmark,
21+
is not contained within the main or other landmark
22+
(see https://dequeuniversity.com/rules/axe/4.3/landmark-banner-is-top-level?application=axe-puppeteer) */}
23+
<main tabIndex={-1}>
24+
<div className="container">
25+
<Row>
26+
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12}>
27+
{children}
28+
</Col>
29+
</Row>
30+
</div>
31+
</main>
32+
</div>
33+
)
34+
35+
/**
36+
* Creates a simple wrapper component consisting of an AppFrame that surrounds
37+
* the provided component. (Displays "Content not found" if none provided.)
38+
*/
39+
export function frame(Component: ComponentType): FC {
40+
const FramedComponent = () => (
41+
<AppFrame>{Component ? <Component /> : <NotFound />}</AppFrame>
42+
)
43+
return FramedComponent
44+
}
45+
46+
export default AppFrame

Diff for: lib/components/app/desktop-nav.tsx

+48-60
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ const NavItemOnLargeScreens = styled(NavItem)`
1919
display: none !important;
2020
}
2121
`
22+
// Typscript TODO: otpConfig type
23+
export type Props = {
24+
otpConfig: any
25+
popupTarget?: string
26+
setPopupContent: (url: string) => void
27+
}
2228

2329
/**
2430
* The desktop navigation bar, featuring a `branding` logo or a `title` text
@@ -27,81 +33,63 @@ const NavItemOnLargeScreens = styled(NavItem)`
2733
* The `branding` and `title` parameters in config.yml are handled
2834
* and shown in this order in the navigation bar:
2935
* 1. If `branding` is defined, it is shown, and no title is displayed.
36+
* (The title is still rendered for screen readers and browsers that lack image support.)
3037
* 2. If `branding` is not defined but if `title` is, then `title` is shown.
3138
* 3. If neither is defined, just show 'OpenTripPlanner' (DEFAULT_APP_TITLE).
3239
*
3340
* TODO: merge with the mobile navigation bar.
3441
*/
35-
// Typscript TODO: otpConfig type
36-
export type Props = {
37-
otpConfig: any
38-
popupTarget?: string
39-
setPopupContent: (url: string) => void
40-
}
41-
4242
const DesktopNav = ({ otpConfig, popupTarget, setPopupContent }: Props) => {
4343
const { branding, persistence, title = DEFAULT_APP_TITLE } = otpConfig
4444
const { language: configLanguages } = otpConfig
4545
const showLogin = Boolean(getAuth0Config(persistence))
4646

47-
// Display branding and title in the order as described in the class summary.
48-
let brandingOrTitle
49-
if (branding) {
50-
brandingOrTitle = (
51-
<div
52-
className={`icon-${branding}`}
53-
// FIXME: Style hack for desktop view.
54-
style={{ marginLeft: 50 }}
55-
/>
56-
)
57-
} else {
58-
brandingOrTitle = (
59-
<div className="navbar-title" style={{ marginLeft: 50 }}>
60-
{title}
61-
</div>
62-
)
63-
}
64-
6547
return (
66-
<Navbar fluid inverse>
67-
{/* Required to allow the hamburger button to be clicked */}
68-
<Navbar.Header style={{ position: 'relative', width: '100%', zIndex: 2 }}>
69-
<Navbar.Brand>
70-
{/* TODO: Reconcile CSS class and inline style. */}
71-
<div
72-
className="app-menu-container"
73-
style={{ color: 'white', float: 'left', marginTop: '5px' }}
74-
>
48+
<header>
49+
<Navbar fluid inverse>
50+
<Navbar.Header
51+
style={{ position: 'relative', width: '100%', zIndex: 2 }}
52+
>
53+
<Navbar.Brand>
7554
<AppMenu />
76-
</div>
55+
<div
56+
className={branding && `with-icon icon-${branding}`}
57+
style={{ marginLeft: 50 }}
58+
>
59+
{/* A title is always rendered (e.g.for screen readers)
60+
but is visually-hidden if a branding icon is used. */}
61+
<div className="navbar-title">{title}</div>
62+
</div>
63+
</Navbar.Brand>
7764

78-
{brandingOrTitle}
79-
</Navbar.Brand>
80-
<ViewSwitcher sticky />
65+
<ViewSwitcher sticky />
8166

82-
<Nav pullRight>
83-
{popupTarget && (
84-
<NavItemOnLargeScreens onClick={() => setPopupContent(popupTarget)}>
85-
<FormattedMessage id={`config.popups.${popupTarget}`} />
86-
</NavItemOnLargeScreens>
87-
)}
88-
{configLanguages &&
89-
// Ensure that > 1 valid language is defined
90-
Object.keys(configLanguages).filter(
91-
(key) => key !== 'allLanguages' && configLanguages[key].name
92-
).length > 1 && (
93-
<LocaleSelector configLanguages={configLanguages} />
67+
<Nav pullRight>
68+
{popupTarget && (
69+
<NavItemOnLargeScreens
70+
onClick={() => setPopupContent(popupTarget)}
71+
>
72+
<FormattedMessage id={`config.popups.${popupTarget}`} />
73+
</NavItemOnLargeScreens>
74+
)}
75+
{configLanguages &&
76+
// Ensure that > 1 valid language is defined
77+
Object.keys(configLanguages).filter(
78+
(key) => key !== 'allLanguages' && configLanguages[key].name
79+
).length > 1 && (
80+
<LocaleSelector configLanguages={configLanguages} />
81+
)}
82+
{showLogin && (
83+
<NavLoginButtonAuth0
84+
id="login-control"
85+
links={accountLinks}
86+
style={{ float: 'right' }}
87+
/>
9488
)}
95-
{showLogin && (
96-
<NavLoginButtonAuth0
97-
id="login-control"
98-
links={accountLinks}
99-
style={{ float: 'right' }}
100-
/>
101-
)}
102-
</Nav>
103-
</Navbar.Header>
104-
</Navbar>
89+
</Nav>
90+
</Navbar.Header>
91+
</Navbar>
92+
</header>
10593
)
10694
}
10795

Diff for: lib/components/app/view-switcher.js

-86
This file was deleted.

0 commit comments

Comments
 (0)