Add profile control at the bottom

merge-requests/3312/head
Alex Gleason 2025-01-24 23:22:35 -06:00
rodzic 4498130f23
commit f56dabe458
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
3 zmienionych plików z 112 dodań i 97 usunięć

Wyświetl plik

@ -23,11 +23,13 @@ import worldIcon from '@tabler/icons/outline/world.svg';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { Link } from 'react-router-dom';
import Account from 'soapbox/components/account.tsx';
import SiteLogo from 'soapbox/components/site-logo.tsx';
import Stack from 'soapbox/components/ui/stack.tsx';
import { useStatContext } from 'soapbox/contexts/stat-context.tsx';
import Search from 'soapbox/features/compose/components/search.tsx';
import ComposeButton from 'soapbox/features/ui/components/compose-button.tsx';
import ProfileDropdown from 'soapbox/features/ui/components/profile-dropdown.tsx';
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
import { useInstance } from 'soapbox/hooks/useInstance.ts';
@ -142,107 +144,119 @@ const SidebarNavigation = () => {
};
return (
<Stack space={6}>
<Link key='logo' to='/' data-preview-title-id='column.home' className='ml-4 flex shrink-0 items-center'>
<SiteLogo alt='Logo' className='h-10 w-auto cursor-pointer' />
<span className='hidden'><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></span>
</Link>
<Stack justifyContent='between' className='min-h-screen py-6'>
<Stack space={6}>
<Link key='logo' to='/' data-preview-title-id='column.home' className='ml-4 flex shrink-0 items-center'>
<SiteLogo alt='Logo' className='h-10 w-auto cursor-pointer' />
<span className='hidden'><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></span>
</Link>
<Search openInRoute autosuggest />
<Search openInRoute autosuggest />
<Stack space={2}>
<SidebarNavigationLink
to='/'
icon={homeIcon}
activeIcon={homeFilledIcon}
text={<FormattedMessage id='tabs_bar.home' defaultMessage='Home' />}
/>
<Stack space={2}>
<SidebarNavigationLink
to='/'
icon={homeIcon}
activeIcon={homeFilledIcon}
text={<FormattedMessage id='tabs_bar.home' defaultMessage='Home' />}
/>
<SidebarNavigationLink
to='/search'
icon={searchIcon}
text={<FormattedMessage id='tabs_bar.search' defaultMessage='Discover' />}
/>
<SidebarNavigationLink
to='/search'
icon={searchIcon}
text={<FormattedMessage id='tabs_bar.search' defaultMessage='Discover' />}
/>
{account && (
<>
<SidebarNavigationLink
to='/notifications'
icon={bellIcon}
activeIcon={bellFilledIcon}
count={notificationCount}
text={<FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' />}
/>
{renderMessagesLink()}
{features.groups && (
<SidebarNavigationLink
to='/groups'
icon={circlesIcon}
activeIcon={circlesFilledIcon}
text={<FormattedMessage id='tabs_bar.groups' defaultMessage='Groups' />}
/>
)}
<SidebarNavigationLink
to={`/@${account.acct}`}
icon={userIcon}
activeIcon={userFilledIcon}
text={<FormattedMessage id='tabs_bar.profile' defaultMessage='Profile' />}
/>
<SidebarNavigationLink
to='/settings'
icon={settingsIcon}
activeIcon={settingsFilledIcon}
text={<FormattedMessage id='tabs_bar.settings' defaultMessage='Settings' />}
count={settingsNotifications.size}
/>
{account.staff && (
<SidebarNavigationLink
to='/soapbox/admin'
icon={dashboardIcon}
count={dashboardCount}
text={<FormattedMessage id='tabs_bar.dashboard' defaultMessage='Dashboard' />}
/>
)}
</>
)}
{(features.publicTimeline) && (
<>
{(account || !restrictUnauth.timelines.local) && (
<SidebarNavigationLink
to='/timeline/local'
icon={features.federating ? atIcon : worldIcon}
text={features.federating ? instance.domain : <FormattedMessage id='tabs_bar.global' defaultMessage='Global' />}
/>
)}
{(features.federating && (account || !restrictUnauth.timelines.federated)) && (
<SidebarNavigationLink
to='/timeline/global'
icon={worldIcon}
text={<FormattedMessage id='tabs_bar.global' defaultMessage='Global' />}
/>
)}
</>
)}
{menu.length > 0 && (
<DropdownMenu items={menu} placement='top'>
<SidebarNavigationLink
icon={dotsCircleHorizontalIcon}
text={<FormattedMessage id='tabs_bar.more' defaultMessage='More' />}
/>
</DropdownMenu>
)}
</Stack>
{account && (
<>
<SidebarNavigationLink
to='/notifications'
icon={bellIcon}
activeIcon={bellFilledIcon}
count={notificationCount}
text={<FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' />}
/>
{renderMessagesLink()}
{features.groups && (
<SidebarNavigationLink
to='/groups'
icon={circlesIcon}
activeIcon={circlesFilledIcon}
text={<FormattedMessage id='tabs_bar.groups' defaultMessage='Groups' />}
/>
)}
<SidebarNavigationLink
to={`/@${account.acct}`}
icon={userIcon}
activeIcon={userFilledIcon}
text={<FormattedMessage id='tabs_bar.profile' defaultMessage='Profile' />}
/>
<SidebarNavigationLink
to='/settings'
icon={settingsIcon}
activeIcon={settingsFilledIcon}
text={<FormattedMessage id='tabs_bar.settings' defaultMessage='Settings' />}
count={settingsNotifications.size}
/>
{account.staff && (
<SidebarNavigationLink
to='/soapbox/admin'
icon={dashboardIcon}
count={dashboardCount}
text={<FormattedMessage id='tabs_bar.dashboard' defaultMessage='Dashboard' />}
/>
)}
</>
)}
{(features.publicTimeline) && (
<>
{(account || !restrictUnauth.timelines.local) && (
<SidebarNavigationLink
to='/timeline/local'
icon={features.federating ? atIcon : worldIcon}
text={features.federating ? instance.domain : <FormattedMessage id='tabs_bar.global' defaultMessage='Global' />}
/>
)}
{(features.federating && (account || !restrictUnauth.timelines.federated)) && (
<SidebarNavigationLink
to='/timeline/global'
icon={worldIcon}
text={<FormattedMessage id='tabs_bar.global' defaultMessage='Global' />}
/>
)}
</>
)}
{menu.length > 0 && (
<DropdownMenu items={menu} placement='top'>
<SidebarNavigationLink
icon={dotsCircleHorizontalIcon}
text={<FormattedMessage id='tabs_bar.more' defaultMessage='More' />}
/>
</DropdownMenu>
<ComposeButton />
)}
</Stack>
{account && (
<ComposeButton />
<div className='mt-12'>
<ProfileDropdown account={account} placement='top'>
<div className='w-full p-2'>
<Account account={account} showProfileHoverCard={false} withLinkToProfile={false} hideActions />
</div>
</ProfileDropdown>
</div>
)}
</Stack>
);

Wyświetl plik

@ -31,7 +31,7 @@ const Layout: LayoutComponent = ({ children }) => (
/** Left sidebar container in the UI. */
const Sidebar: React.FC<ISidebar> = ({ children }) => (
<div className='hidden lg:col-span-3 lg:block'>
<StickyBox className='py-6'>
<StickyBox>
{children}
</StickyBox>
</div>

Wyświetl plik

@ -1,4 +1,4 @@
import { useFloating } from '@floating-ui/react';
import { Placement, useFloating } from '@floating-ui/react';
import logoutIcon from '@tabler/icons/outline/logout.svg';
import plusIcon from '@tabler/icons/outline/plus.svg';
import clsx from 'clsx';
@ -29,6 +29,7 @@ const messages = defineMessages({
interface IProfileDropdown {
account: AccountEntity;
children: React.ReactNode;
placement?: Placement;
}
type IMenuItem = {
@ -39,13 +40,13 @@ type IMenuItem = {
action?: (event: React.MouseEvent) => void;
}
const ProfileDropdown: React.FC<IProfileDropdown> = ({ account, children }) => {
const ProfileDropdown: React.FC<IProfileDropdown> = ({ account, children, placement = 'bottom-end' }) => {
const dispatch = useAppDispatch();
const features = useFeatures();
const intl = useIntl();
const [visible, setVisible] = useState(false);
const { x, y, strategy, refs } = useFloating<HTMLButtonElement>({ placement: 'bottom-end' });
const { x, y, strategy, refs } = useFloating<HTMLButtonElement>({ placement });
const getOtherAccounts = useCallback(makeGetOtherAccounts(), []);
const otherAccounts = useAppSelector((state) => getOtherAccounts(state));
@ -117,7 +118,7 @@ const ProfileDropdown: React.FC<IProfileDropdown> = ({ account, children }) => {
return (
<>
<button
className='rounded-full focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 dark:ring-gray-800 dark:ring-offset-0 dark:focus:ring-primary-500'
className='w-full rounded-full focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 dark:ring-gray-800 dark:ring-offset-0 dark:focus:ring-primary-500'
type='button'
ref={refs.setReference}
onClick={toggleVisible}