Skip to content

Commit

Permalink
Merge pull request #241 from tchryssos/tc-quick-access
Browse files Browse the repository at this point in the history
Quick Access
  • Loading branch information
tchryssos authored Sep 16, 2024
2 parents 55957f5 + 5fd870f commit 0842ba5
Show file tree
Hide file tree
Showing 13 changed files with 329 additions and 131 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@floating-ui/react": "^0.26.23",
"@mdi/js": "^7.4.47",
"@mdi/react": "^1.6.1",
"@mui/base": "5.0.0-beta.4",
"@playwright/test": "^1.35.0",
"@prisma/client": "^4.15.0",
Expand Down
5 changes: 3 additions & 2 deletions src/components/box/GridBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@ export function GridBox({
columnGap,
rowGap,
gridTemplateColumns,
gap,
...rest
}: PropsWithChildren<GridBoxProps>) {
return (
<Box
columnGap={columnGap || { base: 8, sm: 16 }}
columnGap={columnGap ?? gap ?? { base: 8, sm: 16 }}
columns={gridTemplateColumns ? undefined : columns}
display="grid"
gridTemplateColumns={gridTemplateColumns}
rowGap={rowGap || { base: 8, sm: 16 }}
rowGap={rowGap ?? gap ?? { base: 8, sm: 16 }}
// eslint-disable-next-line react/jsx-props-no-spreading
{...rest}
>
Expand Down
77 changes: 61 additions & 16 deletions src/components/form/containers/FormSection.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { css } from '@emotion/react';
import styled from '@emotion/styled';
import { PropsWithChildren, useContext, useEffect, useState } from 'react';
import {
CSSProperties,
PropsWithChildren,
useContext,
useEffect,
useState,
} from 'react';

import { RpgIcons } from '~/constants/icons';
import { Theme } from '~/constants/theme';
Expand All @@ -16,14 +22,19 @@ import { CollapseButton } from '../../buttons/CollapseButton';
import { RpgIcon } from '../../icons/RpgIcon';
import { Text } from '../../Text';

interface FormSectionProps {
type BorderProperties = {
borderless?: boolean;
borderColor?: Color;
borderStyle?: CSSProperties['borderStyle'];
};

type FormSectionProps = {
title: string;
children: React.ReactNode | React.ReactNode[];
columns?: GridBoxProps['columns'];
isCollapsible?: boolean;
className?: string;
visibilityTitle?: string;
borderless?: boolean;
gridTemplateColumns?: GridBoxProps['gridTemplateColumns'];
defaultExpanded?: boolean;
icon?: RpgIcons;
Expand All @@ -32,7 +43,7 @@ interface FormSectionProps {
titleColor?: Color;
onToggleOpen?: (nextOpenState: boolean) => void;
linkId?: string;
}
} & BorderProperties;

const TitleBox = styled(FlexBox)`
position: relative;
Expand All @@ -56,23 +67,42 @@ const Section = styled(FlexBox)`
height: 100%;
`;

const createCollapsibleStyles = (theme: Theme, borderless?: boolean) => css`
border-color: ${borderless ? 'transparent' : theme.colors.textAccent};
border-width: ${borderless ? 0 : theme.borderWidth[1]};
border-style: solid;
`;
const createCollapsibleStyles = (
theme: Theme,
borderProperties?: BorderProperties
) => {
const {
borderless,
borderColor: pBorderColor,
borderStyle: pBorderStyle,
} = borderProperties || {};

const borderColor = theme.colors[pBorderColor || 'textAccent'];
const borderStyle = pBorderStyle || 'solid';

const Line = styled(Box)`
return css`
border-color: ${borderless ? 'transparent' : borderColor};
border-width: ${borderless ? 0 : theme.borderWidth[1]};
border-style: ${borderStyle};
`;
};

const Line = styled(Box)<{ borderProperties?: BorderProperties }>`
height: 0;
width: 100%;
${({ theme }) => createCollapsibleStyles(theme)};
${({ theme, borderProperties }) =>
createCollapsibleStyles(theme, borderProperties)};
border-bottom-width: 0;
border-left-width: 0;
border-right-width: 0;
`;

const Container = styled(GridBox)<{ isOpen?: boolean; borderless?: boolean }>`
${({ theme, borderless }) => createCollapsibleStyles(theme, borderless)};
const Container = styled(GridBox)<{
isOpen?: boolean;
borderProperties?: BorderProperties;
}>`
${({ theme, borderProperties }) =>
createCollapsibleStyles(theme, borderProperties)};
border-top-width: 0;
height: 100%;
visibility: ${({ isOpen }) => (isOpen ? 'visible' : 'collapse')};
Expand Down Expand Up @@ -125,6 +155,8 @@ export function FormSection({
titleColor,
onToggleOpen,
linkId,
borderColor,
borderStyle,
}: FormSectionProps) {
const { getSectionVisibilityInfo, setSectionVisibilityInfo } =
useContext(VisibilityContext);
Expand Down Expand Up @@ -152,10 +184,23 @@ export function FormSection({
}, [initIsExpanded]);
// END - SECTION COLLAPSED STATUS - END

const borderProperties =
borderless || borderColor || borderStyle
? {
borderless,
borderColor,
borderStyle,
}
: undefined;

return (
<Section className={className} flexDirection="column">
<GridBox alignItems="end" gridTemplateColumns="auto 1fr">
<ButtonTitleWrapper transparent onClick={onChangeExpanded}>
<ButtonTitleWrapper
buttonLike={!isCollapsible}
transparent
onClick={onChangeExpanded}
>
<GridBox
alignItems="flex-end"
color={titleColor}
Expand Down Expand Up @@ -195,11 +240,11 @@ export function FormSection({
)}
</GridBox>
</ButtonTitleWrapper>
{!borderless && <Line />}
{!borderless && <Line borderProperties={borderProperties} />}
</GridBox>
<Container
alignContent="start"
borderless={borderless}
borderProperties={borderProperties}
columns={columns}
gridTemplateColumns={gridTemplateColumns}
gridTemplateRows={gridTemplateRows}
Expand Down
7 changes: 5 additions & 2 deletions src/components/formNav/DeleteButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ export function DeleteButton({ characterId, playerId }: DeleteButtonProps) {
};

return (
<>
// Focus trap on dialog adds two observer elements, but if those get caught in
// a flexbox with a gap or something, they shift the layout. This box makes sure
// that this whole button and dialog get treated as one element
<div>
<ConfirmationDialog
cancel={{ onClick: () => setIsConfirmModalOpen(false) }}
confirm={{ onClick: onDelete, label: 'Delete', severity: 'danger' }}
Expand All @@ -50,6 +53,6 @@ export function DeleteButton({ characterId, playerId }: DeleteButtonProps) {
<IconButton onClick={() => setIsConfirmModalOpen(true)}>
<Delete color="text" title="Delete character" />
</IconButton>
</>
</div>
);
}
38 changes: 35 additions & 3 deletions src/components/formNav/FormNavBaseButtons.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { useUser } from '@auth0/nextjs-auth0';
import { useTheme } from '@emotion/react';
import { mdiStarBoxMultiple } from '@mdi/js';
import Icon from '@mdi/react';
import { useRouter } from 'next/router';
import { useContext } from 'react';

Expand All @@ -13,21 +16,29 @@ import { IconButton } from '../buttons/IconButton';
import { Pencil } from '../icons/Pencil';
import { SaveButton } from './SaveButton';

interface NavButtonsProps {
export interface QuickAccessProps {
showQuickAccess: boolean;
setShowQuickAccess: (show: boolean) => void;
}

type NavButtonProps = {
isMyCharacter: boolean;
rulebookName: RulebookType;
characterName: string;
}
quickAccess?: QuickAccessProps;
};

export function FormNavBaseButtons({
isMyCharacter,
rulebookName,
characterName,
}: NavButtonsProps) {
quickAccess,
}: NavButtonProps) {
const { user } = useUser();
const { isEditMode, setIsEditMode } = useContext(EditContext);
const { query } = useRouter();
const isNew = useIsNewCharacter();
const theme = useTheme();

return (
<>
Expand Down Expand Up @@ -63,6 +74,27 @@ export function FormNavBaseButtons({
titleId="edit-pencil-icon"
/>
</IconButton>
{quickAccess && (
<IconButton
onClick={() =>
quickAccess.setShowQuickAccess(!quickAccess.showQuickAccess)
}
>
<Icon
color={
quickAccess.showQuickAccess
? theme.colors.success
: theme.colors.text
}
path={mdiStarBoxMultiple}
title={
quickAccess.showQuickAccess
? 'Close Quick Access'
: 'Open Quick Access'
}
/>
</IconButton>
)}
</>
);
}
5 changes: 3 additions & 2 deletions src/components/meta/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';

import { NavContext } from '~/logic/contexts/navContext';
import { useBreakpointsAtLeast } from '~/logic/hooks/useBreakpoints';
import { pxToRem } from '~/logic/utils/styles/pxToRem';

import { FlexBox } from '../box/FlexBox';
import { DropdownMenuProps } from '../dropdowns/DropdownMenu';
Expand All @@ -19,9 +20,9 @@ const PageWrapper = styled(FlexBox)`
max-width: ${({ theme }) => theme.breakpointValues.lg}px;
width: 100%;
height: 100%;
padding-top: ${({ theme }) => theme.spacing[80]};
padding-top: ${pxToRem(120)};
${({ theme }) => theme.breakpoints.xs} {
padding-top: ${({ theme }) => theme.spacing[128]};
padding-top: ${pxToRem(140)};
}
`;

Expand Down
63 changes: 30 additions & 33 deletions src/components/nav/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { LogoAscii } from '../ascii/LogoAscii';
import { Box } from '../box/Box';
import { FlexBox } from '../box/FlexBox';
import { GridBox } from '../box/GridBox';
import { Divider } from '../divider/Divider';
import { DropdownMenuProps } from '../dropdowns/DropdownMenu';
import { ProfileDropdown } from '../dropdowns/ProfileDropdown';
import { RpgIcon } from '../icons/RpgIcon';
Expand Down Expand Up @@ -77,12 +76,6 @@ const Portal = styled.div<{ flexGap: Spacing }>`
const UserName = styled(Text)`
white-space: nowrap;
`;

const VertDivider = styled(Divider)`
align-self: stretch;
height: unset;
`;

interface NavBarProps {
title: string;
setIconPortalNode: (node: HTMLDivElement) => void;
Expand All @@ -97,15 +90,20 @@ export function NavBar({
dropdownMenuItems,
}: NavBarProps) {
const isXxs = useBreakpointsLessThan('xs');
const atLeastMd = useBreakpointsAtLeast('md');
const flexGap = isXxs ? 8 : 16;
const { user } = useUser();
const userName = getNameFromUser(user as StrictSessionUser);
const atLeastMd = useBreakpointsAtLeast('md');

return (
<Toolbar center flex={1}>
<Toolbar center flex={1} flexDirection="column">
<NavProgress />
<InnerToolbar alignItems="flex-end" flex={1} flexDirection="column">
<InnerToolbar
alignItems="flex-end"
flex={1}
flexDirection="column"
width="100%"
>
<TopRow alignItems="center" justifyContent="space-between">
<LogoTitleBox alignItems="center" gap={flexGap}>
<HomeLink href={HOME_ROUTE}>
Expand All @@ -119,36 +117,35 @@ export function NavBar({
)}
</LogoTitleBox>
<FlexBox alignItems="center" gap={flexGap}>
<Portal flexGap={flexGap} ref={setIconPortalNode} />
{userName && atLeastMd && (
<>
<VertDivider color="accentLight" vertical />
<Link
href={createUsersRoute((user as StrictSessionUser).id)}
isInternal
<Link
href={createUsersRoute((user as StrictSessionUser).id)}
isInternal
>
<GridBox
alignItems="center"
gap={8}
gridTemplateColumns="auto 1fr"
maxWidth={pxToRem(200)}
>
<GridBox
alignItems="center"
gap={8}
gridTemplateColumns="auto 1fr"
maxWidth={pxToRem(200)}
>
<Box height={pxToRem(18)} width={pxToRem(18)}>
<RpgIcon
iconIndex={getIconFromUser(user as StrictSessionUser)}
/>
</Box>
<UserName as="p" overflow="hidden" textOverflow="ellipsis">
{userName}
</UserName>
</GridBox>
</Link>
</>
<Box height={pxToRem(18)} width={pxToRem(18)}>
<RpgIcon
iconIndex={getIconFromUser(user as StrictSessionUser)}
/>
</Box>
<UserName as="p" overflow="hidden" textOverflow="ellipsis">
{userName}
</UserName>
</GridBox>
</Link>
)}
<ProfileDropdown dropdownMenuItems={dropdownMenuItems} />
</FlexBox>
</TopRow>
</InnerToolbar>
<FlexBox flex={1} justifyContent="flex-end" marginTop={4} width="100%">
<Portal flexGap={flexGap} ref={setIconPortalNode} />
</FlexBox>
</Toolbar>
);
}
Loading

0 comments on commit 0842ba5

Please sign in to comment.