mirror of
https://github.com/HSLdevcom/digitransit-ui
synced 2026-01-31 11:30:30 +01:00
Configuration exposed a limited set of theme colors prefixes with 'mode-' to component libraries. Many parts of UI used either a hard coded color or incorrectly HSL theme color. Now all relevant colors can put into a general use color map and component can access them. First use case is near you mode icon row's expand arrow.
163 lines
4.3 KiB
JavaScript
163 lines
4.3 KiB
JavaScript
import PropTypes from 'prop-types';
|
|
import React, { useRef, useState } from 'react';
|
|
import { isAnyLegPropertyIdentical, isRental } from '../../../util/legUtils';
|
|
import { getRouteMode, transitIconName } from '../../../util/modeUtils';
|
|
import { configShape, legShape } from '../../../util/shapes';
|
|
import Icon from '../../Icon';
|
|
import NaviCardExtension from './NaviCardExtension';
|
|
import NaviInstructions from './NaviInstructions';
|
|
import { LEGTYPE } from './NaviUtils';
|
|
import usePrevious from './hooks/usePrevious';
|
|
|
|
const iconMap = {
|
|
BICYCLE: 'icon_cyclist',
|
|
CAR: 'icon_car',
|
|
SCOOTER: 'icon_scooter_rider',
|
|
WALK: 'icon_walk',
|
|
WAIT: 'icon_navigation_wait',
|
|
CALL: 'icon_call',
|
|
WAIT_IN_VEHICLE: 'icon_wait',
|
|
};
|
|
|
|
export default function NaviCard(
|
|
{
|
|
leg,
|
|
nextLeg,
|
|
legType,
|
|
time,
|
|
position,
|
|
tailLength,
|
|
cardAnimation,
|
|
platformUpdated,
|
|
},
|
|
{ config },
|
|
) {
|
|
const [cardExpanded, setCardExpanded] = useState(false);
|
|
const contentRef = useRef();
|
|
const { isEqual: legChanged } = usePrevious(leg, (prev, current) =>
|
|
isAnyLegPropertyIdentical(prev, current, ['legId', 'mode']),
|
|
);
|
|
|
|
const handleClick = () => {
|
|
setCardExpanded(prev => !prev);
|
|
};
|
|
|
|
if (legChanged) {
|
|
setCardExpanded(false);
|
|
}
|
|
|
|
if (
|
|
(!leg && !nextLeg) ||
|
|
legType === LEGTYPE.PENDING ||
|
|
legType === LEGTYPE.END
|
|
) {
|
|
return null;
|
|
}
|
|
|
|
let iconColor = 'currentColor';
|
|
let iconName;
|
|
let instructions = '';
|
|
|
|
if (legType === LEGTYPE.TRANSIT) {
|
|
const m = getRouteMode(leg.route, config);
|
|
iconColor = config.colors[m] || leg.route.color;
|
|
iconName = transitIconName(m, false);
|
|
instructions = `navileg-in-transit`;
|
|
} else if (
|
|
legType !== LEGTYPE.WAIT &&
|
|
legType !== LEGTYPE.WAIT_IN_VEHICLE &&
|
|
isRental(leg, nextLeg)
|
|
) {
|
|
if (leg.mode === 'WALK' && nextLeg?.mode === 'SCOOTER') {
|
|
instructions = `navileg-rent-scooter`;
|
|
} else {
|
|
instructions = 'navileg-rent-cycle';
|
|
}
|
|
iconName = iconMap[leg.mode];
|
|
} else if (legType === LEGTYPE.MOVE) {
|
|
instructions = `navileg-${leg.mode.toLowerCase()}`;
|
|
iconName = iconMap[leg.mode] || iconMap.WALK;
|
|
} else if (legType === LEGTYPE.WAIT) {
|
|
iconName = iconMap.WAIT;
|
|
} else if (legType === LEGTYPE.WAIT_IN_VEHICLE) {
|
|
iconName = iconMap.WAIT_IN_VEHICLE;
|
|
}
|
|
|
|
const maxHeight = cardExpanded
|
|
? `${contentRef.current?.scrollHeight}px`
|
|
: '0px';
|
|
|
|
return (
|
|
<button
|
|
type="button"
|
|
className={`navi-top-card ${cardAnimation}`}
|
|
onClick={handleClick}
|
|
aria-expanded={cardExpanded}
|
|
aria-controls={`navi-card-content-${leg?.legId}`}
|
|
>
|
|
<div className="main-card">
|
|
<div className="content">
|
|
<Icon img={iconName} className="mode" color={iconColor} omitViewBox />
|
|
<div className={`instructions ${cardExpanded ? 'expanded' : ''}`}>
|
|
<NaviInstructions
|
|
leg={leg}
|
|
nextLeg={nextLeg}
|
|
instructions={instructions}
|
|
legType={legType}
|
|
time={time}
|
|
position={position}
|
|
tailLength={tailLength}
|
|
/>
|
|
</div>
|
|
<div type="button" className="navi-top-card-arrow">
|
|
<Icon
|
|
img="icon_arrow-collapse"
|
|
className={`cursor-pointer ${cardExpanded ? 'inverted' : ''}`}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div
|
|
id={`navi-card-content-${leg?.legId}`}
|
|
className="extension"
|
|
style={{
|
|
maxHeight,
|
|
}}
|
|
ref={contentRef}
|
|
aria-hidden={!cardExpanded}
|
|
>
|
|
<NaviCardExtension
|
|
legType={legType}
|
|
leg={leg}
|
|
nextLeg={nextLeg}
|
|
time={time}
|
|
platformUpdated={platformUpdated}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
);
|
|
}
|
|
|
|
NaviCard.propTypes = {
|
|
leg: legShape,
|
|
nextLeg: legShape,
|
|
legType: PropTypes.string.isRequired,
|
|
time: PropTypes.number.isRequired,
|
|
position: PropTypes.shape({
|
|
lat: PropTypes.number,
|
|
lon: PropTypes.number,
|
|
}),
|
|
tailLength: PropTypes.number.isRequired,
|
|
cardAnimation: PropTypes.string.isRequired,
|
|
platformUpdated: PropTypes.bool,
|
|
};
|
|
NaviCard.defaultProps = {
|
|
leg: undefined,
|
|
nextLeg: undefined,
|
|
position: undefined,
|
|
platformUpdated: false,
|
|
};
|
|
|
|
NaviCard.contextTypes = {
|
|
config: configShape.isRequired,
|
|
};
|