Make sure sidebar toggle is rendered only when the sidebar exists

This commit is contained in:
Alejandro Celaya 2025-08-13 10:06:45 +02:00
parent df3ee490a9
commit d762ae1e39
5 changed files with 29 additions and 22 deletions

View File

@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### Fixed ### Fixed
* [#1637](https://github.com/shlinkio/shlink-web-client/issues/1637) Fix brand color used in PWA * [#1637](https://github.com/shlinkio/shlink-web-client/issues/1637) Fix brand color used in PWA
* [#1636](https://github.com/shlinkio/shlink-web-client/issues/1636) Make sure sidebar toggle is rendered only in sections where the sidebar exists.
## [4.5.0] - 2025-08-08 ## [4.5.0] - 2025-08-08

View File

@ -1,5 +1,4 @@
import { changeThemeInMarkup, getSystemPreferredTheme } from '@shlinkio/shlink-frontend-kit'; import { changeThemeInMarkup, getSystemPreferredTheme } from '@shlinkio/shlink-frontend-kit';
import { ShlinkSidebarToggleButton, ShlinkSidebarVisibilityProvider } from '@shlinkio/shlink-web-component';
import type { Settings } from '@shlinkio/shlink-web-component/settings'; import type { Settings } from '@shlinkio/shlink-web-component/settings';
import { clsx } from 'clsx'; import { clsx } from 'clsx';
import type { FC } from 'react'; import type { FC } from 'react';
@ -63,8 +62,7 @@ const App: FCWithDeps<AppProps, AppDeps> = (
return ( return (
<div className="h-full"> <div className="h-full">
<ShlinkSidebarVisibilityProvider> <>
<ShlinkSidebarToggleButton className="fixed top-3.5 left-3 z-901" />
<MainHeader /> <MainHeader />
<div className="h-full pt-(--header-height)"> <div className="h-full pt-(--header-height)">
@ -94,7 +92,7 @@ const App: FCWithDeps<AppProps, AppDeps> = (
<ShlinkVersionsContainer /> <ShlinkVersionsContainer />
</div> </div>
</div> </div>
</ShlinkSidebarVisibilityProvider> </>
<AppUpdateBanner isOpen={appUpdated} onClose={resetAppUpdate} forceUpdate={forceUpdate} /> <AppUpdateBanner isOpen={appUpdated} onClose={resetAppUpdate} forceUpdate={forceUpdate} />
</div> </div>

View File

@ -1,4 +1,9 @@
import type { ShlinkWebComponentProps, TagColorsStorage } from '@shlinkio/shlink-web-component'; import type { TagColorsStorage } from '@shlinkio/shlink-web-component';
import {
ShlinkSidebarToggleButton,
ShlinkSidebarVisibilityProvider,
ShlinkWebComponent,
} from '@shlinkio/shlink-web-component';
import type { Settings } from '@shlinkio/shlink-web-component/settings'; import type { Settings } from '@shlinkio/shlink-web-component/settings';
import type { FC } from 'react'; import type { FC } from 'react';
import { memo } from 'react'; import { memo } from 'react';
@ -17,7 +22,6 @@ type ShlinkWebComponentContainerProps = WithSelectedServerProps & {
type ShlinkWebComponentContainerDeps = { type ShlinkWebComponentContainerDeps = {
buildShlinkApiClient: ShlinkApiClientBuilder, buildShlinkApiClient: ShlinkApiClientBuilder,
TagColorsStorage: TagColorsStorage, TagColorsStorage: TagColorsStorage,
ShlinkWebComponent: FC<ShlinkWebComponentProps>,
ServerError: FC, ServerError: FC,
}; };
@ -32,7 +36,6 @@ const ShlinkWebComponentContainer: FCWithDeps<
const { const {
buildShlinkApiClient, buildShlinkApiClient,
TagColorsStorage: tagColorsStorage, TagColorsStorage: tagColorsStorage,
ShlinkWebComponent,
ServerError, ServerError,
} = useDependencies(ShlinkWebComponentContainer); } = useDependencies(ShlinkWebComponentContainer);
@ -42,23 +45,25 @@ const ShlinkWebComponentContainer: FCWithDeps<
const routesPrefix = `/server/${selectedServer.id}`; const routesPrefix = `/server/${selectedServer.id}`;
return ( return (
<ShlinkSidebarVisibilityProvider>
<ShlinkSidebarToggleButton className="fixed top-3.5 left-3 z-901" />
<ShlinkWebComponent <ShlinkWebComponent
serverVersion={selectedServer.version} serverVersion={selectedServer.version}
apiClient={buildShlinkApiClient(selectedServer)} apiClient={buildShlinkApiClient(selectedServer)}
settings={settings} settings={settings}
routesPrefix={routesPrefix} routesPrefix={routesPrefix}
tagColorsStorage={tagColorsStorage} tagColorsStorage={tagColorsStorage}
createNotFound={(nonPrefixedHomePath) => ( createNotFound={(nonPrefixedHomePath: string) => (
<NotFound to={`${routesPrefix}${nonPrefixedHomePath}`}>List short URLs</NotFound> <NotFound to={`${routesPrefix}${nonPrefixedHomePath}`}>List short URLs</NotFound>
)} )}
autoSidebarToggle={false} autoSidebarToggle={false}
/> />
</ShlinkSidebarVisibilityProvider>
); );
})); }));
export const ShlinkWebComponentContainerFactory = componentFactory(ShlinkWebComponentContainer, [ export const ShlinkWebComponentContainerFactory = componentFactory(ShlinkWebComponentContainer, [
'buildShlinkApiClient', 'buildShlinkApiClient',
'TagColorsStorage', 'TagColorsStorage',
'ShlinkWebComponent',
'ServerError', 'ServerError',
]); ]);

View File

@ -1,5 +1,4 @@
import { FetchHttpClient } from '@shlinkio/shlink-js-sdk/fetch'; import { FetchHttpClient } from '@shlinkio/shlink-js-sdk/fetch';
import { ShlinkWebComponent } from '@shlinkio/shlink-web-component';
import type Bottle from 'bottlejs'; import type Bottle from 'bottlejs';
import type { ConnectDecorator } from '../../container/types'; import type { ConnectDecorator } from '../../container/types';
import { withoutSelectedServer } from '../../servers/helpers/withoutSelectedServer'; import { withoutSelectedServer } from '../../servers/helpers/withoutSelectedServer';
@ -26,7 +25,6 @@ export const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
bottle.decorator('Home', withoutSelectedServer); bottle.decorator('Home', withoutSelectedServer);
bottle.decorator('Home', connect(['servers'], ['resetSelectedServer'])); bottle.decorator('Home', connect(['servers'], ['resetSelectedServer']));
bottle.serviceFactory('ShlinkWebComponent', () => ShlinkWebComponent);
bottle.factory('ShlinkWebComponentContainer', ShlinkWebComponentContainerFactory); bottle.factory('ShlinkWebComponentContainer', ShlinkWebComponentContainerFactory);
bottle.decorator('ShlinkWebComponentContainer', connect(['selectedServer', 'settings'], ['selectServer'])); bottle.decorator('ShlinkWebComponentContainer', connect(['selectedServer', 'settings'], ['selectServer']));

View File

@ -5,11 +5,16 @@ import type { NonReachableServer, NotFoundServer, SelectedServer } from '../../s
import { checkAccessibility } from '../__helpers__/accessibility'; import { checkAccessibility } from '../__helpers__/accessibility';
import { MemoryRouterWithParams } from '../__helpers__/MemoryRouterWithParams'; import { MemoryRouterWithParams } from '../__helpers__/MemoryRouterWithParams';
vi.mock('@shlinkio/shlink-web-component', () => ({
ShlinkSidebarVisibilityProvider: ({ children }: any) => children,
ShlinkSidebarToggleButton: ({ children }: any) => children,
ShlinkWebComponent: () => <>ShlinkWebComponent</>,
}));
describe('<ShlinkWebComponentContainer />', () => { describe('<ShlinkWebComponentContainer />', () => {
const ShlinkWebComponentContainer = ShlinkWebComponentContainerFactory(fromPartial({ const ShlinkWebComponentContainer = ShlinkWebComponentContainerFactory(fromPartial({
buildShlinkApiClient: vi.fn().mockReturnValue(fromPartial({})), buildShlinkApiClient: vi.fn().mockReturnValue(fromPartial({})),
TagColorsStorage: fromPartial({}), TagColorsStorage: fromPartial({}),
ShlinkWebComponent: () => <>ShlinkWebComponent</>,
ServerError: () => <>ServerError</>, ServerError: () => <>ServerError</>,
})); }));
const setUp = (selectedServer: SelectedServer) => render( const setUp = (selectedServer: SelectedServer) => render(