Skip to content
2 changes: 1 addition & 1 deletion apps/studio/src/components/tests/topbar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ describe( 'TopBar', () => {
it( 'shows offline indicator', async () => {
vi.mocked( useOffline ).mockReturnValue( true );
await act( async () => renderWithProvider( <TopBar onToggleSidebar={ vi.fn() } /> ) );
const offlineIndicator = screen.getByRole( 'button', {
const offlineIndicator = screen.getByRole( 'status', {
name: 'Offline indicator',
} );
expect( offlineIndicator ).toHaveAttribute( 'aria-description' );
Expand Down
96 changes: 63 additions & 33 deletions apps/studio/src/components/top-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { sprintf } from '@wordpress/i18n';
import { Icon, help, drawerLeft, cog } from '@wordpress/icons';
import { useI18n } from '@wordpress/react-i18n';
import Button from 'src/components/button';
Expand All @@ -8,6 +7,7 @@ import { Tooltip } from 'src/components/tooltip';
import { WordPressLogo } from 'src/components/wordpress-logo';
import { useAuth } from 'src/hooks/use-auth';
import { useOffline } from 'src/hooks/use-offline';
import { useSiteDetails } from 'src/hooks/use-site-details';
import { getIpcApi } from 'src/lib/get-ipc-api';
import { getLocalizedLink } from 'src/lib/get-localized-link';
import { useI18nLocale } from 'src/stores';
Expand All @@ -20,13 +20,14 @@ const DEFAULT_TOOLTIP_PLACEMENT = 'bottom-start';
function ToggleSidebar( { onToggleSidebar }: TopBarProps ) {
const { __ } = useI18n();
return (
<div className="app-no-drag-region">
<Tooltip
text={ __( 'Toggle sidebar' ) }
className="h-6"
placement={ DEFAULT_TOOLTIP_PLACEMENT }
>
<Button onClick={ onToggleSidebar } variant="icon" aria-label={ __( 'Toggle sidebar' ) }>
<div className="app-no-drag-region ml-2">
<Tooltip text={ __( 'Toggle sidebar' ) } placement={ DEFAULT_TOOLTIP_PLACEMENT }>
<Button
onClick={ onToggleSidebar }
variant="icon"
aria-label={ __( 'Toggle sidebar' ) }
className="!p-1.5 !rounded-lg"
>
<Icon className="text-white" icon={ drawerLeft } size={ 24 } />
</Button>
</Tooltip>
Expand Down Expand Up @@ -55,14 +56,14 @@ function OfflineIndicator() {
className="h-6"
placement={ DEFAULT_TOOLTIP_PLACEMENT }
>
<Button
<span
role="status"
aria-label={ __( 'Offline indicator' ) }
aria-description={ offlineMessage.join( ' ' ) }
className="cursor-default !w-6 !h-6"
variant="icon"
className="inline-flex items-center justify-center w-6 h-6"
>
<Icon className="text-white" size={ 18 } icon={ offlineIcon } />
</Button>
<Icon className="text-white fill-white" size={ 18 } icon={ offlineIcon } />
</span>
</Tooltip>
</div>
)
Expand All @@ -75,15 +76,16 @@ function Authentication() {
const isOffline = useOffline();
if ( isAuthenticated ) {
return (
<Button
onClick={ () => getIpcApi().showUserSettings() }
aria-label={ __( 'Open account settings' ) }
variant="icon"
className="text-white hover:!text-white !px-1 py-1 !h-6 gap-2"
>
<span>{ sprintf( __( 'Howdy, %s' ), user?.displayName || '' ) }</span>{ ' ' }
<Gravatar size={ 18 } className="border-white border-[1.5px]" />
</Button>
<Tooltip text={ user?.displayName || '' } placement="bottom-end">
<Button
onClick={ () => getIpcApi().showUserSettings() }
aria-label={ __( 'Open account settings' ) }
variant="icon"
className="!p-1.5 !rounded-lg"
>
<Gravatar size={ 20 } className="border-white border-[1.5px]" />
</Button>
</Tooltip>
);
}

Expand All @@ -110,14 +112,35 @@ function Authentication() {
function SettingsButton() {
const { __ } = useI18n();
return (
<Button
onClick={ () => getIpcApi().showUserSettings( 'preferences' ) }
aria-label={ __( 'Open settings' ) }
variant="icon"
data-testid="settings-button"
>
<Icon className="text-white" size={ 24 } icon={ cog } />
</Button>
<Tooltip text={ __( 'Settings' ) } placement="bottom-end">
<Button
onClick={ () => getIpcApi().showUserSettings( 'preferences' ) }
aria-label={ __( 'Open settings' ) }
variant="icon"
className="!p-1.5 !rounded-lg"
data-testid="settings-button"
>
<Icon className="text-white" size={ 24 } icon={ cog } />
</Button>
</Tooltip>
);
}

function WindowTitle() {
const { __ } = useI18n();
const { selectedSite } = useSiteDetails();
return (
<div className="fixed top-0 left-0 right-0 h-[52px] flex items-center justify-center pointer-events-none">
<span className="text-[13px] truncate max-w-[50%]">
<span className="text-white/50 font-light">{ __( 'Studio' ) }</span>
{ selectedSite && (
<>
<span className="text-white/30 mx-2.5">{ '\u2022' }</span>
<span className="text-white">{ selectedSite.name }</span>
</>
) }
</span>
</div>
);
}

Expand All @@ -130,17 +153,24 @@ export default function TopBar( { onToggleSidebar }: TopBarProps ) {
};

return (
<div className="flex justify-between items-center text-white px-2 pb-2 pt-1.5">
<div className="flex justify-between items-center text-white pl-2 pr-0.5 pb-2">
<div className="flex items-center space-x-1.5 rtl:space-x-reverse">
<ToggleSidebar onToggleSidebar={ onToggleSidebar } />
<OfflineIndicator />
</div>

<WindowTitle />

<div className="app-no-drag-region flex items-center space-x-1.5 rtl:space-x-reverse">
<Authentication />
<SettingsButton />
<Tooltip text={ __( 'Get help' ) } placement="bottom-start">
<Button onClick={ openDocs } aria-label={ __( 'Get help' ) } variant="icon">
<Tooltip text={ __( 'Get help' ) } placement="bottom-end">
<Button
onClick={ openDocs }
aria-label={ __( 'Get help' ) }
variant="icon"
className="!p-1.5 !rounded-lg"
>
<Icon className="text-white" size={ 24 } icon={ help } />
</Button>
</Tooltip>
Expand Down