Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/align-list-scroll-pattern.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@lifi/widget": patch
---

Align LanguagesPage and RoutesPage scroll behavior with the established `useListHeight` pattern used by other list pages.
2 changes: 1 addition & 1 deletion packages/widget-playground-next/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default function RootLayout({
children: React.ReactNode
}>) {
return (
<html lang="en">
<html lang="en" style={{ overscrollBehavior: 'none' }}>
<head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
Expand Down
4 changes: 4 additions & 0 deletions packages/widget-playground-vite/src/index.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
html {
overscroll-behavior: none;
}

#root {
display: flex;
flex-grow: 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ import { useEditToolsActions } from '../../store/editTools/useEditToolsActions.j
import { useHeaderAndFooterToolValues } from '../../store/editTools/useHeaderAndFooterToolValues.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 {
Expand Down Expand Up @@ -52,12 +50,10 @@ export const DeveloperControlsDetailView = ({
const { showMockHeader, showMockFooter, isFooterFixed } =
useHeaderAndFooterToolValues()
const { container } = useConfigContainer()
const { headerPosition } = useConfigHeaderPosition()
const { variant } = useConfigVariant()
const isDrawerVariant = variant === 'drawer'
const isFullHeight = isFullHeightLayout(container)
const isSkeletonEnabled = !isDrawerVariant
const { setHeader } = useConfigActions()
const {
setSkeletonShow,
setHeaderVisibility,
Expand All @@ -74,16 +70,6 @@ export const DeveloperControlsDetailView = ({

useWidgetEventConsoleLogging(monitoredEvents)

const handleHeaderVisibilityChange = useCallback(
(_: React.ChangeEvent<HTMLInputElement>, checked: boolean): void => {
setHeaderVisibility(checked)
if (headerPosition === 'fixed') {
setHeader({ position: 'fixed', top: checked ? 48 : 0 })
}
},
[headerPosition, setHeaderVisibility, setHeader]
)

const handleBookmarkStoresChange = useCallback(
(_: React.ChangeEvent<HTMLInputElement>, checked: boolean): void => {
if (checked) {
Expand Down Expand Up @@ -139,7 +125,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"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,28 @@ export const WidgetContainer: React.FC<
}
})

export const WidgetContainerRow: React.FC<React.ComponentProps<typeof Box>> =
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<typeof Box> & WidgetContainerRowProps
> = styled(Box, {
shouldForwardProp: (prop) =>
!['withMockHeader', 'withFixedFooter'].includes(prop as string),
})<WidgetContainerRowProps>(({ 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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ export function WidgetViewContainer({
</MockElement>
) : null}
<WidgetContainerRow
withMockHeader={showHeader}
withFixedFooter={showFooter && isFooterFixed}
sx={{ marginBottom: !isFullHeight || showFooter ? 6 : 0 }}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
} => {
Expand Down
59 changes: 36 additions & 23 deletions packages/widget/src/pages/LanguagesPage.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLDivElement>(null)
const { selectedLanguageCode, availableLanguages, setLanguageWithCode } =
useLanguages()

useHeader(t('language.title'))

const { listHeight } = useListHeight({
listParentRef,
})

if (availableLanguages.length < 1) {
return null
}

return (
<PageContainer disableGutters>
<List
sx={{
padding: 1.5,
}}
<Box
className="long-list"
ref={listParentRef}
style={{ height: listHeight, overflow: 'auto' }}
>
{availableLanguages.map((language) => (
<SettingsListItemButton
key={language}
onClick={() => setLanguageWithCode(language)}
>
<ListItemText
primary={
languageNames[language as keyof typeof languageNames] ||
t('language.name', {
lng: language,
}) ||
language
}
/>
{selectedLanguageCode === language && <Check color="primary" />}
</SettingsListItemButton>
))}
</List>
<List
sx={{
padding: 1.5,
}}
>
{availableLanguages.map((language) => (
<SettingsListItemButton
key={language}
onClick={() => setLanguageWithCode(language)}
>
<ListItemText
primary={
languageNames[language as keyof typeof languageNames] ||
t('language.name', {
lng: language,
}) ||
language
}
/>
{selectedLanguageCode === language && <Check color="primary" />}
</SettingsListItemButton>
))}
</List>
</Box>
</PageContainer>
)
}
65 changes: 38 additions & 27 deletions packages/widget/src/pages/RoutesPage/RoutesPage.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -20,6 +23,7 @@ export const RoutesPage = (): JSX.Element => {
const { t } = useTranslation()
const navigate = useNavigate()
const emitter = useWidgetEvents()
const listParentRef = useRef<HTMLDivElement>(null)
const {
routes,
isLoading,
Expand Down Expand Up @@ -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({
Expand All @@ -69,31 +77,34 @@ export const RoutesPage = (): JSX.Element => {
const allowInteraction = account.isConnected && !toAddressUnsatisfied

return (
<Stack
className="long-list"
direction="column"
spacing={2}
sx={{ flex: 1, pt: 1.5 }}
>
{routeNotFound ? (
<RouteNotFoundCard />
) : isLoading && !routes?.length ? (
Array.from({ length: 3 }).map((_, index) => (
<RouteCardSkeleton key={index} />
))
) : (
routes?.map((route: Route, index: number) => (
<RouteCard
key={index}
route={route}
onClick={
allowInteraction ? () => handleRouteClick(route) : undefined
}
active={index === 0}
expanded={routes?.length === 1}
/>
))
)}
</Stack>
<PageContainer disableGutters>
<Box
className="long-list"
ref={listParentRef}
style={{ height: listHeight, overflow: 'auto' }}
>
<Stack direction="column" spacing={2} sx={{ pt: 1.5 }}>
{routeNotFound ? (
<RouteNotFoundCard />
) : isLoading && !routes?.length ? (
Array.from({ length: 3 }).map((_, index) => (
<RouteCardSkeleton key={index} />
))
) : (
routes?.map((route: Route, index: number) => (
<RouteCard
key={index}
route={route}
onClick={
allowInteraction ? () => handleRouteClick(route) : undefined
}
active={index === 0}
expanded={routes?.length === 1}
/>
))
)}
</Stack>
</Box>
</PageContainer>
)
}
Loading