From bb7fd43e3b330d817ae768be6053cf0499de8dd1 Mon Sep 17 00:00:00 2001 From: Lizaveta Miasayedava Date: Fri, 5 Jun 2026 16:18:11 +0200 Subject: [PATCH 1/3] fix: align scroll behavior across widget pages and playgrounds --- .../widget-playground-next/src/app/layout.tsx | 2 +- packages/widget-playground-vite/src/index.css | 4 ++ .../src/hooks/usePlaygroundLayoutControls.ts | 6 +- packages/widget/src/pages/LanguagesPage.tsx | 59 ++++++++++------- .../src/pages/RoutesPage/RoutesPage.tsx | 65 +++++++++++-------- 5 files changed, 81 insertions(+), 55 deletions(-) diff --git a/packages/widget-playground-next/src/app/layout.tsx b/packages/widget-playground-next/src/app/layout.tsx index a1312ed1c..d8696252c 100644 --- a/packages/widget-playground-next/src/app/layout.tsx +++ b/packages/widget-playground-next/src/app/layout.tsx @@ -51,7 +51,7 @@ export default function RootLayout({ children: React.ReactNode }>) { return ( - + { const { container } = useConfigContainer() const { variant } = useConfigVariant() - const { showMockHeader } = useHeaderAndFooterToolValues() const { setHeader, setContainer, getCurrentConfigTheme, setVariant } = useConfigActions() const { selectedLayoutId } = useLayoutValues() @@ -83,7 +81,7 @@ export const usePlaygroundLayoutControls = (): { setHeader({ position: 'fixed', - top: showMockHeader ? 48 : 0, + top: 0, }) const fullHeightContainer = { @@ -111,7 +109,7 @@ export const usePlaygroundLayoutControls = (): { } } }, - [getCurrentConfigTheme, setContainer, setHeader, setVariant, showMockHeader] + [getCurrentConfigTheme, setContainer, setHeader, setVariant] ) return { diff --git a/packages/widget/src/pages/LanguagesPage.tsx b/packages/widget/src/pages/LanguagesPage.tsx index 2ec0405c9..35226e77d 100644 --- a/packages/widget/src/pages/LanguagesPage.tsx +++ b/packages/widget/src/pages/LanguagesPage.tsx @@ -1,49 +1,62 @@ import Check from '@mui/icons-material/Check' -import { List } from '@mui/material' +import { Box, List } from '@mui/material' +import { useRef } from 'react' import { useTranslation } from 'react-i18next' import { ListItemText } from '../components/ListItemText.js' import { PageContainer } from '../components/PageContainer.js' import { SettingsListItemButton } from '../components/SettingsListItemButton.js' import { useHeader } from '../hooks/useHeader.js' import { useLanguages } from '../hooks/useLanguages.js' +import { useListHeight } from '../hooks/useListHeight.js' import { languageNames } from '../providers/I18nProvider/constants.js' export const LanguagesPage: React.FC = () => { const { t } = useTranslation() + const listParentRef = useRef(null) const { selectedLanguageCode, availableLanguages, setLanguageWithCode } = useLanguages() useHeader(t('language.title')) + const { listHeight } = useListHeight({ + listParentRef, + }) + if (availableLanguages.length < 1) { return null } return ( - - {availableLanguages.map((language) => ( - setLanguageWithCode(language)} - > - - {selectedLanguageCode === language && } - - ))} - + + {availableLanguages.map((language) => ( + setLanguageWithCode(language)} + > + + {selectedLanguageCode === language && } + + ))} + + ) } diff --git a/packages/widget/src/pages/RoutesPage/RoutesPage.tsx b/packages/widget/src/pages/RoutesPage/RoutesPage.tsx index 288385641..86e134c16 100644 --- a/packages/widget/src/pages/RoutesPage/RoutesPage.tsx +++ b/packages/widget/src/pages/RoutesPage/RoutesPage.tsx @@ -1,13 +1,16 @@ import type { Route } from '@lifi/sdk' import { useAccount } from '@lifi/wallet-management' +import { Box } from '@mui/material' import { useNavigate } from '@tanstack/react-router' -import { type JSX, useMemo } from 'react' +import { type JSX, useMemo, useRef } from 'react' import { useTranslation } from 'react-i18next' +import { PageContainer } from '../../components/PageContainer.js' import { ProgressToNextUpdate } from '../../components/ProgressToNextUpdate.js' import { RouteCard } from '../../components/RouteCard/RouteCard.js' import { RouteCardSkeleton } from '../../components/RouteCard/RouteCardSkeleton.js' import { RouteNotFoundCard } from '../../components/RouteCard/RouteNotFoundCard.js' import { useHeader } from '../../hooks/useHeader.js' +import { useListHeight } from '../../hooks/useListHeight.js' import { useRoutes } from '../../hooks/useRoutes.js' import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js' import { useWidgetEvents } from '../../hooks/useWidgetEvents.js' @@ -20,6 +23,7 @@ export const RoutesPage = (): JSX.Element => { const { t } = useTranslation() const navigate = useNavigate() const emitter = useWidgetEvents() + const listParentRef = useRef(null) const { routes, isLoading, @@ -50,6 +54,10 @@ export const RoutesPage = (): JSX.Element => { useHeader(t('header.receive'), headerAction) + const { listHeight } = useListHeight({ + listParentRef, + }) + const handleRouteClick = (route: Route) => { setReviewableRoute(route) navigate({ @@ -69,31 +77,34 @@ export const RoutesPage = (): JSX.Element => { const allowInteraction = account.isConnected && !toAddressUnsatisfied return ( - - {routeNotFound ? ( - - ) : isLoading && !routes?.length ? ( - Array.from({ length: 3 }).map((_, index) => ( - - )) - ) : ( - routes?.map((route: Route, index: number) => ( - handleRouteClick(route) : undefined - } - active={index === 0} - expanded={routes?.length === 1} - /> - )) - )} - + + + + {routeNotFound ? ( + + ) : isLoading && !routes?.length ? ( + Array.from({ length: 3 }).map((_, index) => ( + + )) + ) : ( + routes?.map((route: Route, index: number) => ( + handleRouteClick(route) : undefined + } + active={index === 0} + expanded={routes?.length === 1} + /> + )) + )} + + + ) } From cc89fe1db574b05a7e52f6c56b594b187b17a921 Mon Sep 17 00:00:00 2001 From: Lizaveta Miasayedava Date: Fri, 5 Jun 2026 17:17:38 +0200 Subject: [PATCH 2/3] refactor(playground): remove fixed header coupling from full-height layout --- .../DeveloperControlsDetailView.tsx | 16 +--------- .../components/Widget/WidgetView.style.tsx | 31 +++++++++++++------ .../components/Widget/WidgetViewContainer.tsx | 2 ++ .../src/hooks/usePlaygroundLayoutControls.ts | 6 +--- .../src/store/widgetConfig/useConfigValues.ts | 10 ------ 5 files changed, 26 insertions(+), 39 deletions(-) diff --git a/packages/widget-playground/src/components/DeveloperControlsDetailView/DeveloperControlsDetailView.tsx b/packages/widget-playground/src/components/DeveloperControlsDetailView/DeveloperControlsDetailView.tsx index 38aa3a3bf..2d40d2153 100644 --- a/packages/widget-playground/src/components/DeveloperControlsDetailView/DeveloperControlsDetailView.tsx +++ b/packages/widget-playground/src/components/DeveloperControlsDetailView/DeveloperControlsDetailView.tsx @@ -8,10 +8,8 @@ import { useHeaderAndFooterToolValues } from '../../store/editTools/useHeaderAnd import { useLayoutValues } from '../../store/editTools/useLayoutValues.js' import { useSkeletonToolValues } from '../../store/editTools/useSkeletonToolValues.js' import { useWidgetEventMonitorValues } from '../../store/editTools/useWidgetEventMonitorValues.js' -import { useConfigActions } from '../../store/widgetConfig/useConfigActions.js' import { useConfigContainer, - useConfigHeaderPosition, useConfigVariant, } from '../../store/widgetConfig/useConfigValues.js' import { @@ -54,13 +52,11 @@ export const DeveloperControlsDetailView = ({ useHeaderAndFooterToolValues() const { selectedLayoutId } = useLayoutValues() const { container } = useConfigContainer() - const { headerPosition } = useConfigHeaderPosition() const { variant } = useConfigVariant() const isDrawerVariant = variant === 'drawer' const isFullHeight = isFullHeightLayout(container) || selectedLayoutId === 'full-height' const isSkeletonEnabled = !isDrawerVariant - const { setHeader } = useConfigActions() const { setSkeletonShow, setHeaderVisibility, @@ -77,16 +73,6 @@ export const DeveloperControlsDetailView = ({ useWidgetEventConsoleLogging(monitoredEvents) - const handleHeaderVisibilityChange = useCallback( - (_: React.ChangeEvent, checked: boolean): void => { - setHeaderVisibility(checked) - if (headerPosition === 'fixed') { - setHeader({ position: 'fixed', top: checked ? 48 : 0 }) - } - }, - [headerPosition, setHeaderVisibility, setHeader] - ) - const handleBookmarkStoresChange = useCallback( (_: React.ChangeEvent, checked: boolean): void => { if (checked) { @@ -142,7 +128,7 @@ export const DeveloperControlsDetailView = ({ label="Mock header" description="Show a mock header element above the widget. Only available for compact variant in full-height layout." checked={showMockHeader} - onChange={handleHeaderVisibilityChange} + onChange={(_, checked) => setHeaderVisibility(checked)} disabled={!isFullHeight} ariaLabel="Toggle mock header" /> diff --git a/packages/widget-playground/src/components/Widget/WidgetView.style.tsx b/packages/widget-playground/src/components/Widget/WidgetView.style.tsx index 2113b66fe..ed696d1eb 100644 --- a/packages/widget-playground/src/components/Widget/WidgetView.style.tsx +++ b/packages/widget-playground/src/components/Widget/WidgetView.style.tsx @@ -70,15 +70,28 @@ export const WidgetContainer: React.FC< } }) -export const WidgetContainerRow: React.FC> = - styled(Box)(() => { - return { - display: 'flex', - alignItems: 'flex-start', - flexGrow: 1, - width: '100%', - } - }) +interface WidgetContainerRowProps { + withMockHeader?: boolean + withFixedFooter?: boolean +} + +export const WidgetContainerRow: React.FC< + React.ComponentProps & WidgetContainerRowProps +> = styled(Box, { + shouldForwardProp: (prop) => + !['withMockHeader', 'withFixedFooter'].includes(prop as string), +})(({ withMockHeader, withFixedFooter }) => { + const offset = + (withMockHeader ? mockElementHeight : 0) + + (withFixedFooter ? mockElementHeight : 0) + return { + display: 'flex', + alignItems: 'flex-start', + flexGrow: 1, + width: '100%', + ...(offset > 0 && { maxHeight: `calc(100vh - ${offset}px)` }), + } +}) const floatingToolButtonColors = (theme: Theme) => ({ color: theme.vars.palette.text.primary, diff --git a/packages/widget-playground/src/components/Widget/WidgetViewContainer.tsx b/packages/widget-playground/src/components/Widget/WidgetViewContainer.tsx index 4a5397063..a75a39099 100644 --- a/packages/widget-playground/src/components/Widget/WidgetViewContainer.tsx +++ b/packages/widget-playground/src/components/Widget/WidgetViewContainer.tsx @@ -86,6 +86,8 @@ export function WidgetViewContainer({ ) : null} {children} diff --git a/packages/widget-playground/src/hooks/usePlaygroundLayoutControls.ts b/packages/widget-playground/src/hooks/usePlaygroundLayoutControls.ts index 62eb04e80..0a347fdc4 100644 --- a/packages/widget-playground/src/hooks/usePlaygroundLayoutControls.ts +++ b/packages/widget-playground/src/hooks/usePlaygroundLayoutControls.ts @@ -78,11 +78,7 @@ export const usePlaygroundLayoutControls = (): { } case 'full-height': { setVariant('compact') - - setHeader({ - position: 'fixed', - top: 0, - }) + setHeader() const fullHeightContainer = { ...(getCurrentConfigTheme()?.container ?? {}), diff --git a/packages/widget-playground/src/store/widgetConfig/useConfigValues.ts b/packages/widget-playground/src/store/widgetConfig/useConfigValues.ts index 77a1a474e..5ce427292 100644 --- a/packages/widget-playground/src/store/widgetConfig/useConfigValues.ts +++ b/packages/widget-playground/src/store/widgetConfig/useConfigValues.ts @@ -107,16 +107,6 @@ export const useConfigContainer = (): { return { container } } -export const useConfigHeaderPosition = (): { - headerPosition: string | undefined -} => { - const headerPosition = useWidgetConfigStore( - (store) => store.config?.theme?.header?.position - ) - - return { headerPosition } -} - export const useConfigFontFamily = (): { fontFamily: string | undefined } => { From ee8e0b9086dd561d5f4a5d7f1dcf42640445c10d Mon Sep 17 00:00:00 2001 From: Lizaveta Miasayedava Date: Tue, 9 Jun 2026 16:13:35 +0200 Subject: [PATCH 3/3] chore: add changeset --- .changeset/align-list-scroll-pattern.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/align-list-scroll-pattern.md diff --git a/.changeset/align-list-scroll-pattern.md b/.changeset/align-list-scroll-pattern.md new file mode 100644 index 000000000..c33dc16e8 --- /dev/null +++ b/.changeset/align-list-scroll-pattern.md @@ -0,0 +1,5 @@ +--- +"@lifi/widget": patch +--- + +Align LanguagesPage and RoutesPage scroll behavior with the established `useListHeight` pattern used by other list pages.