mirror of
https://github.com/mastodon/mastodon.git
synced 2026-09-30 17:17:47 -05:00
Redesign: Update account menu trigger in main navigation (#40573)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import classNames from 'classnames';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { polymorphicForwardRef } from '@/types/polymorphic';
|
||||
import type { PolymorphicProps } from '@/types/polymorphic';
|
||||
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
@@ -43,66 +43,73 @@ interface ContentProps {
|
||||
subtitleId?: string;
|
||||
}
|
||||
|
||||
export const ListItemContent = polymorphicForwardRef<'h3', ContentProps>(
|
||||
(
|
||||
{ as: Component = 'h3', subtitle, subtitleId, children, ...otherProps },
|
||||
ref,
|
||||
) => {
|
||||
return (
|
||||
<>
|
||||
<Component className={classes.title} ref={ref} {...otherProps}>
|
||||
{children}
|
||||
</Component>
|
||||
{subtitle && (
|
||||
<div className={classes.subtitle} id={subtitleId}>
|
||||
{subtitle}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
},
|
||||
);
|
||||
export const ListItemContent = <As extends React.ElementType = 'h3'>({
|
||||
as,
|
||||
subtitle,
|
||||
subtitleId,
|
||||
children,
|
||||
...otherProps
|
||||
}: PolymorphicProps<ContentProps, As>) => {
|
||||
const Component = as ?? 'h3';
|
||||
return (
|
||||
<>
|
||||
<Component className={classes.title} {...otherProps}>
|
||||
{children}
|
||||
</Component>
|
||||
{subtitle && (
|
||||
<div className={classes.subtitle} id={subtitleId}>
|
||||
{subtitle}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
interface LinkProps
|
||||
extends React.ComponentPropsWithoutRef<typeof Link>, ContentProps {}
|
||||
|
||||
export const ListItemLink = polymorphicForwardRef<'h3', LinkProps>(
|
||||
({ as, subtitle, subtitleId, children, className, ...otherProps }, ref) => {
|
||||
return (
|
||||
<ListItemContent
|
||||
ref={ref}
|
||||
as={as}
|
||||
subtitle={subtitle}
|
||||
subtitleId={subtitleId}
|
||||
>
|
||||
<Link className={classNames(className, 'focusable')} {...otherProps}>
|
||||
{children}
|
||||
</Link>
|
||||
</ListItemContent>
|
||||
);
|
||||
},
|
||||
);
|
||||
export const ListItemLink = <As extends React.ElementType = 'h3'>({
|
||||
as,
|
||||
subtitle,
|
||||
subtitleId,
|
||||
children,
|
||||
className,
|
||||
...otherProps
|
||||
}: PolymorphicProps<LinkProps, As>) => {
|
||||
return (
|
||||
<ListItemContent
|
||||
as={as ?? 'h3'}
|
||||
subtitle={subtitle}
|
||||
subtitleId={subtitleId}
|
||||
>
|
||||
<Link className={classNames(className, 'focusable')} {...otherProps}>
|
||||
{children}
|
||||
</Link>
|
||||
</ListItemContent>
|
||||
);
|
||||
};
|
||||
|
||||
interface ButtonProps
|
||||
extends React.ComponentPropsWithoutRef<'button'>, ContentProps {}
|
||||
|
||||
export const ListItemButton = polymorphicForwardRef<'h3', ButtonProps>(
|
||||
({ as, subtitle, subtitleId, children, className, ...otherProps }, ref) => {
|
||||
return (
|
||||
<ListItemContent
|
||||
as={as}
|
||||
ref={ref}
|
||||
subtitle={subtitle}
|
||||
subtitleId={subtitleId}
|
||||
export const ListItemButton = <As extends React.ElementType = 'h3'>({
|
||||
as,
|
||||
subtitle,
|
||||
subtitleId,
|
||||
children,
|
||||
className,
|
||||
...otherProps
|
||||
}: PolymorphicProps<ButtonProps, As>) => {
|
||||
const Comp = as ?? 'h3';
|
||||
return (
|
||||
<ListItemContent as={Comp} subtitle={subtitle} subtitleId={subtitleId}>
|
||||
<button
|
||||
type='button'
|
||||
className={classNames(className, 'focusable')}
|
||||
{...otherProps}
|
||||
>
|
||||
<button
|
||||
type='button'
|
||||
className={classNames(className, 'focusable')}
|
||||
{...otherProps}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
</ListItemContent>
|
||||
);
|
||||
},
|
||||
);
|
||||
{children}
|
||||
</button>
|
||||
</ListItemContent>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@use '@/styles/mastodon/mixins';
|
||||
|
||||
.wrapper {
|
||||
--list-item-padding: 16px;
|
||||
--list-item-padding-block: var(--list-item-padding);
|
||||
@@ -20,7 +22,7 @@
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 500;
|
||||
@include mixins.type-label;
|
||||
|
||||
:any-link,
|
||||
button {
|
||||
@@ -44,7 +46,8 @@
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 13px;
|
||||
@include mixins.type-caption;
|
||||
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,39 @@
|
||||
.root {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--space-2);
|
||||
--list-item-padding: var(--space-2);
|
||||
--list-item-gap: var(--space-2);
|
||||
|
||||
border: 1px solid var(--color-border-primary);
|
||||
border-radius: var(--radius-3);
|
||||
transition: background-color 200ms;
|
||||
|
||||
& > :global(.account) {
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
|
||||
--account-outer-spacing: 0;
|
||||
--avatar-border-radius: var(--radius-round);
|
||||
--account-name-color: var(--color-text-primary);
|
||||
--account-name-size: var(--fs-14);
|
||||
--account-handle-color: var(--color-text-secondary);
|
||||
--account-handle-size: var(--fs-12);
|
||||
&:hover {
|
||||
background-color: var(--color-bg-highlight);
|
||||
}
|
||||
|
||||
& :global(.display-name) {
|
||||
// Allow display name to wrap instead of truncating with ellipsis
|
||||
white-space: normal;
|
||||
&:has(button:focus-visible) {
|
||||
outline: var(--outline-focus-default);
|
||||
background-color: var(--color-bg-highlight);
|
||||
}
|
||||
|
||||
// Disable default styles for LockupButton component
|
||||
& button {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dotsIcon {
|
||||
padding: var(--space-2);
|
||||
}
|
||||
|
||||
.profileMenuItem {
|
||||
--list-item-padding: 0;
|
||||
--list-item-gap: 8px;
|
||||
--list-item-gap: var(--space-2);
|
||||
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
@@ -17,12 +17,11 @@ import {
|
||||
} from '@phosphor-icons/react';
|
||||
|
||||
import { openModal } from '@/mastodon/actions/modal';
|
||||
import { Account } from '@/mastodon/components/account';
|
||||
import { Avatar } from '@/mastodon/components/avatar';
|
||||
import { IconButton } from '@/mastodon/components/button/redesign';
|
||||
import { DisplayName } from '@/mastodon/components/display_name';
|
||||
import { useAccountHandle } from '@/mastodon/components/display_name/default';
|
||||
import {
|
||||
ListItemButton,
|
||||
ListItemContent,
|
||||
ListItemWrapper,
|
||||
} from '@/mastodon/components/list_item';
|
||||
@@ -52,31 +51,41 @@ export const NavigationAccountCardAndMenu: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<Account
|
||||
id={accountId}
|
||||
minimal
|
||||
withBorder={false}
|
||||
withMenu={false}
|
||||
size={32}
|
||||
/>
|
||||
<Menu type='navigation'>
|
||||
<MenuTrigger
|
||||
as={IconButton}
|
||||
icon={DotsThreeIcon}
|
||||
variant='ghost'
|
||||
size='sm'
|
||||
>
|
||||
<FormattedMessage
|
||||
id='tabs_bar.account_settings'
|
||||
defaultMessage='Account settings'
|
||||
/>
|
||||
</MenuTrigger>
|
||||
<MenuList placement='top' offset={8} strategy='fixed'>
|
||||
<AccountMenuItems />
|
||||
</MenuList>
|
||||
</Menu>
|
||||
</div>
|
||||
<Menu type='navigation'>
|
||||
<MenuTrigger as={AccountMenuTrigger}>
|
||||
<FormattedMessage
|
||||
id='tabs_bar.account_settings'
|
||||
defaultMessage='Account settings'
|
||||
/>
|
||||
</MenuTrigger>
|
||||
<MenuList
|
||||
placement='top-start'
|
||||
offset={{ mainAxis: 12, crossAxis: -20 }}
|
||||
strategy='fixed'
|
||||
>
|
||||
<AccountMenuItems />
|
||||
</MenuList>
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
||||
const AccountMenuTrigger: React.FC<React.ComponentPropsWithoutRef<'button'>> = (
|
||||
props,
|
||||
) => {
|
||||
const { accountId } = useIdentity();
|
||||
const account = useAccount(accountId);
|
||||
const handle = useAccountHandle(account);
|
||||
|
||||
return (
|
||||
<ListItemWrapper
|
||||
icon={<Avatar account={account} size={32} />}
|
||||
sideContent={<DotsThreeIcon size={20} className={classes.dotsIcon} />}
|
||||
className={classes.root}
|
||||
>
|
||||
<ListItemButton {...props} subtitle={handle}>
|
||||
<DisplayName variant='simple' account={account} />
|
||||
</ListItemButton>
|
||||
</ListItemWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user