diff --git a/i18n/en-US.yml b/i18n/en-US.yml index 829ce025f..ac4c22d5a 100644 --- a/i18n/en-US.yml +++ b/i18n/en-US.yml @@ -550,6 +550,7 @@ components: accessible: Accessible bicyclesAllowed: Allowed header: Trip Viewer + listOfRouteStops: List of stops on this route routeHeader: "Route: {routeShortName} {routeLongName}" viewStop: View UserAccountScreen: diff --git a/lib/components/viewers/trip-viewer.js b/lib/components/viewers/trip-viewer.js index bfe164b45..d40c934f0 100644 --- a/lib/components/viewers/trip-viewer.js +++ b/lib/components/viewers/trip-viewer.js @@ -1,14 +1,16 @@ +/* eslint-disable react/jsx-indent */ import { ArrowLeft } from '@styled-icons/fa-solid/ArrowLeft' import { Bicycle } from '@styled-icons/fa-solid/Bicycle' import { Label as BsLabel, Button } from 'react-bootstrap' import { Circle } from '@styled-icons/fa-solid/Circle' import { connect } from 'react-redux' -import { FormattedMessage } from 'react-intl' +import { FormattedMessage, injectIntl } from 'react-intl' import { toDate } from 'date-fns-tz' import { Wheelchair } from '@styled-icons/fa-solid/Wheelchair' import coreUtils from '@opentripplanner/core-utils' import PropTypes from 'prop-types' import React, { Component } from 'react' +import styled from 'styled-components' import * as apiActions from '../../actions/api' import * as mapActions from '../../actions/map' @@ -22,11 +24,26 @@ import ViewStopButton from './view-stop-button' const { getCurrentDate } = coreUtils.time +const StopList = styled.ol` + padding-left: 0; +` +const Stop = styled.li` + list-style: none; +` +const RouteName = styled.h2` + margin-bottom: 20px; + font-size: inherit; +` +const HeaderText = styled.h1` + margin: 2px 0 0 0; +` + class TripViewer extends Component { static propTypes = { findTrip: apiActions.findTrip.type, hideBackButton: PropTypes.bool, homeTimezone: PropTypes.string, + intl: PropTypes.object, setViewedTrip: uiActions.setViewedTrip.type, tripData: PropTypes.object, viewedTrip: PropTypes.object @@ -43,7 +60,8 @@ class TripViewer extends Component { } render() { - const { hideBackButton, homeTimezone, tripData, viewedTrip } = this.props + const { hideBackButton, homeTimezone, intl, tripData, viewedTrip } = + this.props const startOfDay = toDate(getCurrentDate(homeTimezone), { timeZone: homeTimezone }) @@ -65,9 +83,9 @@ class TripViewer extends Component { )} {/* Header Text */} -
+ -
+
@@ -75,8 +93,7 @@ class TripViewer extends Component { {/* Basic Trip Info */} {tripData && (
- {/* Route name */} -
+ {tripData.route && ( )} -
+ {/* Wheelchair/bike accessibility badges, if applicable */} -

- {tripData.wheelchairAccessible === 1 && ( - - - - - - )} - - {tripData.bikesAllowed === 1 && ( - - - - - - )} -

+ {(tripData.wheelchairAccessible === 1 || + tripData.bikesAllowed === 1) && ( +
+ {tripData.wheelchairAccessible === 1 && ( + // TODO: these labels are currently insufficient for screen readers + + + + + + )} + + {tripData.bikesAllowed === 1 && ( + + + + + + )} +
+ )}
)} {/* Stop Listing */} - {tripData && - tripData.stops && - tripData.stopTimes && - tripData.stops.map((stop, i) => { - // determine whether to use special styling for first/last stop - let stripMapLineClass = 'strip-map-line' - if (i === 0) stripMapLineClass = 'strip-map-line-first' - else if (i === tripData.stops.length - 1) { - stripMapLineClass = 'strip-map-line-last' - } - - // determine whether to show highlight in strip map - let highlightClass - if (i === viewedTrip.fromIndex) { - highlightClass = 'strip-map-highlight-first' - } else if (i > viewedTrip.fromIndex && i < viewedTrip.toIndex) { - highlightClass = 'strip-map-highlight' - } else if (i === viewedTrip.toIndex) { - highlightClass = 'strip-map-highlight-last' - } - - return ( -
- {/* the departure time */} -
- -
- - {/* the vertical strip map */} -
- {highlightClass &&
} -
-
- - - -
-
- - {/* the stop-viewer button */} -
- - } - /> -
- - {/* the main stop label */} -
{stop.name}
- -
-
- ) + + {tripData && + tripData.stops && + tripData.stopTimes && + tripData.stops.map((stop, i) => { + // determine whether to use special styling for first/last stop + let stripMapLineClass = 'strip-map-line' + if (i === 0) stripMapLineClass = 'strip-map-line-first' + else if (i === tripData.stops.length - 1) { + stripMapLineClass = 'strip-map-line-last' + } + + // determine whether to show highlight in strip map + let highlightClass + if (i === viewedTrip.fromIndex) { + highlightClass = 'strip-map-highlight-first' + } else if (i > viewedTrip.fromIndex && i < viewedTrip.toIndex) { + highlightClass = 'strip-map-highlight' + } else if (i === viewedTrip.toIndex) { + highlightClass = 'strip-map-highlight-last' + } + + return ( + + {/* the departure time */} +
+ +
+ + {/* the vertical strip map */} +
+ {highlightClass &&
} +
+
+ + + +
+
+ + {/* the stop-viewer button */} +
+ {/* TODO: To a screen reader, "View" appears before the stop name. + A separate label for screen readers will need to be set up. */} + + } + /> +
+ + {/* the main stop label */} +
{stop.name}
+ +
+ + ) + })} +
) @@ -191,4 +220,7 @@ const mapDispatchToProps = { setViewedTrip: uiActions.setViewedTrip } -export default connect(mapStateToProps, mapDispatchToProps)(TripViewer) +export default connect( + mapStateToProps, + mapDispatchToProps +)(injectIntl(TripViewer)) diff --git a/percy/percy.test.js b/percy/percy.test.js index f739c8622..524c9e50f 100644 --- a/percy/percy.test.js +++ b/percy/percy.test.js @@ -352,7 +352,7 @@ test('OTP-RR', async () => { // Open stop viewer from trip viewer await page.click( - 'div.trip-viewer-body > div:nth-child(3) > div.stop-button-container > button' + 'div.trip-viewer-body > ol > li:nth-child(3) > div.stop-button-container > button' ) await page.waitForSelector('.stop-viewer')