Skip to content
Draft
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
4 changes: 3 additions & 1 deletion public/translations/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,10 @@
},
"sidebar": {
"collapse": "Collapse sidebar",
"collapseInstructions": "Collapse project instructions",
"download": "Download project",
"expand": "Expand sidebar",
"expandInstructions": "Open project instructions",
"file": "Project files",
"images": "Image gallery",
"settings": "Settings",
Expand Down Expand Up @@ -355,4 +357,4 @@
"common": {
"or": "or"
}
}
}
2 changes: 2 additions & 0 deletions public/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,10 @@
},
"sidebar": {
"collapse": "Collapse sidebar",
"collapseInstructions": "Collapse project instructions",
"download": "Download project",
"expand": "Expand sidebar",
"expandInstructions": "Open project instructions",
"file": "Project files",
"images": "Image gallery",
"settings": "Settings",
Expand Down
26 changes: 26 additions & 0 deletions src/assets/stylesheets/Project.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,32 @@
overflow: hidden;
}

.project-bar-row {
display: flex;
align-items: stretch;
gap: var(--project-wrapper-grid-gap, #{$space-0-5});

.project-bar {
flex: 1 1 auto;
min-inline-size: 0;
}
}

.project-bar-row__expand {
display: flex;
align-items: center;
flex-shrink: 0;
box-sizing: border-box;
padding: $space-0-5;
border-radius: $space-0-5;
background-color: var(--editor-color-layer-3);
border: 1px solid var(--editor-color-outline);

.rpf-button {
border: none;
}
}

.proj-editor-wrapper {
display: flex;
flex: 0 1 auto;
Expand Down
32 changes: 32 additions & 0 deletions src/assets/stylesheets/Sidebar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,41 @@

.sidebar__panel-heading {
margin: 0;
min-inline-size: 0;
@include font-size-1-5(regular);
}

.sidebar__panel-heading-row {
display: flex;
align-items: center;
gap: var(--space-0-5);

.rpf-button {
border: none;
}
}

.sidebar__panel-collapse {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
flex-shrink: 0;
margin: 0;
border: 1px solid var(--sidebar-border);
border-radius: var(--space-1);
padding: var(--space-1);
color: var(--editor-color-text);

svg {
margin: 0;
}

&:hover {
background-color: var(--sidebar-option-hover);
}
}

.sidebar__panel-header {
display: flex;
flex-direction: column;
Expand Down
21 changes: 15 additions & 6 deletions src/components/Editor/Project/Project.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { showSavedMessage } from "../../../utils/Notifications";
import ProjectBar from "../../ProjectBar/ProjectBar";
import ScratchProjectBar from "../../ProjectBar/ScratchProjectBar";
import Sidebar from "../../Menus/Sidebar/Sidebar";
import SidebarExpandButton from "../../Menus/Sidebar/SidebarExpandButton";
import EditorInput from "../EditorInput/EditorInput";
import ResizableWithHandle from "../../../utils/ResizableWithHandle";
import { useContainerMinWidth } from "../../../hooks/useContainerMinWidth";
Expand Down Expand Up @@ -69,12 +70,20 @@ const Project = (props) => {
/>
)}
<div className="project-wrapper" ref={containerRef}>
{withProjectbar &&
(isCodeEditorScratchProject ? (
<ScratchProjectBar nameEditable={nameEditable} />
) : (
<ProjectBar nameEditable={nameEditable} />
))}
{withProjectbar && (
<div className="project-bar-row">
{withSidebar && (
<SidebarExpandButton
allowMobileView={!isCodeEditorScratchProject}
/>
)}
{isCodeEditorScratchProject ? (
<ScratchProjectBar nameEditable={nameEditable} />
) : (
<ProjectBar nameEditable={nameEditable} />
)}
</div>
)}
{!loading && !isCodeEditorScratchProject && (
<div className="proj-editor-wrapper">
<ResizableWithHandle
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* eslint-disable jsx-a11y/anchor-has-content */
// This is disabled because the empty anchor tag is used for translation and will have content when rendered.

import React, { useRef, useState } from "react";
import { Button } from "@raspberrypifoundation/design-system-react";
import { useRef, useState } from "react";
import { Trans, useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { Tab, TabList, TabPanel, Tabs } from "react-tabs";
import SidebarPanel from "../SidebarPanel";

import BinIcon from "../../../../assets/icons/bin.svg";
import DoubleArrowLeft from "../../../../assets/icons/double_arrow_left.svg";
import PlusIcon from "../../../../assets/icons/plus.svg";
import demoInstructions from "../../../../assets/markdown/demoInstructions.md?raw";
import "../../../../assets/stylesheets/Instructions.scss?inline";
Expand All @@ -17,22 +18,21 @@ import {
} from "../../../../redux/InstructionsSlice";
import {
insertStepAfter,
removeStepAt,
updateStepMarkdown,
REMOVE_ALL_STEPS,
REMOVE_CURRENT_STEP,
removeStepAt,
updateStepMarkdown,
} from "../../../../utils/instructionSteps";
import populateMarkdownTemplate from "../../../../utils/populateMarkdownTemplate";
import { Button } from "@raspberrypifoundation/design-system-react";
import RemoveInstructionStepModal from "../../../Modals/RemoveInstructionStepModal";
import SidebarPanel from "../SidebarPanel";
import InstructionsStep from "./InstructionsStep/InstructionsStep";
import ProgressBar from "./ProgressBar/ProgressBar";
import BinIcon from "../../../../assets/icons/bin.svg";

const INSTRUCTIONS_GUIDE_URL =
"https://help.editor.raspberrypi.org/hc/en-us/articles/52495086715028-How-to-write-project-instructions";

const InstructionsPanel = () => {
const InstructionsPanel = ({ toggleOption, isMobile }) => {
const [tabIndex, setTabIndex] = useState(0);
const [showRemoveStepModal, setShowRemoveStepModal] = useState(false);
const [removeScope, setRemoveScope] = useState(REMOVE_CURRENT_STEP);
Expand Down Expand Up @@ -110,11 +110,31 @@ const InstructionsPanel = () => {

const panelRef = useRef(null);

const collapsePanel = () => {
toggleOption("instructions");
if (window.plausible) {
window.plausible("Collapse file pane");
}
};

return (
<SidebarPanel
defaultWidth="30vw"
panelRef={panelRef}
heading={t("instructionsPanel.projectSteps")}
headingPrefix={
!isMobile && toggleOption ? (
<Button
className="sidebar__panel-collapse"
icon={<DoubleArrowLeft />}
iconOnly
text={t("sidebar.collapseInstructions")}
onClick={collapsePanel}
size="small"
type="tertiary"
/>
) : undefined
}
buttons={
instructionsEditable && !hasInstructions
? [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,44 @@
fireEvent.click(removeModalScopeRadio(scope));
});

describe("The panel header collapse button", () => {
const renderPanel = (props = {}) =>
renderWithProviders(<InstructionsPanel {...props} />, {
preloadedState: {
editor: {
project: { instructions: [{ markdown_content: "instructions" }] },
instructionsEditable: true,
},
instructions: { permitOverride: true, currentStepPosition: 0 },
},
});

test("is not rendered when the panel cannot be toggled", () => {
renderPanel();

expect(
screen.queryByTitle("sidebar.collapseInstructions"),
).not.toBeInTheDocument();
});

test("is not rendered on mobile", () => {
renderPanel({ toggleOption: vi.fn(), isMobile: true });

expect(
screen.queryByTitle("sidebar.collapseInstructions"),
).not.toBeInTheDocument();
});

test("closes the instructions panel when clicked", () => {
const toggleOption = vi.fn();
renderPanel({ toggleOption });

fireEvent.click(screen.getByTitle("sidebar.collapseInstructions"));

Check failure on line 77 in src/components/Menus/Sidebar/InstructionsPanel/InstructionsPanel.test.jsx

View workflow job for this annotation

GitHub Actions / test

src/components/Menus/Sidebar/InstructionsPanel/InstructionsPanel.test.jsx > The panel header collapse button > closes the instructions panel when clicked

TestingLibraryElementError: Unable to find an element with the title: sidebar.collapseInstructions. Ignored nodes: comments, script, style <body> <div> <div class="sidebar__panel" data-testid="sidebar__panel" style="position: relative; user-select: auto; width: 30vw; height: 100%; max-width: 600px; min-width: 280px; box-sizing: border-box; flex-shrink: 0;" > <div class="sidebar__panel-header" > <div class="sidebar__panel-heading-row" > <button aria-label="" class="rpf-button rpf-button--tertiary rpf-button--sm rpf-button--icon-only sidebar__panel-collapse" > <svg fill="none" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M11 18L5 12L11 6L12.4 7.4L7.825 12L12.4 16.6L11 18ZM17.6 18L11.6 12L17.6 6L19 7.4L14.425 12L19 16.6L17.6 18Z" /> </svg> </button> <h2 class="sidebar__panel-heading" > instructionsPanel.projectSteps </h2> </div> <a class="rpf-link" href="https://help.editor.raspberrypi.org/hc/en-us/articles/52495086715028-How-to-write-project-instructions" rel="noreferrer" target="_blank" > instructionsPanel.guideLink </a> </div> <div class="sidebar__panel-content" > <div class="project-instructions" > <div class="c-instruction-tabs" > <div class="react-tabs" data-rttabs="true" > <ul class="react-tabs__tab-list" role="tablist" > <li aria-controls="react-tabs-9" aria-disabled="false" aria-selected="true" class="react-tabs__tab react-tabs__tab--selected" data-rttab="true" id="react-tabs-8" role="tab" tabindex="0" > instructionsPanel.edit </li> <li aria-controls="react-tabs-11" aria-disabled="false" aria-selected="false" class="react-tabs__tab" data-rttab="true" id="react-tabs-10" role="tab" > instructionsPanel.view </li> </ul> <div aria-labelledby="react-tabs-8" class="react-tabs__tab-panel react-tabs__tab-panel--selected" id="react-tabs-9" role="tabpanel" > <textarea data-testid="instructionTextarea" > instructions </textarea> </div> <div aria-labelledby="react-tabs-10" class="react-tabs__tab-panel" id="react-tabs-11" role="tabpanel" /> </div> <div class="instructions-panel__step-actions" > <button aria-label="" class="rpf-button rpf-button--secondary rpf-button--full-width" > <span class="text" > instructionsPanel.addStep </span> <svg fill="none" height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg" > <path d="M6 14V8H0V6H6V0H8V6H14V8H8V14H6Z" /> </svg> </button> <b

expect(toggleOption).toHaveBeenCalledWith("instructions");
});
});

describe("When instructionsEditable changes from false to true", () => {
test("does not leave the rendered preview above the edit/view tabs", () => {
const { container, store } = renderWithProviders(<InstructionsPanel />, {
Expand Down
5 changes: 4 additions & 1 deletion src/components/Menus/Sidebar/Sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ const Sidebar = ({
} else if (!optionIsAvailable) {
setOption(nextDefaultOption);
dispatch(setSidebarOption(nextDefaultOption));
} else {
setOption(selectedSidebarOption);
}
}, [dispatch, nextDefaultOption, optionIsAvailable, selectedSidebarOption]);

Expand Down Expand Up @@ -245,14 +247,15 @@ const Sidebar = ({
>
<SidebarBar
menuOptions={menuOptions}
option={activeOption}
activeOption={activeOption}
toggleOption={toggleOption}
instructions={instructionsSteps}
allowMobileView={allowMobileView}
/>
{activeOption && (
<CustomSidebarPanel
isMobile={isMobile}
toggleOption={toggleOption}
{...(optionDict.panelProps || {})}
/>
)}
Expand Down
12 changes: 6 additions & 6 deletions src/components/Menus/Sidebar/SidebarBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { MOBILE_MEDIA_QUERY } from "../../../utils/mediaQueryBreakpoints";
const SidebarBar = (props) => {
const {
menuOptions,
option,
activeOption,
toggleOption,
instructions = false,
allowMobileView = true,
Expand Down Expand Up @@ -59,7 +59,7 @@ const SidebarBar = (props) => {
};

const collapsePopOut = () => {
toggleOption(option);
toggleOption(activeOption);
if (window.plausible) {
window.plausible("Collapse file pane");
}
Expand All @@ -81,7 +81,7 @@ const SidebarBar = (props) => {
return (
<div
className={classNames("sidebar__bar", {
"sidebar__bar--selected": option,
"sidebar__bar--selected": activeOption,
})}
>
<div className={`sidebar__bar-options--top`}>
Expand All @@ -95,7 +95,7 @@ const SidebarBar = (props) => {
key={i}
Icon={menuOption.icon}
title={menuOption.title}
isActive={option === menuOption.name}
isActive={activeOption === menuOption.name}
toggleOption={toggleOption}
name={menuOption.name}
/>
Expand All @@ -107,13 +107,13 @@ const SidebarBar = (props) => {
key={i}
Icon={menuOption.icon}
title={menuOption.title}
isActive={option === menuOption.name}
isActive={activeOption === menuOption.name}
toggleOption={toggleOption}
name={menuOption.name}
/>
))}
{!isMobile &&
(option ? (
(activeOption ? (
<div className="sidebar__bar-option-wrapper">
<Button
className="sidebar__bar-option"
Expand Down
Loading
Loading