Skip to content

MobileNav component for smaller devices #2361

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

Merged
merged 49 commits into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
fc6496c
use EditableInput in Toolbar
lindapaiste Jun 10, 2023
8277cb8
Merge branch 'develop' into fix/toolbar-title
lindapaiste Jul 6, 2023
a51d2c6
Merge branch 'develop' into fix/toolbar-title
lindapaiste Jul 22, 2023
dafc74d
Merge branch 'develop' into fix/toolbar-title
lindapaiste Jul 30, 2023
d6f831d
Merge branch 'develop' of https://github.com/processing/p5.js-web-edi…
dewanshDT Aug 5, 2023
002945e
Merge remote-tracking branch 'upstream/develop' into fix/toolbar-title
lindapaiste Aug 5, 2023
cff161c
Merge branch 'develop' of https://github.com/processing/p5.js-web-edi…
dewanshDT Aug 6, 2023
62c710b
initial MobileNav component
dewanshDT Aug 6, 2023
07fd1a9
account and editor icon
dewanshDT Aug 6, 2023
122c5f2
useHistory
dewanshDT Aug 6, 2023
a154a87
updated the theme for mobile panel
dewanshDT Aug 6, 2023
dc4e9d4
updated the Nav component to use the MobileNav component
dewanshDT Aug 6, 2023
a02694a
the header and the props
dewanshDT Aug 6, 2023
694e887
snapshots
dewanshDT Aug 7, 2023
6ef16e5
transition override
dewanshDT Aug 9, 2023
33d1223
memoized the title
dewanshDT Aug 9, 2023
2c43627
replaced all navigate with link
dewanshDT Aug 9, 2023
e0586a4
keyboardShortcuts
dewanshDT Aug 9, 2023
6c186ef
cleanup
dewanshDT Aug 9, 2023
60a02f1
title translations
dewanshDT Aug 9, 2023
7e13ecf
Use core Nav logic in MobileNav.
lindapaiste Aug 10, 2023
1c9237d
the more svg
dewanshDT Aug 11, 2023
6df289a
Merge branch 'develop' of https://github.com/processing/p5.js-web-edi…
dewanshDT Aug 11, 2023
08f3251
Merge branch 'develop' into dewanshmobile/mobilenav
dewanshDT Aug 11, 2023
99de115
Merge branch 'dewanshmobile/mobilenav' of https://github.com/dewanshD…
dewanshDT Aug 11, 2023
69628e7
Merge remote-tracking branch 'upstream/develop' into fix/mobilenav-ac…
lindapaiste Aug 11, 2023
6af87f3
Can test on mobile or desktop.
lindapaiste Aug 11, 2023
e02d6ba
Add JSDoc to test-utils for better Intellisense when setting options …
lindapaiste Aug 11, 2023
b25e8ec
Rollback click handling on header logo.
lindapaiste Aug 11, 2023
0180a67
Regenerate snapshots
lindapaiste Aug 11, 2023
2b7596d
Merge pull request #3 from lindapaiste/fix/mobilenav-accessibility
dewanshDT Aug 11, 2023
58e819c
Merge branch 'develop' into dewanshmobile/mobilenav
dewanshDT Aug 11, 2023
3c0ca14
Merge branch 'develop' of https://github.com/processing/p5.js-web-edi…
dewanshDT Aug 12, 2023
9420858
Merge branch 'dewanshmobile/mobilenav' of https://github.com/dewanshD…
dewanshDT Aug 12, 2023
77db01e
language overlay
dewanshDT Aug 12, 2023
1088417
selected language indicator
dewanshDT Aug 12, 2023
aa3b454
Merge remote-tracking branch 'upstream/develop' into fix/toolbar-title
lindapaiste Aug 13, 2023
a49f834
move ProjectName to a separate file
lindapaiste Aug 13, 2023
5547591
Merge branch 'develop' of https://github.com/processing/p5.js-web-edi…
dewanshDT Aug 14, 2023
77fd047
Merge branch 'fix/toolbar-title' of https://github.com/lindapaiste/p5…
dewanshDT Aug 14, 2023
e8d7890
use ProjectName
dewanshDT Aug 14, 2023
334a6f5
Merge branch 'develop' into dewanshmobile/mobilenav
lindapaiste Aug 15, 2023
f916303
position
dewanshDT Aug 15, 2023
c9179e7
overflow and lang
dewanshDT Aug 15, 2023
bd1454e
dispatch
dewanshDT Aug 15, 2023
584de34
margin
dewanshDT Aug 15, 2023
be46e37
find fix
dewanshDT Aug 15, 2023
2a8d3e2
breakpoints and alignment
dewanshDT Aug 15, 2023
cef29cf
snapshots
dewanshDT Aug 15, 2023
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: 4 additions & 0 deletions client/common/icons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import DropdownArrow from '../images/down-filled-triangle.svg';
import Preferences from '../images/preferences.svg';
import Play from '../images/triangle-arrow-right.svg';
import More from '../images/more.svg';
import Editor from '../images/editor.svg';
import Account from '../images/account.svg';
import Code from '../images/code.svg';
import Save from '../images/save.svg';
import Terminal from '../images/terminal.svg';
Expand Down Expand Up @@ -83,6 +85,8 @@ export const GoogleIcon = withLabel(Google);
export const PlusIcon = withLabel(Plus);
export const CloseIcon = withLabel(Close);
export const ExitIcon = withLabel(Exit);
export const EditorIcon = withLabel(Editor);
export const AccountIcon = withLabel(Account);
export const DropdownArrowIcon = withLabel(DropdownArrow);
export const PreferencesIcon = withLabel(Preferences);
export const PlayIcon = withLabel(Play);
Expand Down
28 changes: 19 additions & 9 deletions client/components/Nav/NavBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React, {
} from 'react';
import { MenuOpenContext, NavBarContext } from './contexts';

