documentation/versioned_docs/version-3.xx.xx/advanced-tutorials/custom-layout.md
You can create custom layouts using <Refine> and <LayoutWrapper> components.
Both of these components can accept the listed props for customization. <Refine> is for global customization and the <LayoutWrapper> is for local.
:::caution
To make this example more visual, we used the @pankod/refine-antd package. If you are using Refine headless, you need to provide the components, hooks, or helpers imported from the @pankod/refine-antd package.
:::
Let's look at an example of modifying the default layout to have a top menu layout.
import { Refine } from "@pankod/refine-core";
import {
AntdLayout,
ReadyPage,
useNotificationProvider,
ErrorComponent,
} from "@pankod/refine-antd";
import routerProvider from "@pankod/refine-react-router-v6";
import dataProvider from "@pankod/refine-simple-rest";
import "@pankod/refine-antd/dist/reset.css";
import { PostList } from "pages/posts";
// highlight-next-line
import { CustomSider } from "components";
const { Link } = routerProvider;
const API_URL = "https://api.fake-rest.refine.dev";
const App: React.FC = () => {
return (
<Refine
routerProvider={routerProvider}
dataProvider={dataProvider(API_URL)}
// highlight-start
Layout={({ children, Footer, OffLayoutArea }) => (
<AntdLayout>
<AntdLayout.Header>
<CustomSider />
</AntdLayout.Header>
<AntdLayout.Content>
<AntdLayout.Content>
<div style={{ padding: 24, minHeight: 360 }}>{children}</div>
</AntdLayout.Content>
{Footer && <Footer />}
</AntdLayout.Content>
{OffLayoutArea && <OffLayoutArea />}
</AntdLayout>
)}
// highlight-end
Title={() => (
<Link to="/" style={{ float: "left", marginRight: "10px" }}>
</Link>
)}
ReadyPage={ReadyPage}
notificationProvider={useNotificationProvider}
catchAll={<ErrorComponent />}
/>
);
};
export default App;
Here, we override the <Title> and <Layout> components. When we override <Layout>, we put the <CustomSider> (instead of the <Sider> that was provided to <Layout> to render it by default) on top of <AntdLayout>.
So, we just provided a custom <Sider>. Here's our custom sider that looks horizontal, instead of the default vertical one:
import { useTitle, useMenu } from "@pankod/refine-core";
import { Menu } from "@pankod/refine-antd";
import routerProvider from "@pankod/refine-react-router-v6";
const { Link } = routerProvider;
export const CustomSider: React.FC = () => {
// highlight-start
const Title = useTitle();
const { menuItems, selectedKey } = useMenu();
// highlight-end
return (
<>
// highlight-start
{Title && <Title collapsed={false} />}
<Menu selectedKeys={[selectedKey]} mode="horizontal">
{menuItems.map(({ icon, route, label }) => (
<Menu.Item key={route} icon={icon}>
<Link to={route ?? ""}>{label}</Link>
</Menu.Item>
))}
</Menu>
// highlight-end
</>
);
};
Here, we use useMenu hook to get the list of current resources and print it.
:::info
By default, <Sider> is responsible for rendering <Title>. It gets this component (configured by <Refine> and/or <LayoutWrapper>) by useTitle hook.
:::
:::info
This example demonstrated how to configure a global layout. To learn how to use global layout in custom pages and make local modifications per page, refer to the <LayoutWrapper> docs. →
:::
Here's how it looks in the end:
<CodeSandboxExample path="customization-top-menu-layout" />