react-router-dom#Outlet TypeScript Examples
The following examples show how to use
react-router-dom#Outlet.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: AppLayout.tsx From one-platform with MIT License | 6 votes |
AppLayout = (): JSX.Element => {
return (
<Page>
<div style={{ border: '1px solid #ddd' }}>
<Stack>
<StackItem className="p-4">
<Title headingLevel="h1" size="2xl">
Feedback
</Title>
</StackItem>
<StackItem className="p-4">
<Breadcrumb>
<BreadcrumbItem to="/">One Platform</BreadcrumbItem>
<BreadcrumbItem to="#" isActive>
All Feedback
</BreadcrumbItem>
</Breadcrumb>
</StackItem>
</Stack>
</div>
<Outlet />
</Page>
);
}
Example #2
Source File: renderContent.tsx From Search-Next with GNU General Public License v3.0 | 6 votes |
RenderContent: React.FC<RenderContentProps> = (props) => {
const { children, pathname, noOutlet = false } = props;
const location = useLocation();
let match = useMatch(pathname);
return (
<>
{(pathname === location.pathname ||
pathname === match?.pattern?.path ||
(pathname && pathname.indexOf('undefined') !== -1)) &&
children}
{!noOutlet && <Outlet />}
</>
);
}
Example #3
Source File: Characters.tsx From Riakuto-StartingReact-ja3.1 with Apache License 2.0 | 6 votes |
Characters: VFC = () => (
<>
<header>
<h1>『SLAM DUNK』登場人物</h1>
</header>
<Outlet />
<Divider hidden />
<HomeButton />
</>
)
Example #4
Source File: AccountsNavigator.tsx From celo-web-wallet with MIT License | 6 votes |
export function AccountsNavigator() {
return (
<ScreenContentFrame showBackButton={true}>
<div css={contentContainer}>
<Outlet />
</div>
</ScreenContentFrame>
)
}
Example #5
Source File: OnboardingNavigator.tsx From celo-web-wallet with MIT License | 6 votes |
export function OnboardingNavigator() {
// If wallet exists in storage don't allow user back into onboarding flow
if (hasAccounts() || hasAccount_v1()) {
return <Navigate to="/" replace={true} />
}
// Force navigation to fail screen if providers are unable to connect
const isConnected = useAppSelector((s) => s.wallet.isConnected, shallowEqual)
if (isConnected === false) throw new Error('Unable to connect to network.')
// Otherwise, render screen as normal
return <Outlet />
}
Example #6
Source File: HomeNavigator.tsx From celo-web-wallet with MIT License | 6 votes |
export function HomeNavigator() {
const isUnlocked = useAccountLockStatus()
// Force navigation to fail screen if providers are unable to connect
const isConnected = useAppSelector((s) => s.wallet.isConnected, shallowEqual)
if (isConnected === false) throw new Error('Unable to connect to network.')
// If password has been entered already
if (isUnlocked) {
return (
<ScreenFrame>
<Outlet />
</ScreenFrame>
)
}
// If wallet exists in storage but is not unlocked yet
if (hasAccounts() || hasAccount_v1()) {
return <LoginScreen />
}
// Otherwise, account must not be set up yet
return <Navigate to="/setup" replace={true} />
}
Example #7
Source File: Layout.tsx From react-starter-boilerplate with MIT License | 6 votes |
Layout = () => {
return (
<div className="app">
<header className="app__header">
<img src={logo} className="app__logo" alt="logo" />
<p>
Edit <code>src/layout/Layout.tsx</code> and save to reload.
</p>
<a className="app__link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer">
Learn React
</a>
</header>
<nav className="app__navigation">
<ul className="app__menu">
<li className="app__menu-item">
<Link className="app__menu-link" to={'/' + AppRoute.home}>
Home
</Link>
</li>
<li className="app__menu-item">
<Link className="app__menu-link" to={'/' + AppRoute.about}>
About
</Link>
</li>
<li className="app__menu-item">
<Link className="app__menu-link" to={'/' + AppRoute.help}>
Help
</Link>
</li>
</ul>
</nav>
<main className="app__main">
<Outlet />
</main>
</div>
);
}
Example #8
Source File: bluna.convert.tsx From anchor-web-app with Apache License 2.0 | 6 votes |
function Component({ className }: UIElementProps) {
const navigate = useNavigate();
const match = useMatch({ path: '/basset/bluna/:page', end: true });
const tab = useMemo<Item | undefined>(() => {
return tabItems.find(({ value }) => value === match?.params.page);
}, [match?.params.page]);
const tabChange = useCallback(
(nextTab: Item) => {
navigate(`/basset/bluna/${nextTab.value}`);
},
[navigate],
);
return (
<CenteredLayout maxWidth={800} className={className}>
<TitleContainer>
<PageTitle title="MINT & BURN" />
</TitleContainer>
<Tab
className="tab"
items={tabItems}
selectedItem={tab ?? tabItems[0]}
onChange={tabChange}
labelFunction={({ label }) => label}
keyFunction={({ value }) => value}
tooltipFunction={({ tooltip }) => tooltip}
/>
<Outlet />
</CenteredLayout>
);
}
Example #9
Source File: index.tsx From shippo with MIT License | 5 votes |
Passport = () => {
return <Outlet />
}
Example #10
Source File: index.tsx From shippo with MIT License | 5 votes |
Setting = () => {
return <Outlet />
}
Example #11
Source File: App.tsx From rari-dApp with GNU Affero General Public License v3.0 | 5 votes |
App = memo(() => {
return (
<Layout>
<Routes>
<Route path="/pools" element={<Outlet />}>
{Object.values(Pool).map((pool) => {
return (
<Route
key={pool}
path={pool}
element={<PoolPortal pool={pool} />}
/>
);
})}
</Route>
<Route path="/tranches" element={<TranchesPage />} />
<Route path="/pool2" element={<Pool2Page />} />
<Route path="/fuse" element={<FusePoolsPage />} />
<Route path="/fuse/liquidations" element={<FuseLiquidationsPage />} />
<Route path="/fuse/new-pool" element={<FusePoolCreatePage />} />
<Route path="/fuse/pool/:poolId" element={<FusePoolPage />} />
<Route path="/fuse/pool/:poolId/info" element={<FusePoolInfoPage />} />
<Route path="/fuse/pool/:poolId/edit" element={<FusePoolEditPage />} />
<Route path="/utils" element={<Navigate to="/" replace={true} />} />
<Route path="/utils/interest-rates" element={<InterestRatesPage />} />
<Route path="/utils/positions" element={<StatsPage />} />
{/* Backwards Compatibility Routes */}
<Route
path="/interest_rates"
element={<Navigate to="/utils/interest-rates" replace={true} />}
/>
<Route
path="/interest-rates"
element={<Navigate to="/utils/interest-rates" replace={true} />}
/>
<Route
path="/positions"
element={<Navigate to="/utils/positions" replace={true} />}
/>
{/* Backwards Compatibility Routes */}
<Route path="/" element={<MultiPoolPortal />} />
<Route path="*" element={<PageNotFound />} />
</Routes>
</Layout>
);
})
Example #12
Source File: trade.tsx From anchor-web-app with Apache License 2.0 | 5 votes |
function TradeBase({ className }: RewardsPoolProps) {
const navigate = useNavigate();
const pageMatch = useMatch(`/trade/:view`);
const tab = useMemo<Item | undefined>(() => {
switch (pageMatch?.params.view) {
case 'buy':
return tabItems[0];
case 'sell':
return tabItems[1];
}
}, [pageMatch?.params.view]);
const tabChange = useCallback(
(nextTab: Item) => {
navigate({
pathname: nextTab.value === 'sell' ? `/trade/sell` : `/trade/buy`,
});
},
[navigate],
);
return (
<CenteredLayout className={className}>
<Tab
className="tab"
items={tabItems}
selectedItem={tab ?? tabItems[0]}
onChange={tabChange}
labelFunction={({ label }) => label}
keyFunction={({ value }) => value}
tooltipFunction={({ tooltip }) => tooltip}
/>
<Section>
<Routes>
<Route path="" element={<Navigate to="/trade/buy" />} />
<Route path="/buy" element={<TradeBuy />} />
<Route path="/sell" element={<TradeSell />} />
<Route path="*" element={<Navigate to="/trade/buy" />} />
</Routes>
<Outlet />
</Section>
</CenteredLayout>
);
}
Example #13
Source File: rewards.anc-governance.tsx From anchor-web-app with Apache License 2.0 | 5 votes |
function RewardsAncUstLpBase({ className }: RewardsAncUstLpProps) {
const navigate = useNavigate();
const pageMatch = useMatch(`/${ancGovernancePathname}/:view`);
const subTab = useMemo<Item | undefined>(() => {
switch (pageMatch?.params.view) {
case 'stake':
return stakeItems[0];
case 'unstake':
return stakeItems[1];
}
}, [pageMatch?.params.view]);
const subTabChange = useCallback(
(nextTab: Item) => {
navigate({
pathname: `/${ancGovernancePathname}/${nextTab.value}`,
});
},
[navigate],
);
return (
<CenteredLayout className={className}>
<header>
<h1>
<Circles radius={24} backgroundColors={['#2C2C2C']}>
<GifIcon
src={anc80gif}
style={{ fontSize: '2em', borderRadius: '50%' }}
/>
</Circles>
ANC Governance
</h1>
</header>
<Section>
<RulerTab
className="subtab"
items={stakeItems}
selectedItem={subTab ?? stakeItems[0]}
onChange={subTabChange}
labelFunction={({ label }) => label}
keyFunction={({ value }) => value}
tooltipFunction={({ tooltip }) => tooltip}
/>
<div className="form">
<Routes>
<Route path="/stake" element={<AncGovernanceStake />} />
<Route path="unstake" element={<AncGovernanceUnstake />} />
<Route
index={true}
element={<Navigate to={`/${ancGovernancePathname}/stake`} />}
/>
<Route
path="*"
element={<Navigate to={`/${ancGovernancePathname}/stake`} />}
/>
</Routes>
<Outlet />
</div>
</Section>
</CenteredLayout>
);
}
Example #14
Source File: wh.convert.tsx From anchor-web-app with Apache License 2.0 | 5 votes |
function Component({ className }: UIElementProps) {
const navigate = useNavigate();
const match = useMatch({ path: '/basset/wh/:tokenSymbol/:page', end: true });
const { data: bAssetInfo } = useBAssetInfoByTokenSymbolQuery(
match?.params.tokenSymbol,
);
const tabItems = useMemo<Item[]>(() => {
const bAssetSymbol = bAssetInfo
? bAssetInfo.tokenDisplay.anchor?.symbol ?? bAssetInfo.bAsset.symbol
: 'ASSET';
const whAssetSymbol = bAssetInfo
? bAssetInfo.tokenDisplay.wormhole.symbol
: 'whASSET';
return [
{
label: `to ${bAssetSymbol}`,
value: 'to-basset',
tooltip:
'Convert wormhole tokens into bAssets that are useable on Anchor.',
},
{
label: `to ${whAssetSymbol}`,
value: 'to-wbasset',
tooltip: 'Convert bAssets useable on Anchor into wormhole tokens.',
},
];
}, [bAssetInfo]);
const tab = useMemo<Item | undefined>(() => {
return tabItems.find(({ value }) => value === match?.params.page);
}, [match?.params.page, tabItems]);
const tabChange = useCallback(
(nextTab: Item) => {
navigate(`/basset/wh/${match?.params.tokenSymbol}/${nextTab.value}`);
},
[navigate, match?.params.tokenSymbol],
);
return (
<CenteredLayout className={className} maxWidth={800}>
<TitleContainer>
<PageTitle
title="CONVERT"
tooltip="Tokens transferred to the terra chain through wormhole must be converted to bAssets useable on Anchor to be deposited as collateral."
/>
</TitleContainer>
<Tab
className="tab"
items={tabItems}
selectedItem={tab ?? tabItems[0]}
onChange={tabChange}
labelFunction={({ label }) => label}
keyFunction={({ value }) => value}
tooltipFunction={({ tooltip }) => tooltip}
/>
<Outlet />
</CenteredLayout>
);
}
Example #15
Source File: App.tsx From pintora with MIT License | 5 votes |
AppLayout = () => {
useEffect(() => {
const params = new URLSearchParams(location.search)
let code = ''
const encodedCode = params.get('code')
if (encodedCode) {
try {
code = pintora.util.decodeCodeInUrl(encodedCode)
} catch (error) {
console.error('[live-editor] error when decoding code in url', error)
}
const newParams = new URLSearchParams(params)
newParams.delete('code')
history.replaceState(null, '', `?${newParams.toString()}`)
} else if (params.has('example')) {
const exampleName: keyof typeof EXAMPLES = params.get('example') as any
if (exampleName) {
const example = EXAMPLES[exampleName]
if (example) {
code = EXAMPLES[exampleName].code
}
}
} else {
try {
const rawData = localStorage.getItem(LAST_EDITOR_CODE_KEY)
if (rawData) {
const data = JSON.parse(rawData)
code = data.code
}
} catch (error) {
console.warn('error recovering data from storage', error)
}
}
if (code) {
store.dispatch(actions.updateEditorCode({ code, syncToPreview: true }))
}
}, [])
return (
<>
<Header></Header>
<div className="App__content flex">
<AppSidebar></AppSidebar>
<Outlet />
</div>
</>
)
}
Example #16
Source File: AppEditorShell.tsx From mui-toolpad with MIT License | 5 votes |
export default function AppEditorShell({ appId, ...props }: ToolpadAppShellProps) {
const domLoader = useDomLoader();
const [createReleaseDialogOpen, setCreateReleaseDialogOpen] = React.useState(false);
return (
<ToolpadAppShell
appId={appId}
actions={
<React.Fragment>
{domLoader.saving ? (
<Box display="flex" flexDirection="row" alignItems="center">
<CircularProgress size={16} color="inherit" sx={{ mr: 1 }} />
</Box>
) : null}
<Typography>{domLoader.unsavedChanges} unsaved change(s).</Typography>
<IconButton
aria-label="Create release"
color="inherit"
sx={{ ml: 1 }}
onClick={() => setCreateReleaseDialogOpen(true)}
>
<RocketLaunchIcon />
</IconButton>
</React.Fragment>
}
{...props}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
overflow: 'hidden',
height: '100%',
}}
>
<PagePanel
appId={appId}
sx={{
width: 250,
borderRight: 1,
borderColor: 'divider',
}}
/>
<Box
sx={{
flex: 1,
overflow: 'hidden',
position: 'relative',
}}
>
<Outlet />
</Box>
<CreateReleaseDialog
appId={appId}
open={createReleaseDialogOpen}
onClose={() => setCreateReleaseDialogOpen(false)}
/>
</Box>
</ToolpadAppShell>
);
}
Example #17
Source File: SettingsView.tsx From mysterium-vpn-desktop with MIT License | 5 votes |
SettingsView: React.FC = observer(function SettingsView() {
const navigate = useNavigate()
const location = useLocation()
const isFilterTabActive = location.pathname == locations.settingsFilters
const isConnectionTabActive = location.pathname == locations.settingsConnection
const isMysteriumIdTabActive = location.pathname == locations.settingsMysteriumId
return (
<ViewContainer>
<ViewNavBar />
<ViewSplit>
<ViewSidebar>
<SideTop>
<IconSettings color={brandLight} />
<Title>Settings</Title>
</SideTop>
<SideBot>
<NavButton active={isFilterTabActive} onClick={() => navigate(locations.settingsFilters)}>
<FontAwesomeIcon icon={faSlidersH} />
Default filters
</NavButton>
<NavButton
active={isConnectionTabActive}
onClick={() => navigate(locations.settingsConnection)}
>
<FontAwesomeIcon icon={faGlobe} />
Connection
</NavButton>
<NavButton
active={isMysteriumIdTabActive}
onClick={() => navigate(locations.settingsMysteriumId)}
>
<FontAwesomeIcon icon={faUserAlt} />
Mysterium ID
</NavButton>
<Version />
</SideBot>
</ViewSidebar>
<Content>
<Outlet />
</Content>
</ViewSplit>
</ViewContainer>
)
})
Example #18
Source File: AppLayout.tsx From one-platform with MIT License | 5 votes |
AppLayout: FC = () => {
const { pathname } = useLocation();
const [isSidebarOpen, setIsSidebarOpen] = useToggle(true);
const { breadcrumbs } = useBreadcrumb();
const isBreadcrumbHidden = breadcrumbs.length === 0;
return (
<Page
mainContainerId="app-layout-page"
sidebar={<Sidebar isOpen={isSidebarOpen} />}
className={styles['app-layout']}
breadcrumb={
!isBreadcrumbHidden && (
<Breadcrumb className={styles['app-layout--breadcrumb']}>
<BreadcrumbItem>
<Button variant="link" className="pf-u-p-0" onClick={setIsSidebarOpen.toggle}>
<BarsIcon />
</Button>
</BreadcrumbItem>
<BreadcrumbItem to="/">One Platform</BreadcrumbItem>
<BreadcrumbItem>
{pathname === config.baseURL ? 'API Catalog Home' : <Link to="/">API Catalog</Link>}
</BreadcrumbItem>
{breadcrumbs.map(({ label, url }, index) => {
const isActive = index === breadcrumbs.length - 1;
return (
<BreadcrumbItem key={label}>
{isActive ? label : <Link to={url}>{label}</Link>}
</BreadcrumbItem>
);
})}
</Breadcrumb>
)
}
>
<PageSection
className={styles['app-layout--content']}
variant="light"
padding={{ default: 'noPadding' }}
>
<Outlet />
</PageSection>
</Page>
);
}
Example #19
Source File: rewards.anc-ust-lp.tsx From anchor-web-app with Apache License 2.0 | 4 votes |
function RewardsAncUstLpBase({ className }: RewardsAncUstLpProps) {
const navigate = useNavigate();
const pageMatch = useMatch(`/${ancUstLpPathname}/:view`);
const tab = useMemo<Item | undefined>(() => {
switch (pageMatch?.params.view) {
case 'provide':
case 'withdraw':
return tabItems[0];
case 'stake':
case 'unstake':
return tabItems[1];
}
}, [pageMatch?.params.view]);
const tabChange = useCallback(
(nextTab: Item) => {
navigate(
nextTab.value === 'stake'
? `/${ancUstLpPathname}/stake`
: `/${ancUstLpPathname}/provide`,
);
},
[navigate],
);
const subTab = useMemo<Item | undefined>(() => {
switch (pageMatch?.params.view) {
case 'provide':
return poolItems[0];
case 'withdraw':
return poolItems[1];
case 'stake':
return stakeItems[0];
case 'unstake':
return stakeItems[1];
}
}, [pageMatch?.params.view]);
const subTabChange = useCallback(
(nextTab: Item) => {
navigate(`/${ancUstLpPathname}/${nextTab.value}`);
},
[navigate],
);
return (
<CenteredLayout className={className}>
<header>
<h1>
<Circles radius={24} backgroundColors={['#ffffff', '#2C2C2C']}>
<TokenIcon token="ust" style={{ fontSize: '1.1em' }} />
<GifIcon
src={anc80gif}
style={{ fontSize: '2em', borderRadius: '50%' }}
/>
</Circles>
ANC-UST LP
</h1>
<Tab
items={tabItems}
selectedItem={tab ?? tabItems[0]}
onChange={tabChange}
labelFunction={({ label }) => label}
keyFunction={({ value }) => value}
height={46}
borderRadius={30}
fontSize={12}
/>
</header>
<Section>
<RulerTab
className="subtab"
items={tab?.value === 'stake' ? stakeItems : poolItems}
selectedItem={
subTab ?? (tab?.value === 'stake' ? stakeItems[0] : poolItems[0])
}
onChange={subTabChange}
labelFunction={({ label }) => label}
keyFunction={({ value }) => value}
tooltipFunction={({ tooltip }) => tooltip}
/>
<div className="form">
{tab?.value === 'stake' && <AncUstLpStakeOverview />}
<Routes>
<Route path={`/provide`} element={<AncUstLpProvide />} />
<Route path={`/withdraw`} element={<AncUstLpWithdraw />} />
<Route path={`/stake`} element={<AncUstLpStake />} />
<Route path={`/unstake`} element={<AncUstLpUnstake />} />
<Route
path={``}
element={<Navigate to={`/${ancUstLpPathname}/provide`} />}
/>
<Route
path={`*`}
element={<Navigate to={`/${ancUstLpPathname}/provide`} />}
/>
</Routes>
<Outlet />
</div>
</Section>
</CenteredLayout>
);
}
Example #20
Source File: HelpView.tsx From mysterium-vpn-desktop with MIT License | 4 votes |
HelpView: React.FC = observer(function HelpView() {
const { navigation } = useStores()
const navigate = useNavigate()
const location = useLocation()
const isBugReportActive = location.pathname.includes(locations.helpBugReport)
const isTermsAndConditionsActive = location.pathname.includes(locations.helpTermsAndConditions)
return (
<ViewContainer>
<ViewNavBar />
<ViewSplit>
<ViewSidebar>
<SideTop>
<IconPerson color={brandLight} />
<Title>Get help</Title>
<Small>Help using Mysterium VPN</Small>
</SideTop>
<SideBot>
<SupportChatButton onClick={() => navigation.openChat()}>
<FontAwesomeIcon icon={faComments} />
Support chat
</SupportChatButton>
<NavButton active={isBugReportActive} onClick={() => navigate(locations.helpBugReport)}>
<FontAwesomeIcon icon={faBug} />
Bug report
</NavButton>
<NavButton
active={isTermsAndConditionsActive}
onClick={() => navigate(locations.helpTermsAndConditions)}
>
<FontAwesomeIcon icon={faFileContract} />
Terms & Conditions
</NavButton>
<NavButton active={false} onClick={() => shell.openExternal("https://docs.mysterium.network")}>
<FontAwesomeIcon icon={faBook} />
Documentation
</NavButton>
<SocialButtons>
<IconButton
active={false}
onClick={() => {
shell.openExternal("https://discordapp.com/invite/n3vtSwc")
}}
>
<FontAwesomeIcon icon={faDiscord} size="2x" />
</IconButton>
<IconButton
active={false}
onClick={() => {
shell.openExternal("https://www.reddit.com/r/MysteriumNetwork/")
}}
>
<FontAwesomeIcon icon={faReddit} size="2x" />
</IconButton>
<IconButton active={false}>
<FontAwesomeIcon
icon={faTwitter}
size="2x"
onClick={() => {
shell.openExternal("https://twitter.com/MysteriumNet")
}}
/>
</IconButton>
<IconButton active={false}>
<FontAwesomeIcon
icon={faFacebookSquare}
size="2x"
onClick={() => {
shell.openExternal("https://www.facebook.com/MysteriumNet")
}}
/>
</IconButton>
</SocialButtons>
<Version />
</SideBot>
</ViewSidebar>
<Content>
<Outlet />
</Content>
</ViewSplit>
</ViewContainer>
)
})
Example #21
Source File: index.tsx From Search-Next with GNU General Public License v3.0 | 4 votes |
SettingPage: React.FC<SettingPageProps> = ({
children,
route,
...props
}) => {
const history = useNavigate();
const location = useLocation();
const params = useParams();
const [menuList, setMenuList] = React.useState<Router[] | undefined>([]);
const [breads, setBreads] = React.useState<Router[]>([]);
const getBreadCrumbs = (routes: Router[], parentPath: string = '') => {
let breadCrumbs: Router[] = [];
const findRoute = (
routes: Router[] | undefined,
parentPath: string = '',
) => {
if (!routes) return routes;
const loc = location;
routes.forEach((i) => {
const fullPath = `${parentPath}/${i.path}`;
const splitPath = fullPath.split(':');
const paramsPath =
splitPath[0] +
Object.values(params)
.filter((u) => u !== '')
.join('/');
if (
loc.pathname.indexOf(i.path) !== -1 ||
loc.pathname === paramsPath
) {
breadCrumbs.push(i);
}
if (i.routes) {
findRoute(i.routes, fullPath);
}
});
};
findRoute(routes, parentPath);
return breadCrumbs;
};
React.useEffect(() => {
if (location.pathname === '/setting') {
history(route?.routes?.[0].path || '/setting', { replace: true });
}
setMenuList(route?.routes);
}, []);
React.useEffect(() => {
const breads = getBreadCrumbs(route.routes || [], '/setting');
setBreads(breads);
}, [location]);
return (
<div className="flex flex-row h-screen bg-gray-70">
<div className="w-72 p-4 h-full">
<div className="flex gap-1">
<Tooltip title="回到首页" arrow>
<IconButton
size="small"
onClick={() => {
history('/');
}}
>
<Home />
</IconButton>
</Tooltip>
<Tooltip title="返回上级" arrow>
<IconButton
size="small"
onClick={() => {
history(-1);
}}
>
<KeyboardBackspace />
</IconButton>
</Tooltip>
</div>
<div className="flex flex-col gap-1 my-4">
{menuList?.map((i) => (
<div
key={i.path}
className={classNames(
'hover:bg-gray-150',
'transition-all',
'px-2.5',
'py-1.5',
'cursor-pointer',
'rounded',
'text-sm',
'text-gray-800',
{
'bg-gray-150': location.pathname.indexOf(i.path) > -1,
},
)}
onClick={() => {
history(i.path);
}}
>
{i.title}
</div>
))}
</div>
</div>
<div className="h-full overflow-hidden flex flex-col w-full px-6 py-4">
<Breadcrumbs separator="›" aria-label="breadcrumb" className="mb-4">
{breads.map((i, index) => (
<div
className={classNames('text-2xl cursor-pointer mb-0', {
'font-semibold': index === breads.length - 1,
})}
key={i.path}
onClick={() => {
const path =
'/setting/' +
breads
.map((i) => i.path)
.filter((_, ji) => ji <= index)
.join('/');
index !== breads.length - 1 ? history(path) : null;
}}
>
<div className="flex items-center gap-1">
{i.title}
{i?.status === 'process' && (
<Chip
color="warning"
label={i?.status}
size="small"
variant="outlined"
/>
)}
</div>
</div>
))}
</Breadcrumbs>
<div className="flex-grow overflow-y-auto w-full">
<div className="max-w-4xl">
<Outlet />
</div>
</div>
<div className="text-center max-w-4xl">
<Copyright />
</div>
</div>
</div>
);
}