Skip to content
This repository has been archived by the owner on Jan 23, 2025. It is now read-only.

style: enhancements for responsive design #930

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
10 changes: 9 additions & 1 deletion src/components/context/LayoutContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { createContext, useContext, useMemo, useState } from 'react';
import { createContext, useContext, useEffect, useMemo, useState } from 'react';

import { useMediaQuery, useTheme } from '@mui/material';

import { ChatStatus } from '@graasp/sdk';

Expand Down Expand Up @@ -71,6 +73,9 @@ export const LayoutContextProvider = ({
null,
);

const theme = useTheme();

const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [isMainMenuOpen, setIsMainMenuOpen] = useState(true);
const [isItemSharingOpen, setIsItemSharingOpen] = useState(true);

Expand All @@ -80,6 +85,9 @@ export const LayoutContextProvider = ({
new URLSearchParams(window.location.search).get('chat') === ChatStatus.Open;
const [isChatboxMenuOpen, setIsChatboxMenuOpen] = useState(chatIsOpen);

useEffect(() => {
setIsMainMenuOpen(!isMobile);
}, [isMobile]);
const value: LayoutContextInterface = useMemo(
() => ({
mode,
Expand Down
5 changes: 3 additions & 2 deletions src/components/item/header/ItemHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ const ItemHeader = ({ showNavigation = true }: Props): JSX.Element => {
return (
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
mb={1}
justifyContent="space-between"
mb={3}
mt={2}
id={ITEM_HEADER_ID}
>
{/* display empty div to render actions on the right */}
Expand Down
179 changes: 166 additions & 13 deletions src/components/item/header/ItemHeaderActions.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
import { Stack } from '@mui/material';
import { useState } from 'react';

import MoreVertIcon from '@mui/icons-material/MoreVert';
import {
Box,
Divider,
IconButton,
Stack,
SwipeableDrawer,
Typography,
styled,
useMediaQuery,
useTheme,
} from '@mui/material';

import { DiscriminatedItem, ItemType, PermissionLevel } from '@graasp/sdk';
import { ChatboxButton } from '@graasp/ui';
Expand All @@ -22,6 +35,7 @@ import ShareButton from '../../common/ShareButton';
import { useCurrentUserContext } from '../../context/CurrentUserContext';
import { useLayoutContext } from '../../context/LayoutContext';
import ItemMenu from '../../main/ItemMenu';
import MobileItemMenu from '../../main/MobileItemMenu';
import ItemSettingsButton from '../settings/ItemSettingsButton';
import ModeButton from './ModeButton';

Expand All @@ -31,8 +45,45 @@ type Props = {
item?: DiscriminatedItem;
};

// a way to expand button to include the text
const StyledBox = styled(Box)(() => ({
'& span': {
maxWidth: '20px',
},
'& button': {
paddingRight: '100px',
LinaYahya marked this conversation as resolved.
Show resolved Hide resolved
},
}));

type ButtonWithTextProps = {
children: JSX.Element;
isMobile: boolean;
text: string;
onClick: () => void;
};

const IconButtonWithText = ({
children,
isMobile,
text,
onClick,
}: ButtonWithTextProps): JSX.Element =>
isMobile ? (
<StyledBox
onClick={onClick}
p="6px 11px"
LinaYahya marked this conversation as resolved.
Show resolved Hide resolved
display="flex"
alignItems="center"
gap={3}
>
{children} {text}
</StyledBox>
) : (
children
);
const ItemHeaderActions = ({ item }: Props): JSX.Element => {
const { t: translateBuilder } = useBuilderTranslation();

const {
editingItemId,
openedActionTabId,
Expand All @@ -42,6 +93,9 @@ const ItemHeaderActions = ({ item }: Props): JSX.Element => {
} = useLayoutContext();

const { data: member } = useCurrentUserContext();
const [isItemActionsDrawerOpen, setIsItemActionsDrawerOpen] = useState(false);
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
LinaYahya marked this conversation as resolved.
Show resolved Hide resolved

const { data: memberships } = useItemMemberships(item?.id);
const canEdit = isItemUpdateAllowedForUser({
Expand All @@ -60,6 +114,10 @@ const ItemHeaderActions = ({ item }: Props): JSX.Element => {
setIsItemMetadataMenuOpen(false);
};

const toggleActionsDrawer = () => {
setIsItemActionsDrawerOpen(!isItemActionsDrawerOpen);
};
const closeDrawer = () => setIsItemActionsDrawerOpen(false);
const renderItemActions = () => {
// if id is defined, we are looking at an item
if (item && item?.id) {
Expand All @@ -69,33 +127,128 @@ const ItemHeaderActions = ({ item }: Props): JSX.Element => {
ITEM_TYPES_WITH_CAPTIONS.includes(item.type) &&
canEdit;

const shareActions = (
<>
<IconButtonWithText
isMobile={isMobile}
text={translateBuilder(BUILDER.SHARE_ITEM_BUTTON)}
onClick={closeDrawer}
>
<ShareButton itemId={item.id} />
</IconButtonWithText>
{canAdmin && (
<IconButtonWithText
isMobile={isMobile}
text={translateBuilder(BUILDER.LIBRARY_SETTINGS_BUTTON_TITLE)}
onClick={closeDrawer}
>
<PublishButton itemId={item.id} />
</IconButtonWithText>
)}
</>
);
const activeActions = (
<>
{showEditButton && <EditButton item={item} />}
{/* prevent moving from top header to avoid confusion */}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not remove this comment. it should be placed above the canMove prop.

<ItemMenu item={item} canMove={false} canEdit={showEditButton} />
{showEditButton && (
<IconButtonWithText
isMobile={isMobile}
text={translateBuilder(BUILDER.EDIT_ITEM_BUTTON)}
onClick={closeDrawer}
>
<EditButton item={item} />
</IconButtonWithText>
)}
<Box width="100%">
{isMobile ? (
<MobileItemMenu
item={item}
canMove={false}
canEdit={showEditButton}
>
{shareActions}
</MobileItemMenu>
) : (
<ItemMenu item={item} canMove={false} canEdit={showEditButton} />
)}
</Box>

<ShareButton itemId={item.id} />
<ChatboxButton
tooltip={translateBuilder(BUILDER.ITEM_CHATBOX_TITLE)}
id={ITEM_CHATBOX_BUTTON_ID}
onClick={onClickChatbox}
/>
{canAdmin && <PublishButton itemId={item.id} />}
{!isMobile && shareActions}
{isMobile && <Divider />}
{!isMobile && (
<ChatboxButton
tooltip={translateBuilder(BUILDER.ITEM_CHATBOX_TITLE)}
id={ITEM_CHATBOX_BUTTON_ID}
onClick={onClickChatbox}
/>
)}
</>
);

return (
<>
{openedActionTabId !== ItemActionTabs.Settings && activeActions}
{canEdit && <ItemSettingsButton id={item.id} />}
<DownloadButton id={item.id} name={item.name} />
<IconButtonWithText
isMobile={isMobile}
text={translateBuilder(BUILDER.DOWNLOAD_ITEM_BUTTON)}
onClick={closeDrawer}
>
<DownloadButton id={item.id} name={item.name} />
</IconButtonWithText>
{canEdit && (
<IconButtonWithText
isMobile={isMobile}
text={translateBuilder(BUILDER.SETTINGS_TITLE)}
onClick={closeDrawer}
>
<ItemSettingsButton id={item.id} />
</IconButtonWithText>
)}
</>
);
}
return null;
};

if (isMobile) {
return item ? (
<>
<Box display="flex" sx={{ '& button': { padding: 0.5 } }}>
<ItemMetadataButton />
<ModeButton />
<ChatboxButton
tooltip={translateBuilder(BUILDER.ITEM_CHATBOX_TITLE)}
id={ITEM_CHATBOX_BUTTON_ID}
onClick={onClickChatbox}
/>
<IconButton onClick={toggleActionsDrawer}>
<MoreVertIcon />
</IconButton>
</Box>

<SwipeableDrawer
anchor="bottom"
open={isItemActionsDrawerOpen}
onClose={closeDrawer}
onOpen={() => setIsItemActionsDrawerOpen(true)}
PaperProps={{ sx: { maxHeight: '80vh', paddingY: 2 } }}
>
<Typography px={3} pb={1} variant="h5">
{item.name}
</Typography>
<Divider sx={{ borderColor: theme.palette.grey[400] }} />
<Box
display="flex"
flexDirection="column"
sx={{ maxHeight: '100%', overflow: 'auto', marginTop: 1 }}
>
{renderItemActions()}
</Box>
</SwipeableDrawer>
</>
) : (
<ModeButton />
);
}
LinaYahya marked this conversation as resolved.
Show resolved Hide resolved
return (
<Stack direction="row">
{renderItemActions()}
Expand Down
8 changes: 7 additions & 1 deletion src/components/layout/Navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useLocation } from 'react-router-dom';

import { useMediaQuery, useTheme } from '@mui/material';

import {
HomeMenu,
ItemMenu,
Expand Down Expand Up @@ -39,6 +41,9 @@ const Navigator = (): JSX.Element | null => {
const { data: item, isLoading: isItemLoading } = useItem(itemId);
const itemPath = item?.path;

const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));

LinaYahya marked this conversation as resolved.
Show resolved Hide resolved
const { data: parents, isLoading: areParentsLoading } = useParents({
id: itemId,
path: itemPath,
Expand Down Expand Up @@ -114,13 +119,14 @@ const Navigator = (): JSX.Element | null => {
return (
<Navigation
id={NAVIGATION_ROOT_ID}
sx={{ paddingLeft: 2 }}
item={item}
buildToItemPath={buildToItemPath}
parents={parents}
renderRoot={renderRoot}
buildMenuItemId={buildNavigationLink}
useChildren={useChildren as any}
// eslint-disable-next-line react/jsx-props-no-spreading
{...(isMobile && { maxItems: 2 })}
Comment on lines +127 to +128
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// eslint-disable-next-line react/jsx-props-no-spreading
{...(isMobile && { maxItems: 2 })}
maxItems={isMobile ? 2 : undefined}

/>
);
};
Expand Down
14 changes: 7 additions & 7 deletions src/components/main/ItemMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,12 @@ const ItemMenu = ({
: [];
return result.concat([
<HideButton key="hide" type={ActionButton.MENU_ITEM} item={item} />,
<PinButton key="pin" type={ActionButton.MENU_ITEM} item={item} />,
<CollapseButton
key="collapse"
type={ActionButton.MENU_ITEM}
item={item}
/>,
<PinButton key="pin" type={ActionButton.MENU_ITEM} item={item} />,
<RecycleButton
key="recycle"
type={ActionButton.MENU_ITEM}
Expand All @@ -104,18 +104,18 @@ const ItemMenu = ({
return null;
}
return [
<FavoriteButton
size="medium"
key="favorite"
type={ActionButton.MENU_ITEM}
item={item}
/>,
<CopyButton
key="copy"
type={ActionButton.MENU_ITEM}
itemIds={[item.id]}
onClick={handleClose}
/>,
<FavoriteButton
size="medium"
key="favorite"
type={ActionButton.MENU_ITEM}
item={item}
/>,
];
};

Expand Down
20 changes: 15 additions & 5 deletions src/components/main/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { Link } from 'react-router-dom';

import { Grid, Typography, styled } from '@mui/material';
import {
Grid,
Typography,
styled,
useMediaQuery,
useTheme,
} from '@mui/material';
import Box from '@mui/material/Box';

import { Context } from '@graasp/sdk';
Expand Down Expand Up @@ -46,9 +52,11 @@ export const platformsHostsMap = defaultHostsMapper({

const Main = ({ children }: Props): JSX.Element => {
const { isMainMenuOpen, setIsMainMenuOpen } = useLayoutContext();

const itemId = useShortenURLParams(ITEM_ID_PARAMS);

const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
LinaYahya marked this conversation as resolved.
Show resolved Hide resolved

const getNavigationEvents = usePlatformNavigation(platformsHostsMap, itemId);
const platformProps = {
[Platform.Builder]: {
Expand All @@ -73,9 +81,11 @@ const Main = ({ children }: Props): JSX.Element => {
<Box display="flex" ml={2}>
<StyledLink to={HOME_PATH}>
<GraaspLogo height={GRAASP_LOGO_HEADER_HEIGHT} sx={{ fill: 'white' }} />
<Typography variant="h6" color="inherit" mr={2} ml={1}>
{APP_NAME}
</Typography>
{!isMobile && (
<Typography variant="h6" color="inherit" mr={2} ml={1}>
{APP_NAME}
</Typography>
)}
</StyledLink>
<PlatformSwitch
id={APP_NAVIGATION_PLATFORM_SWITCH_ID}
Expand Down
Loading