Skip to content

Commit

Permalink
#6800 Page Editor Walkthrough Modal (#6894)
Browse files Browse the repository at this point in the history
* implement iframe/showModal approach

* add static modal via Modal.Dialog

* add close behavior to modal

* add modal header function close button

* add content for first step in walkthrough

* import pixiebrix bootstrap theme

* add fixed height to modal body

* add carousel indicators'

* trigger the page editor modal from the mod launcher footer link

* refactor walkthroughModalProtocol

* add style to close button & sticky footer

* fix mod launcher footer link

* add inline icons

* add alt text to images

* update snapshots

* fix lint errors

* fix casing on devtools toolbar tab image

* remove commented out height

* rearrange paragraph elements in modal body

* convert some images to webp format

* swap svg/webp with png

* add step telemetry

* add modal close telemetry

* move showWalkthroughModal into own module

* change DeferredPromise type to void

* add sticky header
  • Loading branch information
mnholtz authored Nov 17, 2023
1 parent 3905c58 commit a8c2b82
Show file tree
Hide file tree
Showing 27 changed files with 681 additions and 15 deletions.
8 changes: 8 additions & 0 deletions img/devtools-dock-bottom-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/devtools-docking-context-menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/devtools-pixiebrix-toolbar-hidden.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/devtools-pixiebrix-toolbar-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/devtools-pixiebrix-toolbar-tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions img/devtools-shortcut-mac.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions img/devtools-shortcut-windows.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/inspect-context-menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion src/components/quickBar/defaultActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { faSlack } from "@fortawesome/free-brands-svg-icons";
import { DEFAULT_SERVICE_URL, MARKETPLACE_URL } from "@/urlConstants";
import { Events } from "@/telemetry/events";
import reportEvent from "@/telemetry/reportEvent";
import showWalkthroughModal from "@/components/walkthroughModal/showWalkthroughModal";

const PIXIEBRIX_SECTION = "PixieBrix";

Expand Down Expand Up @@ -101,7 +102,7 @@ export const pageEditorAction: Action = {
reportEvent(Events.PAGE_EDITOR_WALKTHROUGH_LINK_CLICK, {
source: "quick bar",
});
window.location.href = "https://pixiebrix.com/developers-welcome";
void showWalkthroughModal();
},
};

Expand Down
92 changes: 92 additions & 0 deletions src/components/walkthroughModal/WalkthroughModal.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*!
* Copyright (C) 2023 PixieBrix, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@import "@/themes/colors";

.root {
color: $S800;
font-weight: 400;

p,
li {
font-size: 15px;
}

:global(.modal-title) {
color: $S700;
font-size: 24px;
}

:global(.modal-content) {
background-color: $S0;
border-color: $S0;
}

:global(.modal-header) {
border-bottom: none;
}

small {
font-size: 12px;
color: $S600;
}

button:global(.close) {
font-weight: 100;
font-size: 33px;
color: $S4;
padding: 16px 24px;
}
}

.carouselIndicators {
position: inherit;
margin: 0;

li {
width: 8px;
height: 8px;
margin: 4px;
border-radius: 50%;
background-color: $S4;
opacity: 1;

&:global(.active) {
background-color: $primary-bg;
}
}
}

.modalFooter {
position: sticky;
bottom: 0;
background-image: linear-gradient(
to bottom,
rgba(255, 0, 0, 0),
rgb(255, 255, 255) 33%
);
}

