Skip to content

Commit

Permalink
Highlight current Viewport in ViewportMenu Component. (#386)
Browse files Browse the repository at this point in the history
This PR makes sure the currently applied Viewport is highlighted in the
`ViewportMenu` drop-down. Previously, there was no highlighting. So,
people could not remember what Viewport they'd applied. Note that we do
not highlight the "Reset Viewport" option. I also added a visual
regression test to ensure the correct highlighting behavior.

J=SLAP-2946
TEST=auto, manual
  • Loading branch information
tmeyer2115 authored Sep 26, 2023
1 parent 66cd396 commit ef54a4e
Show file tree
Hide file tree
Showing 10 changed files with 49 additions and 6 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions e2e-tests/tests/infra/StudioPlaywrightPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,18 @@ export default class StudioPlaywrightPage {
return path.join(this.tmpDir, "src/components", componentName + ".tsx");
}

async openViewportMenu() {
await this.page
.getByRole("button", { name: "See Available Viewports" })
.click();
}

async setViewport(viewportName: string) {
await this.page
.getByRole("button", { name: `Select ${viewportName} Viewport` })
.click();
}

async takePageScreenshotAfterImgRender() {
await this.waitForIFrameImagesToLoad();
await expect(this.page).toHaveScreenshot();
Expand Down
13 changes: 13 additions & 0 deletions e2e-tests/tests/viewport-menu.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { studioTest } from "./infra/studioTest.js";

studioTest("can set and reset Viewport", async ({ studioPage }) => {
await studioPage.switchPage("LocationPage");
await studioPage.openViewportMenu();
await studioPage.takePageScreenshotAfterImgRender();
await studioPage.setViewport("Galaxy Z Flip5 Folded");
await studioPage.openViewportMenu();
await studioPage.takePageScreenshotAfterImgRender();
await studioPage.setViewport("Reset Viewport");
await studioPage.openViewportMenu();
await studioPage.takePageScreenshotAfterImgRender();
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function ViewportButton(): JSX.Element {

return (
<div ref={containerRef}>
<button onClick={handleClick}>
<button onClick={handleClick} aria-label="See Available Viewports">
<Icon />
</button>
{isOpen && <ViewportMenu closeMenu={handleClose} />}
Expand Down
28 changes: 23 additions & 5 deletions packages/studio-ui/src/components/Viewport/ViewportMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useCallback } from "react";
import { VIEWPORTS, Viewport } from "./defaults";
import useStudioStore from "../../store/useStudioStore";
import classNames from "classnames";

export interface ViewportMenuProps {
closeMenu: () => void;
Expand All @@ -9,8 +10,9 @@ export interface ViewportMenuProps {
export default function ViewportMenu({
closeMenu,
}: ViewportMenuProps): JSX.Element {
const [setViewport] = useStudioStore((store) => [
const [setViewport, currentViewport] = useStudioStore((store) => [
store.pagePreview.setViewport,
store.pagePreview.viewport,
]);

const handleSelect = useCallback(
Expand All @@ -23,29 +25,45 @@ export default function ViewportMenu({

return (
<div className="absolute z-20 rounded bg-white text-sm text-gray-700 shadow-lg flex flex-col items-start py-1">
{Object.values(VIEWPORTS).map((val) => {
{Object.values(VIEWPORTS).map((viewport) => {
return (
<Option key={val.name} viewport={val} handleSelect={handleSelect} />
<Option
key={viewport.name}
viewport={viewport}
handleSelect={handleSelect}
isCurrentlySelected={
viewport.name !== VIEWPORTS.resetviewport.name &&
viewport === currentViewport
}
/>
);
})}
</div>
);
}
interface OptionProps {
viewport: Viewport;
isCurrentlySelected: boolean;
handleSelect: (viewport) => void;
}

function Option({ viewport, handleSelect }: OptionProps) {
function Option({ viewport, isCurrentlySelected, handleSelect }: OptionProps) {
const onClick = useCallback(
() => handleSelect(viewport),
[handleSelect, viewport]
);
const { name, styles } = viewport;
const className = classNames(
"flex items-center gap-x-2 px-6 py-2 cursor-pointer w-full text-left",
{
"bg-gray-300": isCurrentlySelected,
"hover:bg-gray-100": !isCurrentlySelected,
}
);

return (
<button
className="flex items-center gap-x-2 px-6 py-2 cursor-pointer hover:bg-gray-100 w-full text-left"
className={className}
onClick={onClick}
aria-label={`Select ${name} Viewport`}
>
Expand Down

0 comments on commit ef54a4e

Please sign in to comment.