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

Pc/feat/nav bar update #881

Merged
merged 19 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"singleQuote": true,
"printWidth": 100,
"plugins": ["prettier-plugin-tailwindcss"]
}
7 changes: 0 additions & 7 deletions .prettierrc.js

This file was deleted.

15 changes: 8 additions & 7 deletions common/components/buttons/DonateButton.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React, { useState } from 'react';
import { faHeart } from '@fortawesome/free-regular-svg-icons';
import { faHeart as faHeartSolid } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Link from 'next/link';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faHeart as faHeartSolid } from '@fortawesome/free-solid-svg-icons';

export const DonateButton: React.FC = () => {
const [hovered, setHovered] = useState<boolean>(false);
Expand All @@ -12,11 +11,13 @@ export const DonateButton: React.FC = () => {
href="https://transitmatters.org/donate"
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
className="flex w-full cursor-pointer justify-center gap-x-2 rounded-md bg-tm-red p-2 ring-white focus:outline-none focus:ring-1 md:justify-start"
className="rounded-mdring-white group flex w-full cursor-pointer justify-start gap-x-2 rounded-md bg-tm-red hover:bg-white focus:outline-none focus:ring-1 md:justify-start"
>
<div className="relative flex flex-row items-center text-base text-stone-100 md:pl-1">
<FontAwesomeIcon icon={hovered ? faHeartSolid : faHeart} className="pr-2" size="lg" />
<p>Donate</p>
<div className="relative flex flex-row items-center gap-2 pl-1 text-sm text-stone-100">
<div className="group flex h-8 w-8 items-center justify-center rounded-full ">
<FontAwesomeIcon icon={faHeartSolid} size="lg" className="group-hover:text-tm-red" />
</div>
<p className="group-hover:text-tm-red">Make a donation</p>
</div>
</Link>
</>
Expand Down
26 changes: 26 additions & 0 deletions common/components/nav/BusDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import { SidebarTabs } from '../../../modules/navigation/SidebarTabs';
import { TRIP_PAGES, BUS_OVERVIEW } from '../../constants/pages';
import { BusRouteSelection } from './BusRouteSelection';

interface BusDropdownProps {
close?: () => void;
}

export const BusDropdown: React.FC<BusDropdownProps> = ({ close }) => {
return (
<div className="rounded-b-md">
<BusRouteSelection />
<div
className={
'flex flex-col gap-[2px] rounded-b-md border border-t-0 border-mbta-bus border-opacity-50 bg-neutral-800 px-1 py-[4px]'
}
role={'navigation'}
>
<SidebarTabs tabs={BUS_OVERVIEW} close={close} />
<hr className="h-[1px] w-3/4 self-center border-neutral-500" />
<SidebarTabs tabs={TRIP_PAGES} close={close} />
</div>
</div>
);
};
70 changes: 70 additions & 0 deletions common/components/nav/BusRouteSelection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { faCheckCircle } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Listbox, Transition } from '@headlessui/react';
import { ChevronUpDownIcon } from '@heroicons/react/20/solid';
import { useRouter } from 'next/navigation';
import React, { Fragment } from 'react';
import { getBusRoutes } from '../../constants/stations';
import { getBusRouteSelectionItemHref, useDelimitatedRoute } from '../../utils/router';
export const BusRouteSelection: React.FC = () => {
const route = useDelimitatedRoute();
const router = useRouter();
const busRoutes = getBusRoutes();
const selected = route.query.busRoute;
return (
<div className="bg-mbta-lightBus">
<Listbox
value={selected}
onChange={(key) => router.push(getBusRouteSelectionItemHref(key, route))}
>
<div className="relative text-white text-opacity-95">
<Listbox.Button className="relative w-full cursor-pointer border border-mbta-bus bg-tm-lightGrey py-2 pl-3 pr-10 text-left focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white/75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm">
<span className="block truncate ">{selected}</span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronUpDownIcon className="h-5 w-5 " aria-hidden="true" />
</span>
</Listbox.Button>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black/5 focus:outline-none sm:text-sm">
{busRoutes.map((busRoute, personIdx) => (
<Listbox.Option
key={personIdx}
className={({ active }) =>
`relative cursor-pointer select-none py-2 pl-10 pr-4 ${
active ? 'bg-amber-100 text-amber-900' : 'text-gray-900'
}`
}
value={busRoute}
>
{({ selected }) => (
<>
<span
className={`block truncate ${selected ? 'font-medium' : 'font-normal'}`}
>
{busRoute}
</span>
{selected ? (
<span className="absolute inset-y-0 left-0 flex items-center pl-3 text-mbta-bus">
<FontAwesomeIcon
icon={faCheckCircle}
className="h-5 w-5"
aria-hidden="true"
/>
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</Listbox>
</div>
);
};
19 changes: 19 additions & 0 deletions common/components/nav/BusSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { useDelimitatedRoute } from '../../utils/router';
import { BusDropdown } from './BusDropdown';
import { MenuDropdown } from './MenuDropdown';

interface BusSectionProps {
close?: () => void;
}

export const BusSection: React.FC<BusSectionProps> = ({ close }) => {
const route = useDelimitatedRoute();
return (
<div className="w-full gap-y-2">
<MenuDropdown line="line-bus" route={route}>
<BusDropdown close={close} />
</MenuDropdown>
</div>
);
};
60 changes: 60 additions & 0 deletions common/components/nav/MenuDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { faTrainSubway, faTrainTram } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import classNames from 'classnames';
import Link from 'next/link';
import React, { useEffect, useState } from 'react';
import { LINE_OBJECTS } from '../../constants/lines';
import { BUS_DEFAULTS } from '../../state/defaults/dateDefaults';
import { lineColorBackground } from '../../styles/general';
import type { Line } from '../../types/lines';
import type { Route } from '../../types/router';
import { getLineSelectionItemHref } from '../../utils/router';

interface MenuDropdownProps {
line: Line;
route: Route;
children: React.ReactNode;
}

export const MenuDropdown: React.FC<MenuDropdownProps> = ({ line, route, children }) => {
const selected = line === route.line;
const [show, setShow] = useState<boolean>(false);

// Need a timeout so that the selected and previously selected dropdowns do not render as opened simultaneously.
useEffect(() => {
setTimeout(() => setShow(true), 0);
}, [selected]);
return (
<div className={classNames('w-full')}>
<Link
href={
line === 'line-bus'
? `/bus/trips/single?busRoute=1&date=${BUS_DEFAULTS.singleTripConfig.date}`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have some helper fns to generate these URLs

: getLineSelectionItemHref(line, route)
}
>
<div
className={classNames(
'flex w-full flex-row items-center gap-2 rounded-t-md py-1 pl-1 text-sm ',
`${lineColorBackground[line ?? 'DEFAULT']}`,
selected
? `bg-opacity-100 text-white text-opacity-95`
: `bg-opacity-0 hover:rounded-md hover:bg-opacity-30`
)}
>
<div
className={classNames(
lineColorBackground[line ?? 'DEFAULT'],
'flex h-8 w-8 items-center justify-center rounded-full bg-opacity-75'
)}
>
{/* TODO: add bus icon */}
<FontAwesomeIcon icon={line === 'line-green' ? faTrainTram : faTrainSubway} size="lg" />
</div>
{LINE_OBJECTS[line].name}
</div>
</Link>
{selected && show && children}
</div>
);
};
10 changes: 10 additions & 0 deletions common/components/nav/NavSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';

interface NavSectionProps {
title: string;
content: React.ReactNode;
}

export const NavSection: React.FC<NavSectionProps> = ({ title, content }) => {
return <div>{content}</div>;
};
8 changes: 8 additions & 0 deletions common/components/nav/NavSectionHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react';
interface NavSectionHeaderProps {
title: string;
}

export const NavSectionHeader: React.FC<NavSectionHeaderProps> = ({ title }) => {
return <h3 className="text-xs italic text-stone-300">{title}</h3>;
};
29 changes: 29 additions & 0 deletions common/components/nav/SubwayDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import classNames from 'classnames';
import React from 'react';
import { SidebarTabs } from '../../../modules/navigation/SidebarTabs';
import { OVERVIEW_PAGE, LINE_PAGES, TRIP_PAGES } from '../../constants/pages';
import { lineColorBorder } from '../../styles/general';
import type { Line } from '../../types/lines';

interface SubwayDropdownProps {
line: Line;
close?: () => void;
}

export const SubwayDropdown: React.FC<SubwayDropdownProps> = ({ line, close }) => {
return (
<div
className={classNames(
'flex flex-col gap-[2px] rounded-b-md border border-opacity-50 bg-neutral-800 px-1 py-[4px]',
lineColorBorder[line ?? 'DEFAULT']
)}
role={'navigation'}
>
<SidebarTabs tabs={OVERVIEW_PAGE} close={close} />
<hr className="h-[1px] w-3/4 self-center border-neutral-500" />
<SidebarTabs tabs={LINE_PAGES} close={close} />
<hr className="h-[1px] w-3/4 self-center border-neutral-500" />
<SidebarTabs tabs={TRIP_PAGES} close={close} />
</div>
);
};
29 changes: 29 additions & 0 deletions common/components/nav/SubwaySection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { useDelimitatedRoute } from '../../utils/router';
import { MenuDropdown } from './MenuDropdown';
import { SubwayDropdown } from './SubwayDropdown';

interface SubwaySectionProps {
close?: () => void;
}

export const SubwaySection: React.FC<SubwaySectionProps> = ({ close }) => {
const route = useDelimitatedRoute();

return (
<div className="flex w-full flex-col gap-y-1">
<MenuDropdown line="line-red" route={route}>
<SubwayDropdown line="line-red" close={close} />
</MenuDropdown>
<MenuDropdown line="line-orange" route={route}>
<SubwayDropdown line="line-orange" close={close} />
</MenuDropdown>
<MenuDropdown line="line-blue" route={route}>
<SubwayDropdown line="line-blue" close={close} />
</MenuDropdown>
<MenuDropdown line="line-green" route={route}>
<SubwayDropdown line="line-green" close={close} />
</MenuDropdown>
</div>
);
};
9 changes: 2 additions & 7 deletions common/constants/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export type PageMetadata = {
icon: IconDefinition;
hasStationStore?: boolean;
dateStoreSection: DateStoreSection;
sub?: boolean;
title?: string;
};

Expand Down Expand Up @@ -105,7 +104,6 @@ export const ALL_PAGES: PageMap = {
lines: ['line-red', 'line-orange', 'line-blue', 'line-green'],
icon: faGaugeHigh,
dateStoreSection: 'line',
sub: true,
},
predictions: {
key: 'predictions',
Expand All @@ -114,7 +112,6 @@ export const ALL_PAGES: PageMap = {
lines: ['line-red', 'line-orange', 'line-blue', 'line-green'],
icon: faStopwatch20,
dateStoreSection: 'line',
sub: true,
},
service: {
key: 'service',
Expand All @@ -123,7 +120,6 @@ export const ALL_PAGES: PageMap = {
lines: ['line-red', 'line-orange', 'line-blue', 'line-green'],
dateStoreSection: 'line',
icon: faClockFour,
sub: true,
},
slowzones: {
key: 'slowzones',
Expand All @@ -132,7 +128,6 @@ export const ALL_PAGES: PageMap = {
lines: ['line-red', 'line-blue', 'line-orange'],
icon: faWarning,
dateStoreSection: 'line',
sub: true,
},
systemSlowzones: {
key: 'systemSlowzones',
Expand All @@ -149,7 +144,6 @@ export const ALL_PAGES: PageMap = {
lines: ['line-red', 'line-blue', 'line-green', 'line-orange', 'line-bus'],
icon: faUsers,
dateStoreSection: 'line',
sub: true,
},
};

Expand All @@ -160,8 +154,9 @@ export const TODAY = [ALL_PAGES.today];

export const BUS_OVERVIEW = [ALL_PAGES.ridership];

export const OVERVIEW_PAGE = [ALL_PAGES.overview];

export const LINE_PAGES = [
ALL_PAGES.overview,
ALL_PAGES.service,
ALL_PAGES.slowzones,
ALL_PAGES.speed,
Expand Down
2 changes: 1 addition & 1 deletion common/layouts/PrimaryLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const queryClient = new QueryClient({
export const Layout: React.FC<LayoutProps> = ({ children }) => {
return (
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools position="top-left" />
<ReactQueryDevtools position="bottom-right" />
<div className="flex h-screen flex-col">
<main className="relative h-full">{children}</main>
</div>
Expand Down
6 changes: 3 additions & 3 deletions copy/landingCopy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const ServiceBaseline = <p className={BASELINE_STYLE}>Compared to histori

export const RidershipBaseline = <p className={BASELINE_STYLE}>Compared to historical maximums</p>;

export const SpeedDescription = (
const SpeedDescription = (
<p className={DESCRIPTION_STYLE}>
How quickly can riders move through Boston?
<br />
Expand All @@ -22,7 +22,7 @@ export const SpeedDescription = (
</p>
);

export const ServiceDescription = (
const ServiceDescription = (
<p className={DESCRIPTION_STYLE}>
How long must riders wait for trains and buses?
<span className="text-sm text-stone-800">
Expand All @@ -33,7 +33,7 @@ export const ServiceDescription = (
</p>
);

export const RidershipDescription = (
const RidershipDescription = (
<p className={DESCRIPTION_STYLE}>
How many riders are using the system?
<br />
Expand Down
Loading
Loading