.modalHeader {
position: sticky;
top: 0;
z-index: 1;
background-image: linear-gradient(
to top,
rgba(255, 0, 0, 0),
rgb(255, 255, 255) 10%
);
}
248 changes: 248 additions & 0 deletions src/components/walkthroughModal/WalkthroughModalApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/*
* Copyright (C) 2023 PixieBrix, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import styles from "./WalkthroughModal.module.scss";

import { Button, Carousel, Col, Container, Modal, Row } from "react-bootstrap";
import React, { useEffect, useState } from "react";
import { closeWalkthroughModal } from "@/contentScript/messenger/api";
import { type Target } from "@/types/messengerTypes";
import { Events } from "@/telemetry/events";
import inspectContextMenuImage from "@img/inspect-context-menu.png";
import devtoolsShortcutWindowsImage from "@img/devtools-shortcut-windows.svg";
import devtoolsShortcutMacImage from "@img/devtools-shortcut-mac.svg";
import devtoolsDockingContextMenu from "@img/devtools-docking-context-menu.png";
import devtoolsToolbarScreenshot from "@img/devtools-pixiebrix-toolbar-screenshot.png";
import devtoolsPixieBrixToolbarTab from "@img/devtools-pixiebrix-toolbar-tab.png";
import devtoolsPixieBrixToolbarTabHidden from "@img/devtools-pixiebrix-toolbar-hidden.png";
import devtoolsDockBottomIcon from "@img/devtools-dock-bottom-icon.svg";
import cx from "classnames";
import { isMac } from "@/utils/browserUtils";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faEllipsisV } from "@fortawesome/free-solid-svg-icons";
import reportEvent from "@/telemetry/reportEvent";

type WalkthroughModalStep = {
title: string;
body: React.ReactNode;
};

const steps: WalkthroughModalStep[] = [
{
title: "Opening the Chrome DevTools",
body: (
<>
<Row>
<Col>
<img
src={inspectContextMenuImage}
alt="The right-click browser context menu with the 'Inspect' option included"
className="img-fluid"
/>
</Col>
<Col>
{isMac() ? (
<img
src={devtoolsShortcutMacImage}
alt="Keyboard shortcut to open devtools on Mac systems: Command + Option + I"
/>
) : (
<img
src={devtoolsShortcutWindowsImage}
alt="Keyboard shortcut to open devtools on Windows systems: Control + Shift + I"
/>
)}
</Col>
</Row>
<p className="mt-3">
The Page Editor lives in the Chrome DevTools. You can open the
DevTools in two different ways.
</p>
<ul className="mb-0">
<li>Right click anywhere on the page and select “Inspect”</li>
<li>Or, utilize the keyboard shortcut for your system</li>
</ul>
</>
),
},
{
title: "Docking the DevTools",
body: (
<>
<Row>
<Col>
<img
src={devtoolsToolbarScreenshot}
alt="DevTools toolbar with three-dot menu icon included"
className="img-fluid"
/>
</Col>
<Col>
<img
src={devtoolsDockingContextMenu}
alt="The context menu that will show after clicking the DevTools three-dot menu, with 'Dock Side' option included"
className="img-fluid"
/>
</Col>
</Row>
<p className="mt-3">
Dock the DevTools to the bottom of the screen, if necessary. The Page
Editor is a powerful tool that needs a bit of room to work its magic.
</p>
<p className="mb-0">
Click the ‘
<FontAwesomeIcon
icon={faEllipsisV}
className="mx-1"
title="Three-dot menu icon"
/>
’ menu in the top right of the DevTools
<br />
Select the ‘
<img
src={devtoolsDockBottomIcon}
alt="DevTools dock bottom icon"
width="16px"
/>
’ (third option) under ‘Dock side’
</p>
</>
),
},
{
title: "Opening the Page Editor",
body: (
<>
<img
src={devtoolsPixieBrixToolbarTab}
alt="DevTools toolbar with the PixieBrix tab included"
className="mb-3 img-fluid"
/>
<img
src={devtoolsPixieBrixToolbarTabHidden}
alt="DevTools toolbar with the PixieBrix tab included under the chevron icon"
className="img-fluid"
/>
<p className="mt-3 mb-0">
Last step is to select the PixieBrix tab from the tab bar. If you
don’t see the tab, it’s probably behind the double-chevron menu.
</p>
</>
),
},
];

const WalkthroughModalApp: React.FunctionComponent = () => {
const [stepIndex, setStepIndex] = useState(0);
const params = new URLSearchParams(location.search);
const opener = JSON.parse(params.get("opener")) as Target;

useEffect(() => {
reportEvent(Events.PAGE_EDITOR_WALKTHROUGH_MODAL_VIEW, {
stepNumber: stepIndex + 1,
// eslint-disable-next-line security/detect-object-injection -- steps are constants defined in this file
stepTitle: steps[stepIndex].title,
});
}, [stepIndex]);

return (
<Modal
backdrop={false}
animation={false}
show={true}
onHide={() => {
closeWalkthroughModal(opener);
}}
className={styles.root}
>
<Modal.Header className={styles.modalHeader} closeButton>
<Container>
<small>
Step {stepIndex + 1} of {steps.length}
</small>
<Modal.Title>{steps[stepIndex].title}</Modal.Title>
</Container>
</Modal.Header>
<Carousel
activeIndex={stepIndex}
interval={null}
slide={false}
controls={false}
indicators={false}
>
{steps.map((step, index) => (
<Carousel.Item key={index}>
<Modal.Body className="show-grid">
<Container>{step.body}</Container>
</Modal.Body>
</Carousel.Item>
))}
</Carousel>
<Modal.Body className={cx("show-grid", styles.modalFooter)}>
<Row>
<Col>
{stepIndex > 0 && (
<Button
size="sm"
variant="link"
onClick={() => {
if (stepIndex > 0) {
setStepIndex(stepIndex - 1);
}
}}
>
Prev
</Button>
)}
</Col>
<Col>
<ol
className={cx(styles.carouselIndicators, "carousel-indicators")}
>
{steps.map((_, index) => (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions -- Navigation can be done via prev/next buttons
<li
key={index}
className={cx({ active: index === stepIndex })}
onClick={() => {
setStepIndex(index);
}}
/>
))}
</ol>
</Col>
<Col className="d-flex justify-content-end">
<Button
size="sm"
onClick={() => {
if (stepIndex < steps.length - 1) {
setStepIndex(stepIndex + 1);
} else {
closeWalkthroughModal(opener);
}
}}
>
{stepIndex < steps.length - 1 ? "Next" : "Close"}
</Button>
</Col>
</Row>
</Modal.Body>
</Modal>
);
};

export default WalkthroughModalApp;
Loading

0 comments on commit a8c2b82

Please sign in to comment.