function NavBar({ children }) {
function NavBar({ children, className }) {
const [dropdownOpen, setDropdownOpen] = useState('none');

const timerRef = useRef(null);
Expand Down Expand Up @@ -55,6 +55,15 @@ function NavBar({ children }) {
timerRef.current = setTimeout(() => setDropdownOpen('none'), 10);
}, [timerRef, setDropdownOpen]);

const toggleDropdownOpen = useCallback(
(dropdown) => {
setDropdownOpen((prevState) =>
prevState === dropdown ? 'none' : dropdown
);
},
[setDropdownOpen]
);

const contextValue = useMemo(
() => ({
createDropdownHandlers: (dropdown) => ({
Expand All @@ -64,9 +73,7 @@ function NavBar({ children }) {
);
},
onClick: () => {
setDropdownOpen((prevState) =>
prevState === 'none' ? dropdown : 'none'
);
toggleDropdownOpen(dropdown);
},
onBlur: handleBlur,
onFocus: clearHideTimeout
Expand All @@ -80,15 +87,16 @@ function NavBar({ children }) {
clearHideTimeout();
setDropdownOpen(dropdown);
}
})
}),
toggleDropdownOpen
}),
[setDropdownOpen, clearHideTimeout, handleBlur]
[setDropdownOpen, toggleDropdownOpen, clearHideTimeout, handleBlur]
);

