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

Full-screen panels on small screens #2289

Merged
merged 12 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from 9 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
4 changes: 2 additions & 2 deletions assets/css/_ladder_page.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ $color-route-tabs-separator: #9fa2ac;
padding-left: $route-picker-width;
}

@media screen and (max-width: $mobile-max-width) {
@media screen and (max-width: map-get($old-breakpoints, "mobile-max-width")) {
.c-ladder-page--picker-container-visible {
padding-left: $mobile-route-picker-width;
}
}

@media screen and (max-width: $mobile-max-width) {
@media screen and (max-width: map-get($old-breakpoints, "mobile-max-width")) {
.c-ladder-page--picker-container-visible {
.c-ladder-page__tab-bar-and-ladders {
@include blur;
Expand Down
4 changes: 2 additions & 2 deletions assets/css/_late_view.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ $late-view-background-color: $color-bg-light;
top: 0;
z-index: map-get($z-page-layout-context, "view");

@media screen and (max-width: 700px) {
width: 100%;
@media screen and (max-width: map-get($breakpoints, "max-mobile-landscape-tablet-portrait-width")) {
width: 100vw;
firestack marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
4 changes: 2 additions & 2 deletions assets/css/_map_page.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ $z-map-page-context: (
z-index: map-get($z-map-page-context, "map");

.c-map-page__input-and-results--visible ~ & {
@media screen and (max-width: $mobile-portrait-max-width) {
@media screen and (max-width: map-get($old-breakpoints, "mobile-portrait-max-width")) {
filter: blur(3.25px);
}
}
Expand Down Expand Up @@ -102,7 +102,7 @@ $z-map-page-context: (
display: none;

.c-map-page__input-and-results--visible ~ & {
@media screen and (max-width: $mobile-portrait-max-width) {
@media screen and (max-width: map-get($old-breakpoints, "mobile-portrait-max-width")) {
// Make button clickable
display: block;
// Force Flex + Posistion to fill area
Expand Down
6 changes: 3 additions & 3 deletions assets/css/_notification_drawer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
width: 23.5rem;
z-index: map-get($z-page-layout-context, "view");

@media screen and (max-width: $mobile-max-width) {
width: 100%;
@media screen and (max-width: map-get($breakpoints, "max-mobile-landscape-tablet-portrait-width")) {
width: 100vw;
}
@media screen and (max-width: $mobile-portrait-max-width) {
@media screen and (max-width: map-get($breakpoints, "max-mobile-width")) {
position: fixed;
bottom: 0;
}
Expand Down
2 changes: 1 addition & 1 deletion assets/css/_picker_container.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
display: none;
}

@media screen and (max-width: $mobile-max-width) {
@media screen and (max-width: map-get($old-breakpoints, "mobile-max-width")) {
.c-picker-container {
--picker-container-width: min(
#{$mobile-route-picker-width},
Expand Down
8 changes: 2 additions & 6 deletions assets/css/_properties_panel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@
width: 23.5rem;
z-index: map-get($z-page-layout-context, "properties-panel");

@media screen and (max-width: $mobile-max-width) {
@media screen and (max-width: map-get($breakpoints, "max-mobile-landscape-tablet-portrait-width")) {
width: 100vw;

.l-nav__app-content & {
width: 100%;
}
}
@media screen and (max-width: $mobile-portrait-max-width) {
@media screen and (max-width: map-get($breakpoints, "max-mobile-width")) {
position: fixed;
bottom: 0;
}
Expand Down
2 changes: 1 addition & 1 deletion assets/css/_search_page.scss
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ $z-search-page-context: (
padding: 0.625rem 1rem 0 1rem;
}

@media screen and (max-width: $mobile-max-width) {
@media screen and (max-width: map-get($old-breakpoints, "mobile-max-width")) {
.c-search-page {
flex-direction: column;
}
Expand Down
6 changes: 6 additions & 0 deletions assets/css/_skate_ui.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
$breakpoints: (
"max-mobile-width": 480px,
"max-mobile-landscape-tablet-portrait-width": 800px,
"max-tablet-width": 1340px,
);

// #region Text Styles [v2]

// https://www.notion.so/mbta-downtown-crossing/2022-12-19-Type-Styles-6f6c90eb449248b7a954e234b718137f
Expand Down
9 changes: 4 additions & 5 deletions assets/css/_swings_view.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,18 @@
}

// Full width on mobile portrait, to be updated with more responsive designs
@media screen and (max-width: 480px) {
@media screen and (max-width: map-get($breakpoints, "max-mobile-landscape-tablet-portrait-width")) {
.l-nav__app-content & {
width: 100%;
width: 100vw;

.c-swings-view__table {
width: 100%;
}
}
}
@media screen and (max-width: $mobile-portrait-max-width) {
@media screen and (max-width: map-get($breakpoints, "max-mobile-width")) {
position: fixed;
bottom: 0;
width: 100vw;
}
}

Expand Down Expand Up @@ -215,7 +214,7 @@
}
}

@media screen and (max-width: $mobile-max-width) {
@media screen and (max-width: map-get($old-breakpoints, "mobile-max-width")) {
.c-swings-view__header {
padding-left: 1.75rem;
}
Expand Down
2 changes: 1 addition & 1 deletion assets/css/_ui_kit.scss
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ $font-family-route-pill: "Helvetica Neue", Helvetica, Arial, sans-serif;
filter: blur(5px);
}

@media screen and (max-width: $mobile-max-width) {
@media screen and (max-width: map-get($old-breakpoints, "mobile-max-width")) {
.blurred-mobile {
@include blur;
}
Expand Down
7 changes: 4 additions & 3 deletions assets/css/app.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
$non-mobile-min-width: 768px;
$mobile-max-width: $non-mobile-min-width - 1;
$mobile-portrait-max-width: 480px;
$old-breakpoints: (
"mobile-max-width": 767px,
"mobile-portrait-max-width": 480px,
);
$tab-bar-width: 3rem;
$drawer-tab-width: 2rem;
$route-picker-width: 21.875rem;
Expand Down
12 changes: 10 additions & 2 deletions assets/src/components/nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import LeftNav from "./nav/leftNav"
import TopNav from "./nav/topNav"
import MobilePortraitNav from "./nav/mobilePortraitNav"
import { StateDispatchContext } from "../contexts/stateDispatchContext"
import { usePanelStateFromStateDispatchContext } from "../hooks/usePanelState"

interface Props {
children?: React.ReactNode
Expand All @@ -15,19 +16,26 @@ const Nav: React.FC<Props> = ({ children }) => {
const [, dispatch] = useContext(StateDispatchContext)
const deviceType = useScreenSize()

const { isViewOpen } = usePanelStateFromStateDispatchContext()

const navVisibilityStyle = isViewOpen ? "hidden" : "visible"

switch (deviceType) {
case "mobile":
return (
<div className="l-nav--narrow">
<div className="l-nav__app-content">{children}</div>
<MobilePortraitNav />
<MobilePortraitNav isViewOpen={isViewOpen} />
</div>
)
case "mobile_landscape_tablet_portrait":
return (
<div className="l-nav--medium">
<div className="l-nav__app-content">{children}</div>
<div className="l-nav__nav-bar l-nav__nav-bar--left">
<div
className="l-nav__nav-bar l-nav__nav-bar--left"
style={{ visibility: navVisibilityStyle }}
Copy link
Member

Choose a reason for hiding this comment

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

question: just wondering, why visibility here instead of something like the hidden attribute?

Copy link
Member Author

Choose a reason for hiding this comment

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

I was working off of how <MobilePortraitNav/> is implemented, but if you feel like hidden would be more appropriate I could change it.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, I feel like I'd need to know why that was chosen in <MobilePortraitNav/> originally. Using hidden instead of visibility would change the way it works(visibility: visible keeps the element taking up layout space, where hidden does display: none), and I'm not sure if there are assumptions else where that require that. But I would prefer hidden in both cases if there are no issues.

Copy link
Member

Choose a reason for hiding this comment

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

It seems like using `hidden`` would work? #1719 (comment)

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll play around with it a bit and see if there are any drawbacks to hidden.

Copy link
Member Author

Choose a reason for hiding this comment

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

Okay I don't see any drawbacks to hidden. Is it okay if I use hidden here but leave <MobilePortraitNav/> be for now?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah that's fine 👍🏻

>
<LeftNav
toggleMobileMenu={() => dispatch(toggleMobileMenu())}
defaultToCollapsed={true}
Expand Down
16 changes: 7 additions & 9 deletions assets/src/components/nav/mobilePortraitNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,18 @@ import { StateDispatchContext } from "../../contexts/stateDispatchContext"
import { toggleMobileMenu } from "../../state"
import BottomNavMobile from "./bottomNavMobile"
import TopNavMobile from "./topNavMobile"
import { OpenView } from "../../state/pagePanelState"
import { usePanelStateFromStateDispatchContext } from "../../hooks/usePanelState"

const MobilePortraitNav = (): JSX.Element => {
const MobilePortraitNav = ({
isViewOpen,
}: {
isViewOpen: boolean
}): JSX.Element => {
const [state, dispatch] = useContext(StateDispatchContext)

const { mobileMenuIsOpen, routeTabs } = state
const {
currentView: { openView, selectedVehicleOrGhost },
openNotificationDrawer,
openSwingsView,
} = usePanelStateFromStateDispatchContext()

const isViewOpen = openView !== OpenView.None || selectedVehicleOrGhost
const { openNotificationDrawer, openSwingsView } =
usePanelStateFromStateDispatchContext()

const navVisibilityStyle = isViewOpen ? "hidden" : "visible"

Expand Down
5 changes: 4 additions & 1 deletion assets/src/components/viewHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@ const ViewHeader: ViewHeaderType = ({
}): JSX.Element => {
const deviceType = useScreenSize()

const screenSizeAllowsBackButton =
deviceType === "mobile" || deviceType === "mobile_landscape_tablet_portrait"

return (
<div className="c-view-header">
{backlinkToView &&
backlinkToView !== OpenView.None &&
deviceType === "mobile" ? (
screenSizeAllowsBackButton ? (
<button
className="c-view-header__backlink"
onClick={followBacklink}
Expand Down
8 changes: 7 additions & 1 deletion assets/src/hooks/usePanelState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { TabMode } from "../components/propertiesPanel/tabPanels"
import { StateDispatchContext } from "../contexts/stateDispatchContext"
import { Dispatch } from "../state"
import {
OpenView,
PagePath,
VehicleType,
ViewState,
Expand Down Expand Up @@ -37,8 +38,9 @@ export const usePanelStateForViewState = (
view: ViewState,
dispatch: Dispatch
) => {
const currentView = view.state[view.currentPath]
return {
currentView: view.state[view.currentPath],
currentView,
setPath: (path: PagePath) => {
if (path !== view.currentPath) {
dispatch(setPath(path))
Expand All @@ -52,5 +54,9 @@ export const usePanelStateForViewState = (
openNotificationDrawer: () => dispatch(openNotificaitonDrawer()),
closeView: () => dispatch(closeView()),
openPreviousView: () => dispatch(openPreviousView()),
isViewOpen:
currentView.openView !== OpenView.None ||
(currentView.selectedVehicleOrGhost && true) ||
false,
}
}
33 changes: 27 additions & 6 deletions assets/tests/components/nav.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Nav from "../../src/components/nav"
import useScreenSize from "../../src/hooks/useScreenSize"
import getTestGroups from "../../src/userTestGroups"
import { TestGroups } from "../../src/userInTestGroup"
import { mockUsePanelState } from "../testHelpers/usePanelStateMocks"

jest.mock("../../src/hooks/useScreenSize", () => ({
__esModule: true,
Expand All @@ -19,13 +20,16 @@ jest.mock("userTestGroups", () => ({
default: jest.fn(() => []),
}))

jest.mock("../../src/hooks/usePanelState")

beforeEach(() => {
mockUsePanelState({ isViewOpen: false })
;(getTestGroups as jest.Mock).mockReturnValue([])
})

describe("Nav", () => {
test("renders mobile nav content", () => {
;(useScreenSize as jest.Mock).mockImplementationOnce(() => "mobile")
jest.mocked(useScreenSize).mockReturnValueOnce("mobile")

const result = render(
<BrowserRouter>
Expand All @@ -38,9 +42,9 @@ describe("Nav", () => {
})

test("renders mobile landscape / tablet portrait nav content", () => {
;(useScreenSize as jest.Mock).mockImplementationOnce(
() => "mobile_landscape_tablet_portrait"
)
jest
.mocked(useScreenSize)
.mockReturnValueOnce("mobile_landscape_tablet_portrait")

const result = render(
<BrowserRouter>
Expand All @@ -52,8 +56,23 @@ describe("Nav", () => {
expect(result.queryByText("Route Ladders")).toBeNull()
})

test("renders mobile landscape / tablet portrait nav content with nav elements hidden when a view is open", () => {
mockUsePanelState({ isViewOpen: true })
jest
.mocked(useScreenSize)
.mockReturnValueOnce("mobile_landscape_tablet_portrait")

const result = render(
<BrowserRouter>
<Nav>Hello, world!</Nav>
</BrowserRouter>
)

expect(result.getByTitle("Route Ladders")).not.toBeVisible()
})

test("renders tablet nav content", () => {
;(useScreenSize as jest.Mock).mockImplementationOnce(() => "tablet")
jest.mocked(useScreenSize).mockReturnValueOnce("tablet")

const result = render(
<BrowserRouter>
Expand All @@ -66,7 +85,7 @@ describe("Nav", () => {
})

test("renders nav item with title 'Search Map' if in map test group", () => {
;(getTestGroups as jest.Mock).mockReturnValue([TestGroups.MapBeta])
jest.mocked(getTestGroups).mockReturnValue([TestGroups.MapBeta])

render(
<BrowserRouter>
Expand All @@ -79,6 +98,8 @@ describe("Nav", () => {
})

test("renders desktop nav content", () => {
jest.mocked(useScreenSize).mockReturnValueOnce("desktop")

const result = render(
<BrowserRouter>
<Nav>Hello, world!</Nav>
Expand Down
Loading
Loading