mirror of
https://github.com/mastodon/mastodon.git
synced 2026-10-20 05:24:33 -05:00
Redesign: Update main navigation footer design (#40795)
This commit is contained in:
@@ -6,19 +6,19 @@
|
||||
border-radius: var(--radius-3);
|
||||
transition: background-color 200ms;
|
||||
|
||||
&:hover {
|
||||
&:has(a:hover) {
|
||||
background-color: var(--color-bg-highlight);
|
||||
}
|
||||
|
||||
&:has(button:focus-visible) {
|
||||
&:has(a:focus-visible) {
|
||||
outline: var(--outline-focus-default);
|
||||
background-color: var(--color-bg-highlight);
|
||||
}
|
||||
|
||||
// Disable default styles for LockupButton component
|
||||
& button {
|
||||
// Disable default hover & focus styles for LockupLink
|
||||
& a {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
|
||||
@@ -14,27 +14,32 @@ import {
|
||||
GavelIcon,
|
||||
ShieldStarIcon,
|
||||
SignOutIcon,
|
||||
MastodonLogoIcon,
|
||||
GithubLogoIcon,
|
||||
} from '@phosphor-icons/react';
|
||||
|
||||
import { openModal } from '@/mastodon/actions/modal';
|
||||
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 {
|
||||
LockupButton,
|
||||
LockupContent,
|
||||
LockupLink,
|
||||
LockupWrapper,
|
||||
} from '@/mastodon/components/lockup';
|
||||
import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
MenuItemDivider,
|
||||
MenuItemGroup,
|
||||
MenuItemLink,
|
||||
MenuList,
|
||||
MenuTrigger,
|
||||
} from '@/mastodon/components/menu';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useIdentity } from '@/mastodon/identity_context';
|
||||
import { source_url, version } from '@/mastodon/initial_state';
|
||||
import {
|
||||
canManageReports,
|
||||
canViewAdminDashboard,
|
||||
@@ -45,46 +50,35 @@ import classes from './account_card_and_menu.module.scss';
|
||||
|
||||
export const NavigationAccountCardAndMenu: React.FC = () => {
|
||||
const { accountId } = useIdentity();
|
||||
const account = useAccount(accountId);
|
||||
const handle = useAccountHandle(account);
|
||||
const accountBasePath = `/@${account?.acct}`;
|
||||
|
||||
if (!accountId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<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 (
|
||||
<LockupWrapper
|
||||
icon={<Avatar account={account} size={32} />}
|
||||
sideContent={<DotsThreeIcon size={20} className={classes.dotsIcon} />}
|
||||
sideContent={
|
||||
<Menu type='navigation'>
|
||||
<MenuTrigger as={IconButton} icon={DotsThreeIcon} size='sm'>
|
||||
<FormattedMessage
|
||||
id='tabs_bar.account_settings'
|
||||
defaultMessage='Account settings'
|
||||
/>
|
||||
</MenuTrigger>
|
||||
<MenuList placement='top' offset={12} strategy='fixed'>
|
||||
<AccountMenuItems />
|
||||
</MenuList>
|
||||
</Menu>
|
||||
}
|
||||
className={classes.root}
|
||||
>
|
||||
<LockupButton {...props} subtitle={handle}>
|
||||
<LockupLink to={accountBasePath} subtitle={handle}>
|
||||
<DisplayName variant='simple' account={account} />
|
||||
</LockupButton>
|
||||
</LockupLink>
|
||||
</LockupWrapper>
|
||||
);
|
||||
};
|
||||
@@ -194,6 +188,24 @@ export const AccountMenuItems: React.FC<{
|
||||
|
||||
<MenuItemDivider />
|
||||
|
||||
<MenuItemGroup label={`Mastodon v${version}`}>
|
||||
<MenuItemLink as='a' href={source_url} icon={GithubLogoIcon}>
|
||||
<FormattedMessage
|
||||
id='navigation_bar.source_code'
|
||||
defaultMessage='Source Code'
|
||||
/>
|
||||
</MenuItemLink>
|
||||
|
||||
<MenuItemLink as='a' href='/blocks' icon={MastodonLogoIcon}>
|
||||
<FormattedMessage
|
||||
id='navigation_bar.about_mastodon'
|
||||
defaultMessage='About Mastodon'
|
||||
/>
|
||||
</MenuItemLink>
|
||||
</MenuItemGroup>
|
||||
|
||||
<MenuItemDivider />
|
||||
|
||||
<MenuItem onClick={confirmLogout} icon={SignOutIcon}>
|
||||
<FormattedMessage
|
||||
id='navigation_bar.sign_out'
|
||||
|
||||
@@ -2,26 +2,15 @@
|
||||
|
||||
.root {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: var(--space-2);
|
||||
margin-top: var(--space-6);
|
||||
margin-top: var(--space-4);
|
||||
color: var(--color-text-secondary);
|
||||
|
||||
@include mixins.type-caption;
|
||||
}
|
||||
|
||||
.heading {
|
||||
margin-inline-end: auto;
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
gap: var(--space-2);
|
||||
|
||||
a {
|
||||
color: var(--color-text-secondary);
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
|
||||
&[aria-current='page'] {
|
||||
@@ -36,3 +25,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
@@ -2,14 +2,20 @@ import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
import { domain, termsOfServiceEnabled } from '@/mastodon/initial_state';
|
||||
import {
|
||||
statusPageUrl,
|
||||
termsOfServiceEnabled,
|
||||
profile_directory as canViewProfileDirectory,
|
||||
version,
|
||||
source_url,
|
||||
} from '@/mastodon/initial_state';
|
||||
|
||||
import classes from './footer_links.module.scss';
|
||||
|
||||
export const NavigationFooterLinks: React.FC<{
|
||||
siteName?: string;
|
||||
multiColumn?: boolean;
|
||||
}> = ({ siteName = domain, multiColumn }) => {
|
||||
withVersionInfo?: boolean;
|
||||
}> = ({ multiColumn, withVersionInfo }) => {
|
||||
const multiColumnLinkAttrs = multiColumn
|
||||
? {
|
||||
target: '_blank',
|
||||
@@ -18,7 +24,6 @@ export const NavigationFooterLinks: React.FC<{
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<h2 className={classes.heading}>{siteName}</h2>
|
||||
<ul className={classes.list}>
|
||||
<li>
|
||||
<NavLink to='/about' {...multiColumnLinkAttrs}>
|
||||
@@ -28,18 +33,6 @@ export const NavigationFooterLinks: React.FC<{
|
||||
/>
|
||||
</NavLink>
|
||||
</li>
|
||||
<li>
|
||||
<NavLink
|
||||
to='/privacy-policy'
|
||||
rel='privacy-policy'
|
||||
{...multiColumnLinkAttrs}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='footer.privacy_policy_short'
|
||||
defaultMessage='Privacy'
|
||||
/>
|
||||
</NavLink>
|
||||
</li>
|
||||
{termsOfServiceEnabled && (
|
||||
<li>
|
||||
<NavLink
|
||||
@@ -54,7 +47,47 @@ export const NavigationFooterLinks: React.FC<{
|
||||
</NavLink>
|
||||
</li>
|
||||
)}
|
||||
<li>
|
||||
<NavLink
|
||||
to='/privacy-policy'
|
||||
rel='privacy-policy'
|
||||
{...multiColumnLinkAttrs}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='footer.privacy_policy_short'
|
||||
defaultMessage='Privacy'
|
||||
/>
|
||||
</NavLink>
|
||||
</li>
|
||||
{statusPageUrl && (
|
||||
<li>
|
||||
<a href={statusPageUrl} target='_blank' rel='noopener'>
|
||||
<FormattedMessage id='footer.status' defaultMessage='Status' />
|
||||
</a>
|
||||
</li>
|
||||
)}
|
||||
{canViewProfileDirectory && (
|
||||
<li>
|
||||
<NavLink to='/directory'>
|
||||
<FormattedMessage
|
||||
id='footer.directory_short'
|
||||
defaultMessage='Directory'
|
||||
/>
|
||||
</NavLink>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
{withVersionInfo && (
|
||||
<p>
|
||||
{`Mastodon v${version} `}
|
||||
<a href={source_url} rel='noopener' target='_blank'>
|
||||
<FormattedMessage
|
||||
id='footer.source_code'
|
||||
defaultMessage='View source code'
|
||||
/>
|
||||
</a>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -294,10 +294,7 @@ export const RedesignNavigationPanel: React.FC<{
|
||||
<NavigationAccountCardAndMenu />
|
||||
</>
|
||||
)}
|
||||
<NavigationFooterLinks
|
||||
multiColumn={multiColumn}
|
||||
siteName={siteName}
|
||||
/>
|
||||
<NavigationFooterLinks multiColumn={multiColumn} />
|
||||
</footer>
|
||||
</>
|
||||
)}
|
||||
@@ -315,10 +312,7 @@ export const RedesignNavigationPanel: React.FC<{
|
||||
</ul>
|
||||
<footer className={classes.footer} data-stuck={!isScrolledToBottom}>
|
||||
{disabledAccountId ? <DisabledAccountBanner /> : <LoggedOutInfo />}
|
||||
<NavigationFooterLinks
|
||||
multiColumn={multiColumn}
|
||||
siteName={siteName}
|
||||
/>
|
||||
<NavigationFooterLinks withVersionInfo multiColumn={multiColumn} />
|
||||
</footer>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -866,6 +866,7 @@
|
||||
"footer.about_server": "About {domain}",
|
||||
"footer.about_this_server": "About",
|
||||
"footer.directory": "Profiles directory",
|
||||
"footer.directory_short": "Directory",
|
||||
"footer.get_app": "Get the app",
|
||||
"footer.keyboard_shortcuts": "Keyboard shortcuts",
|
||||
"footer.privacy_policy": "Privacy policy",
|
||||
@@ -1038,6 +1039,7 @@
|
||||
"mute_modal.you_wont_see_mentions": "You won't see posts that mention them.",
|
||||
"mute_modal.you_wont_see_posts": "They can still see your posts, but you won't see theirs.",
|
||||
"navigation_bar.about": "About",
|
||||
"navigation_bar.about_mastodon": "About Mastodon",
|
||||
"navigation_bar.account_settings": "Password and security",
|
||||
"navigation_bar.administration": "Administration",
|
||||
"navigation_bar.advanced_interface": "Open in advanced web interface",
|
||||
@@ -1073,6 +1075,7 @@
|
||||
"navigation_bar.search": "Search",
|
||||
"navigation_bar.search_trends": "Search / Trending",
|
||||
"navigation_bar.sign_out": "Sign Out",
|
||||
"navigation_bar.source_code": "Source Code",
|
||||
"navigation_panel.collapse_followed_tags": "Collapse followed hashtags menu",
|
||||
"navigation_panel.collapse_lists": "Collapse list menu",
|
||||
"navigation_panel.expand_followed_tags": "Expand followed hashtags menu",
|
||||
|
||||
Reference in New Issue
Block a user