Skip to content

Commit

Permalink
fix(facelift): refactor workspace preview to use large menu item
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrobonamin committed Nov 2, 2023
1 parent c5dc739 commit a119ef0
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const PresenceMenuItem = memo(function PresenceMenuItem(props: PresenceLi
ref={setMenuItemElement}
text={presence.user.displayName}
subText={hasLink ? undefined : 'Not in a document'}
avatar={
preview={
<UserAvatar
size={1}
key={presence.user.id}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {SelectIcon} from '@sanity/icons'
import {Button, MenuButton, Menu, MenuButtonProps, Box, Label, Stack} from '@sanity/ui'
import {Button, MenuButton, Menu, MenuButtonProps, Box, Label, Stack, Card} from '@sanity/ui'
import React, {useCallback, useMemo, useState} from 'react'
import styled from 'styled-components'
import {useActiveWorkspace} from '../../../activeWorkspaceMatcher'
import {useColorScheme} from '../../../colorScheme'
import {useWorkspaces} from '../../../workspaces'
import {Tooltip, MenuItem} from '../../../../../ui'
import {useWorkspaceAuthStates} from './hooks'
import {WorkspacePreview} from './WorkspacePreview'
import {STATE_TITLES, WorkspacePreviewIcon} from './WorkspacePreview'
import {useRouter} from 'sanity/router'

const StyledMenu = styled(Menu)`
Expand Down Expand Up @@ -95,21 +95,17 @@ export function WorkspaceMenuButton(props: WorkspaceMenuButtonProps) {

return (
<MenuItem
size="large"
key={workspace.name}
// eslint-disable-next-line react/jsx-no-bind
onClick={handleSelectWorkspace}
pressed={workspace.name === activeWorkspace.name}
>
{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
{/* @ts-ignore - Workspace preview hasn't been redesigned for facelift */}
<WorkspacePreview
icon={workspace?.icon}
selected={workspace.name === activeWorkspace.name}
state={state}
subtitle={workspace?.subtitle}
title={workspace?.title || workspace.name}
/>
</MenuItem>
selected={workspace.name === activeWorkspace.name}
badgeText={STATE_TITLES[state]}
preview={<WorkspacePreviewIcon icon={workspace.icon} size="large" />}
text={workspace?.title || workspace.name}
subText={workspace?.subtitle}
/>
)
})}
</StyledMenu>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,43 @@ import React, {createElement, isValidElement, useMemo} from 'react'
import {isValidElementType} from 'react-is'
import styled from 'styled-components'

const STATE_TITLES = {
export const STATE_TITLES = {
'logged-in': '',
'logged-out': 'Signed out',
'no-access': '',
}

export const MediaCard = styled(Card)`
width: 35px;
height: 35px;
type PreviewIconSize = 'small' | 'large'
interface MediaCardProps {
$size: PreviewIconSize
}

export const MediaCard = styled(Card)<MediaCardProps>`
width: ${(props) => (props.$size === 'small' ? '35px' : '41px')};
height: ${(props) => (props.$size === 'small' ? '35px' : '41px')};
svg {
width: 100%;
height: 100%;
}
`

export const WorkspacePreviewIcon = ({
icon,
size = 'small',
}: {
icon: React.ComponentType | React.ReactNode
size: PreviewIconSize
}) => {
const iconComponent = useMemo(() => createIcon(icon), [icon])

return (
<MediaCard radius={2} tone="transparent" $size={size}>
{iconComponent}
</MediaCard>
)
}

const createIcon = (icon: React.ComponentType | React.ReactNode) => {
if (isValidElementType(icon)) return createElement(icon)
if (isValidElement(icon)) return icon
Expand All @@ -38,14 +59,11 @@ export interface WorkspacePreviewProps {
export function WorkspacePreview(props: WorkspacePreviewProps) {
const {state, subtitle, selected, title, icon, iconRight} = props

const iconComponent = useMemo(() => createIcon(icon), [icon])
const iconRightComponent = useMemo(() => createIcon(iconRight), [iconRight])

return (
<Flex align="center" flex="none" gap={3}>
<MediaCard radius={2} tone="transparent">
{iconComponent}
</MediaCard>
<WorkspacePreviewIcon icon={icon} size="small" />

<Stack flex={1} space={2}>
<Text textOverflow="ellipsis" weight="medium">
Expand Down
36 changes: 22 additions & 14 deletions packages/sanity/src/ui/menuItem/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import {
} from '@sanity/ui'
import React, {createElement, forwardRef, isValidElement, useMemo} from 'react'
import {isValidElementType} from 'react-is'
import styled from 'styled-components'

interface LargeMenuItem {
size: 'large'
subText?: string
badgeText?: string
avatar?: React.ReactNode
preview?: React.ReactNode
/**
* Hotkeys are only supported in `size="small"` menu items.
*/
Expand All @@ -38,12 +39,12 @@ interface SmallMenuItem {
*/
badgeText?: undefined
/**
* Avatar is only supported in `size="large"` menu items.
* preview is only supported in `size="large"` menu items.
*/
avatar?: undefined
preview?: undefined
}

const fontSize = 1
const FONT_SIZE = 1

/** @internal */
export type MenuItemProps = Pick<
Expand All @@ -67,6 +68,13 @@ export type MenuItemProps = Pick<
children?: undefined
}

const PreviewWrapper = styled.div`
width: 41px;
height: 41px;
display: flex;
align-items: center;
justify-content: center;
`
/**
* Studio UI <MenuItem>.
*
Expand All @@ -81,7 +89,7 @@ export const MenuItem = forwardRef(function MenuItem(
badgeText,
subText,
text,
avatar = null,
preview = null,
icon,
iconRight,
hotkeys,
Expand All @@ -94,23 +102,23 @@ export const MenuItem = forwardRef(function MenuItem(
if (size === 'large') {
return (
<Flex gap={3} align="center">
{avatar}
{preview && <PreviewWrapper>{preview}</PreviewWrapper>}
{(text || subText) && (
<Stack flex={1} space={2}>
{text && (
<Text size={fontSize} textOverflow="ellipsis" weight="medium">
<Text size={FONT_SIZE} textOverflow="ellipsis" weight="medium">
{text}
</Text>
)}
{subText && (
<Text size={fontSize} textOverflow="ellipsis" weight={'regular'} muted>
<Text size={FONT_SIZE} textOverflow="ellipsis" weight={'regular'} muted>
{subText}
</Text>
)}
</Stack>
)}
{badgeText && (
<Badge fontSize={fontSize} mode="default">
<Badge fontSize={FONT_SIZE} mode="default">
{badgeText}
</Badge>
)}
Expand All @@ -121,33 +129,33 @@ export const MenuItem = forwardRef(function MenuItem(
return (
<Flex as="span" gap={3} align="center">
{icon && (
<Text size={fontSize}>
<Text size={FONT_SIZE}>
{isValidElement(icon) && icon}
{isValidElementType(icon) && createElement(icon)}
</Text>
)}

{text && (
<Box flex={1}>
<Text size={fontSize} textOverflow="ellipsis" weight="medium">
<Text size={FONT_SIZE} textOverflow="ellipsis" weight="medium">
{text}
</Text>
</Box>
)}

{hotkeys && (
<Hotkeys fontSize={fontSize} keys={hotkeys} style={{marginTop: -4, marginBottom: -4}} />
<Hotkeys fontSize={FONT_SIZE} keys={hotkeys} style={{marginTop: -4, marginBottom: -4}} />
)}

{iconRight && (
<Text size={fontSize}>
<Text size={FONT_SIZE}>
{isValidElement(iconRight) && iconRight}
{isValidElementType(iconRight) && createElement(iconRight)}
</Text>
)}
</Flex>
)
}, [size, icon, text, hotkeys, iconRight, avatar, subText, badgeText])
}, [size, icon, text, hotkeys, iconRight, preview, subText, badgeText])

return (
<UIMenuItem ref={ref} {...props}>
Expand Down

0 comments on commit a119ef0

Please sign in to comment.