return (
<NavBarContext.Provider value={contextValue}>
<header>
<nav className="nav" ref={nodeRef}>
<nav className={className} ref={nodeRef}>
<MenuOpenContext.Provider value={dropdownOpen}>
{children}
</MenuOpenContext.Provider>
Expand All @@ -99,11 +107,13 @@ function NavBar({ children }) {
}

NavBar.propTypes = {
children: PropTypes.node
children: PropTypes.node,
className: PropTypes.string
};

NavBar.defaultProps = {
children: null
children: null,
className: 'nav'
};

export default NavBar;
8 changes: 7 additions & 1 deletion client/components/Nav/NavDropdownMenu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React, { useContext, useMemo } from 'react';
import TriangleIcon from '../../images/down-filled-triangle.svg';
import { MenuOpenContext, NavBarContext, ParentMenuContext } from './contexts';

function NavDropdownMenu({ id, title, children }) {
export function useMenuProps(id) {
const activeMenu = useContext(MenuOpenContext);

const isOpen = id === activeMenu;
Expand All @@ -16,6 +16,12 @@ function NavDropdownMenu({ id, title, children }) {
id
]);

return { isOpen, handlers };
}

function NavDropdownMenu({ id, title, children }) {
const { isOpen, handlers } = useMenuProps(id);

return (
<li className={classNames('nav__item', isOpen && 'nav__item--open')}>
<button {...handlers}>
Expand Down
10 changes: 6 additions & 4 deletions client/components/Nav/NavMenuItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { useContext, useMemo } from 'react';
import ButtonOrLink from '../../common/ButtonOrLink';
import { NavBarContext, ParentMenuContext } from './contexts';

function NavMenuItem({ hideIf, ...rest }) {
function NavMenuItem({ hideIf, className, ...rest }) {
const parent = useContext(ParentMenuContext);

const { createMenuItemHandlers } = useContext(NavBarContext);
Expand All @@ -18,7 +18,7 @@ function NavMenuItem({ hideIf, ...rest }) {
}

return (
<li className="nav__dropdown-item">
<li className={className}>
<ButtonOrLink {...rest} {...handlers} />
</li>
);
Expand All @@ -31,13 +31,15 @@ NavMenuItem.propTypes = {
/**
* Provides a way to deal with optional items.
*/
hideIf: PropTypes.bool
hideIf: PropTypes.bool,
className: PropTypes.string
};

NavMenuItem.defaultProps = {
onClick: null,
value: null,
hideIf: false
hideIf: false,
className: 'nav__dropdown-item'
};

export default NavMenuItem;
3 changes: 2 additions & 1 deletion client/components/Nav/contexts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export const MenuOpenContext = createContext('none');

export const NavBarContext = createContext({
createDropdownHandlers: () => ({}),
createMenuItemHandlers: () => ({})
createMenuItemHandlers: () => ({}),
toggleDropdownOpen: () => {}
});
2 changes: 0 additions & 2 deletions client/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ export const PROJECT_SAVE_SUCCESS = 'PROJECT_SAVE_SUCCESS';
export const PROJECT_SAVE_FAIL = 'PROJECT_SAVE_FAIL';
export const NEW_PROJECT = 'NEW_PROJECT';
export const RESET_PROJECT = 'RESET_PROJECT';
export const SHOW_EDIT_PROJECT_NAME = 'SHOW_EDIT_PROJECT_NAME';
export const HIDE_EDIT_PROJECT_NAME = 'HIDE_EDIT_PROJECT_NAME';

export const SET_PROJECT = 'SET_PROJECT';
export const SET_PROJECTS = 'SET_PROJECTS';
Expand Down
3 changes: 3 additions & 0 deletions client/images/account.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions client/images/editor.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions client/images/more.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 0 additions & 12 deletions client/modules/IDE/actions/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,18 +351,6 @@ export function cloneProject(project) {
};
}

export function showEditProjectName() {
return {
type: ActionTypes.SHOW_EDIT_PROJECT_NAME
};
}

export function hideEditProjectName() {
return {
type: ActionTypes.HIDE_EDIT_PROJECT_NAME
};
}

export function setProjectSavedTime(updatedAt) {
return {
type: ActionTypes.SET_PROJECT_SAVED_TIME,
Expand Down
36 changes: 28 additions & 8 deletions client/modules/IDE/components/EditableInput.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,36 @@ function EditableInput({
emptyPlaceholder,
InputComponent,
inputProps,
onChange
onChange,
disabled,
'aria-label': ariaLabel
}) {
const [isEditing, setIsEditing] = React.useState(false);
const [currentValue, setCurrentValue] = React.useState(value || '');
const displayValue = currentValue || emptyPlaceholder;
const hasValue = currentValue !== '';
const classes = `editable-input editable-input--${
isEditing ? 'is-editing' : 'is-not-editing'
} editable-input--${hasValue ? 'has-value' : 'has-placeholder'}`;
const inputRef = React.createRef();
} editable-input--${hasValue ? 'has-value' : 'has-placeholder'} ${
disabled ? 'editable-input--disabled' : ''
}`;
const inputRef = React.useRef();
const { t } = useTranslation();
React.useEffect(() => {
if (isEditing) {
inputRef.current.focus();
inputRef.current?.focus();
}
}, [isEditing]);

function beginEditing() {
setIsEditing(true);
}

function cancelEditing() {
setIsEditing(false);
setCurrentValue(value);
}

function doneEditing() {
setIsEditing(false);

Expand All @@ -51,6 +60,8 @@ function EditableInput({
function checkForKeyAction(event) {
if (event.key === 'Enter') {
doneEditing();
} else if (event.key === 'Escape' || event.key === 'Esc') {
cancelEditing();
}
}

Expand All @@ -59,7 +70,11 @@ function EditableInput({
<button
className="editable-input__label"
onClick={beginEditing}
aria-label={t('EditableInput.EditValue', { display: displayValue })}
aria-label={
ariaLabel ?? t('EditableInput.EditValue', { display: displayValue })
}
aria-hidden={isEditing}
disabled={disabled}
>
<span>{displayValue}</span>
<EditIcon
Expand All @@ -74,9 +89,10 @@ function EditableInput({
type="text"
{...inputProps}
disabled={!isEditing}
aria-hidden={!isEditing}
onBlur={doneEditing}
onChange={updateValue}
onKeyPress={checkForKeyAction}
onKeyDown={checkForKeyAction}
ref={inputRef}
value={currentValue}
/>
Expand All @@ -89,7 +105,9 @@ EditableInput.defaultProps = {
InputComponent: 'input',
inputProps: {},
validate: () => true,
value: ''
value: '',
disabled: false,
'aria-label': undefined
};

EditableInput.propTypes = {
Expand All @@ -99,7 +117,9 @@ EditableInput.propTypes = {
inputProps: PropTypes.object, // eslint-disable-line
onChange: PropTypes.func.isRequired,
validate: PropTypes.func,
value: PropTypes.string
value: PropTypes.string,
disabled: PropTypes.bool,
'aria-label': PropTypes.string
};

export default EditableInput;
Loading