Custom Layout
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.
Usage
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,
  notificationProvider,
  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'
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)}
      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>
      )}
      Title={() => (
        <Link to="/" style={{ float: 'left', marginRight: '10px' }}>
          <img src="/refine.svg" alt="Refine" />
        </Link>
      )}
      ReadyPage={ReadyPage}
      notificationProvider={notificationProvider}
      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 = () => {
  const Title = useTitle()
  const { menuItems, selectedKey } = useMenu()
  return (
    <>
      {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>
    </>
  )
}
Here, we use useMenu hook to get the list of current resources and print it.
By default, <Sider> is responsible for rendering <Title>. It gets this component (configured by <Refine> and/or <LayoutWrapper>) by useTitle hook.
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. →
Example
Here's how it looks in the end:
npm create refine-app@latest -- --example customization-top-menu-layout