Skip to content

Commit

Permalink
feat: Add tooltip that says "Click to start detour" (#2366)
Browse files Browse the repository at this point in the history
* feat: Add tooltip that says "Click to start detour"

* fix: Use fireEvent instead of userEvent in diversionPage tests to fix a known bug in userEvent

* refactor: Extract <MapTooltip /> out as its own component

* feat(storybook): Add storybook story for <MapTooltip />
  • Loading branch information
joshlarson authored Jan 30, 2024
1 parent 2e6c52a commit b65aee6
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 22 deletions.
1 change: 1 addition & 0 deletions assets/css/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ $z-properties-panel-context: (
@import "loading_spinner";
@import "location_card";
@import "map_page";
@import "map/tooltip";
@import "map/controls/layers_control";
@import "map/controls/recenter_control";
@import "map/controls/street_view_switch";
Expand Down
14 changes: 14 additions & 0 deletions assets/css/map/_tooltip.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.c-map-tooltip::before {
border-top-color: black;
}

.c-map-tooltip {
background-color: black;
border-color: black;
color: white;
opacity: 100% !important;
font-size: 14px;
padding: 4px 8px 4px 8px;
font-family: var(--bs-body-font-family);
border-radius: var(--bs-border-radius);
}
5 changes: 4 additions & 1 deletion assets/src/components/detours/detourMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
latLngLiteralToShapePoint,
shapePointToLatLngLiteral,
} from "../../util/pointLiterals"
import { MapTooltip } from "../map/tooltip"

interface DetourMapProps {
/**
Expand Down Expand Up @@ -122,7 +123,9 @@ export const DetourMap = ({
position && onClickOriginalShape(latLngLiteralToShapePoint(position))
},
}}
/>
>
{!startPoint && <MapTooltip>Click to start detour</MapTooltip>}
</Polyline>
</Map>
)

Expand Down
20 changes: 20 additions & 0 deletions assets/src/components/map/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React, { PropsWithChildren } from "react"
import { Tooltip } from "react-leaflet"

interface MapTooltipProps extends PropsWithChildren {
permanent?: boolean
}

export const MapTooltip = ({ children, permanent }: MapTooltipProps) => (
<Tooltip
/* key is present here to force React to re-render the <MapTooltip /> if the value of permanent changes */
key={`tooltip-permanent-${permanent}`}
className="c-map-tooltip"
direction="top"
offset={[0, -15]}
sticky
permanent={permanent}
>
{children}
</Tooltip>
)
41 changes: 41 additions & 0 deletions assets/stories/skate-components/map/tooltip.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from "react"
import { MapTooltip } from "../../../src/components/map/tooltip"
import type { Meta, StoryObj } from "@storybook/react"
import { inMapDecorator } from "../../../.storybook/inMapDecorator"
import { Polyline } from "react-leaflet"

const meta = {
component: MapTooltip,
args: {
children: "Tooltip Title",
permanent: true,
},
argTypes: {
permanent: { table: { disable: true } },
},
render: ({ children, permanent }) => (
<Polyline
className="c-detour_map--original-route-shape"
positions={[
{ lat: 42.36, lng: -71.03 },
{ lat: 42.36, lng: -71.09 },
]}
>
<MapTooltip permanent={permanent}>{children}</MapTooltip>
</Polyline>
),
decorators: [inMapDecorator],
parameters: { layout: "fullscreen", stretch: true },
} satisfies Meta<typeof MapTooltip>

export default meta

type Story = StoryObj<typeof meta>

export const Visible: Story = {}

export const OnlyVisibleOnHover: Story = {
args: {
permanent: false,
},
}
9 changes: 4 additions & 5 deletions assets/tests/components/detours/detourMap.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { jest, describe, test, expect, beforeEach } from "@jest/globals"
import { render, screen } from "@testing-library/react"
import { fireEvent, render, screen } from "@testing-library/react"
import React, { ComponentProps } from "react"
import { DetourMap } from "../../../src/components/detours/detourMap"
import userEvent from "@testing-library/user-event"
import "@testing-library/jest-dom/jest-globals"
import { defaultCenter } from "../../../src/components/map"

Expand Down Expand Up @@ -38,7 +37,7 @@ describe("DetourMap", () => {
/>
)

await userEvent.click(
await fireEvent.click(
container.querySelector(".c-detour_map--original-route-shape")!
)

Expand All @@ -51,7 +50,7 @@ describe("DetourMap", () => {
<DetourMapWithDefaults onClickMap={onClickMap} />
)

await userEvent.click(container.querySelector(".c-vehicle-map")!)
await fireEvent.click(container.querySelector(".c-vehicle-map")!)

expect(onClickMap).toHaveBeenNthCalledWith(1, {
lat: expect.closeTo(defaultCenter.lat),
Expand All @@ -63,7 +62,7 @@ describe("DetourMap", () => {
const onUndoLastWaypoint = jest.fn()
render(<DetourMapWithDefaults onUndoLastWaypoint={onUndoLastWaypoint} />)

await userEvent.click(
await fireEvent.click(
screen.getByRole("button", { name: "Clear Last Waypoint" })
)

Expand Down
31 changes: 15 additions & 16 deletions assets/tests/components/detours/diversionPage.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { jest, describe, test, expect, beforeEach } from "@jest/globals"
import { render, screen } from "@testing-library/react"
import { fireEvent, render, screen } from "@testing-library/react"
import React, { ComponentProps } from "react"
import userEvent from "@testing-library/user-event"
import "@testing-library/jest-dom/jest-globals"
import { fetchDetourDirections } from "../../../src/api"
import { DiversionPage as DiversionPageDefault } from "../../../src/components/detours/diversionPage"
Expand Down Expand Up @@ -34,7 +33,7 @@ describe("DetourMap", () => {
test("can click on route shape to start detour", async () => {
const { container } = render(<DiversionPage />)

await userEvent.click(
await fireEvent.click(
container.querySelector(".c-detour_map--original-route-shape")!
)

Expand All @@ -45,11 +44,11 @@ describe("DetourMap", () => {
test("can click on route shape again to end detour", async () => {
const { container } = render(<DiversionPage />)

await userEvent.click(
await fireEvent.click(
container.querySelector(".c-detour_map--original-route-shape")!
)

await userEvent.click(
await fireEvent.click(
container.querySelector(".c-detour_map--original-route-shape")!
)

Expand All @@ -59,11 +58,11 @@ describe("DetourMap", () => {
test("clicking on map while drawing a detour adds a point", async () => {
const { container } = render(<DiversionPage />)

await userEvent.click(
await fireEvent.click(
container.querySelector(".c-detour_map--original-route-shape")!
)

await userEvent.click(container.querySelector(".c-vehicle-map")!)
await fireEvent.click(container.querySelector(".c-vehicle-map")!)

expect(
container.querySelectorAll(".c-detour_map-circle-marker--detour-point")
Expand All @@ -73,13 +72,13 @@ describe("DetourMap", () => {
test("detour points are correctly rendered when detour is complete", async () => {
const { container } = render(<DiversionPage />)

await userEvent.click(
await fireEvent.click(
container.querySelector(".c-detour_map--original-route-shape")!
)

await userEvent.click(container.querySelector(".c-vehicle-map")!)
await fireEvent.click(container.querySelector(".c-vehicle-map")!)

await userEvent.click(
await fireEvent.click(
container.querySelector(".c-detour_map--original-route-shape")!
)

Expand All @@ -91,13 +90,13 @@ describe("DetourMap", () => {
test("clicking on 'Clear Last Waypoint' removes last point from detour", async () => {
const { container } = render(<DiversionPage />)

await userEvent.click(
await fireEvent.click(
container.querySelector(".c-detour_map--original-route-shape")!
)

await userEvent.click(container.querySelector(".c-vehicle-map")!)
await fireEvent.click(container.querySelector(".c-vehicle-map")!)

await userEvent.click(
await fireEvent.click(
screen.getByRole("button", { name: "Clear Last Waypoint" })
)

Expand All @@ -117,7 +116,7 @@ describe("DetourMap", () => {
test("'Clear Last Waypoint' is disabled when detour drawing has started but no waypoints are present", async () => {
const { container } = render(<DiversionPage />)

await userEvent.click(
await fireEvent.click(
container.querySelector(".c-detour_map--original-route-shape")!
)

Expand All @@ -129,11 +128,11 @@ describe("DetourMap", () => {
test("'Clear Last Waypoint' is disabled when detour drawing has finished", async () => {
const { container } = render(<DiversionPage />)

await userEvent.click(
await fireEvent.click(
container.querySelector(".c-detour_map--original-route-shape")!
)

await userEvent.click(
await fireEvent.click(
container.querySelector(".c-detour_map--original-route-shape")!
)

Expand Down

0 comments on commit b65aee6

Please sign in to comment.