Skip to content
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

feat: add menu to dashboard nav #9844

Merged
Merged
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
24 changes: 21 additions & 3 deletions packages/client/components/DashNavList/DashNavList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import {useFragment} from 'react-relay'
import {PALETTE} from '~/styles/paletteV3'
import {DashNavList_organization$key} from '../../__generated__/DashNavList_organization.graphql'
import {TierEnum} from '../../__generated__/DowngradeToStarterMutation.graphql'
import useBreakpoint from '../../hooks/useBreakpoint'
import {Breakpoint} from '../../types/constEnums'
import {upperFirst} from '../../utils/upperFirst'
import LeftDashNavItem from '../Dashboard/LeftDashNavItem'
import BaseTag from '../Tag/BaseTag'
import DashNavListTeams from './DashNavListTeams'
import DashNavMenu from './DashNavMenu'

const EmptyTeams = styled('div')({
fontSize: 16,
Expand All @@ -32,27 +35,28 @@ const Tag = styled(BaseTag)<{tier: TierEnum | null}>(({tier}) => ({
}))

interface Props {
className?: string
organizationsRef: DashNavList_organization$key | null
onClick?: () => void
}

const DashNavList = (props: Props) => {
const {className, onClick, organizationsRef} = props
const {onClick, organizationsRef} = props
const organizations = useFragment(
graphql`
fragment DashNavList_organization on Organization @relay(plural: true) {
...DashNavListTeams_organization
...DashNavMenu_organization
id
name
tier
...DashNavListTeams_organization
viewerTeams {
id
}
}
`,
organizationsRef
)
const isDesktop = useBreakpoint(Breakpoint.SIDEBAR_LEFT)
const teams = organizations?.flatMap((org) => org.viewerTeams)

if (teams?.length === 0) {
Expand Down Expand Up @@ -84,6 +88,20 @@ const DashNavList = (props: Props) => {
label={'Settings & Members'}
/>
</div>

{isDesktop ? (
<DashNavMenu organizationRef={org} />
) : (
<StyledLeftDashNavItem
className={'bg-transparent'}
icon={'manageAccounts'}
isViewerOnTeam
onClick={onClick}
href={`/me/organizations/${org.id}/billing`}
label={'Settings & Members'}
/>
)}
<div className='border-t border-solid border-slate-300' />
<DashNavListTeams onClick={onClick} organizationRef={org} />
</div>
)
Expand Down
98 changes: 98 additions & 0 deletions packages/client/components/DashNavList/DashNavMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import styled from '@emotion/styled'
import graphql from 'babel-plugin-relay/macro'
import React from 'react'
import {useFragment} from 'react-relay'
import {useHistory} from 'react-router'
import {DashNavMenu_organization$key} from '../../__generated__/DashNavMenu_organization.graphql'
import {PALETTE} from '../../styles/paletteV3'
import {Menu} from '../../ui/Menu/Menu'
import {MenuContent} from '../../ui/Menu/MenuContent'
import {MenuItem} from '../../ui/Menu/MenuItem'
import LeftDashNavItem from '../Dashboard/LeftDashNavItem'

const StyledLeftDashNavItem = styled(LeftDashNavItem)<{isViewerOnTeam: boolean}>(
({isViewerOnTeam}) => ({
color: isViewerOnTeam ? PALETTE.SLATE_700 : PALETTE.SLATE_600,
borderRadius: 44,
paddingLeft: 15
})
)

type Props = {
organizationRef: DashNavMenu_organization$key
}

const DashNavMenu = (props: Props) => {
const {organizationRef} = props
const history = useHistory()
const org = useFragment(
graphql`
fragment DashNavMenu_organization on Organization {
id
tier
}
`,
organizationRef
)
const {id: orgId, tier} = org
const menuItems = [
{
label: (
<>
Plans & Billing{' '}
{tier === 'starter' && (
<>
•&nbsp;<span className='text-sky-500'>Upgrade</span>
</>
)}
</>
),
href: `/me/organizations/${orgId}/billing`
},
{
label: 'Teams',
href: `/me/organizations/${orgId}/teams`
},
{
label: 'Members',
href: `/me/organizations/${orgId}/members`
},
{
label: 'Organization Settings',
href: `/me/organizations/${orgId}/settings`
},
{
label: 'Authentication',
href: `/me/organizations/${orgId}/authentication`
}
]

const handleMenuItemClick = (href: string) => {
history.push(href)
}

return (
<Menu
trigger={
<div>
<StyledLeftDashNavItem
className={'bg-transparent'}
icon={'manageAccounts'}
isViewerOnTeam
label={'Settings & Members'}
/>
</div>
}
>
<MenuContent side='right' align='center' sideOffset={20}>
{menuItems.map((item) => (
<MenuItem key={item.href} onClick={() => handleMenuItemClick(item.href)}>
{item.label}
</MenuItem>
))}
</MenuContent>
</Menu>
)
}

export default DashNavMenu
25 changes: 14 additions & 11 deletions packages/client/components/MeetingOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React, {useEffect, useState} from 'react'
import {useLazyLoadQuery} from 'react-relay'
import {MeetingOptionsQuery} from '../__generated__/MeetingOptionsQuery.graphql'
import {Menu} from '../ui/Menu/Menu'
import {MenuContent} from '../ui/Menu/MenuContent'
import {MenuItem} from '../ui/Menu/MenuItem'
import {Tooltip} from '../ui/Tooltip/Tooltip'
import {TooltipContent} from '../ui/Tooltip/TooltipContent'
Expand Down Expand Up @@ -92,17 +93,19 @@ const MeetingOptions = (props: Props) => {
</OptionsButton>
}
>
<Tooltip open={openTooltip}>
<div onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
<TooltipTrigger asChild>
<MenuItem onClick={handleClick} isDisabled={isDisabled}>
<div className='mr-3 flex text-slate-700'>{<SwapHorizIcon />}</div>
Change template
</MenuItem>
</TooltipTrigger>
</div>
<TooltipContent>{tooltipCopy}</TooltipContent>
</Tooltip>
<MenuContent sideOffset={10}>
<Tooltip open={openTooltip}>
<div onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
<TooltipTrigger asChild>
<MenuItem onClick={handleClick} isDisabled={isDisabled}>
<div className='mr-3 flex text-slate-700'>{<SwapHorizIcon />}</div>
Change template
</MenuItem>
</TooltipTrigger>
</div>
<TooltipContent>{tooltipCopy}</TooltipContent>
</Tooltip>
</MenuContent>
</Menu>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import useSnacksForNewMeetings from '~/hooks/useSnacksForNewMeetings'
import {PALETTE} from '~/styles/paletteV3'
import plural from '~/utils/plural'
import {Menu} from '../ui/Menu/Menu'
import {MenuContent} from '../ui/Menu/MenuContent'
import FlatButton from './FlatButton'
import SelectMeetingDropdown from './SelectMeetingDropdown'

Expand Down Expand Up @@ -56,7 +57,9 @@ const NewMeetingActionsCurrentMeetings = (props: Props) => {
</CurrentButton>
}
>
<SelectMeetingDropdown meetings={activeMeetings!} />
<MenuContent className='w-[300px]' sideOffset={10}>
<SelectMeetingDropdown meetings={activeMeetings!} />
</MenuContent>
</Menu>
)
}
Expand Down
31 changes: 8 additions & 23 deletions packages/client/ui/Menu/Menu.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,16 @@
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
import React from 'react'
import {twMerge} from 'tailwind-merge'

interface MenuProps extends DropdownMenu.DropdownMenuProps {
className?: string
trigger: React.ReactNode
}

export const Menu = React.forwardRef<HTMLDivElement, MenuProps>(
({trigger, className, children, ...props}, ref) => {
return (
<DropdownMenu.Root {...props}>
<DropdownMenu.Trigger asChild>{trigger}</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content
align='end'
className={twMerge(
'border-rad w-auto min-w-[200px] max-w-[400px] rounded-md bg-white shadow-lg outline-none',
className
)}
sideOffset={10}
ref={ref}
>
{children}
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
)
}
)
export const Menu: React.FC<MenuProps> = ({trigger, className, children, ...props}) => {
return (
<DropdownMenu.Root {...props}>
<DropdownMenu.Trigger asChild>{trigger}</DropdownMenu.Trigger>
<DropdownMenu.Portal>{children}</DropdownMenu.Portal>
</DropdownMenu.Root>
)
}
25 changes: 25 additions & 0 deletions packages/client/ui/Menu/MenuContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
import React from 'react'
import {twMerge} from 'tailwind-merge'

interface MenuContentProps extends DropdownMenu.MenuContentProps {
className?: string
children: React.ReactNode
}

export const MenuContent = React.forwardRef<HTMLDivElement, MenuContentProps>(
({className, children, ...props}, ref) => {
return (
<DropdownMenu.Content
className={twMerge(
'border-rad w-auto min-w-[200px] max-w-[400px] rounded-md bg-white shadow-lg outline-none',
className
)}
ref={ref}
{...props}
>
{children}
</DropdownMenu.Content>
)
}
)
Loading