24

I'm using AntD, thought it would be an easy and quick set up for a common and standard Responsive NavBar, but it turned out it's not responsive by default:

squashed

As you can see, it's squashed.

Here is the code:

<Menu
                        theme="dark"
                        mode="horizontal"
                        defaultSelectedKeys={["1"]}
                        style={{ lineHeight: '64px' }}
                        breakpoint="lg"
                        collapsedWidth="0"
                    >
                                <Menu.Item key="1">nav 1</Menu.Item>
                                <Menu.Item key="2">nav 2</Menu.Item>
                                <Menu.Item key="3">nav 3</Menu.Item>
                                <Menu.Item key="4"><Icon spin={true} type="plus-circle" className="publish-btn" /></Menu.Item>
                                <Menu.Item key="5"><Icon spin={true} type="login" className="loggin-btn" /></Menu.Item>
                    </Menu>

So I read the document again and thought I would have to use Grid inside the Menu to make it responsive. However, it threw me errors: errors

Here is the code:

<Menu
                        theme="dark"
                        mode="horizontal"
                        defaultSelectedKeys={["1"]}
                        style={{ lineHeight: '64px' }}
                        breakpoint="lg"
                        collapsedWidth="0"
                    >

                        <Row key="1" gutter={16}>
                            <Col span={3} key="1">
                                <Menu.Item key="1">nav 1</Menu.Item>
                            </Col>
                            <Col span={3} key="2">
                                <Menu.Item key="2">nav 2</Menu.Item>
                            </Col>
                            <Col span={3} key="3">
                                <Menu.Item key="3">nav 3</Menu.Item>
                            </Col>
                            <Col span={3} offset={9} key="4">
                                <Menu.Item key="4"><Icon spin={true} type="plus-circle" className="publish-btn" /></Menu.Item>
                            </Col>
                            <Col span={3} key="5">
                                <Menu.Item key="5"><Icon type="login" className="loggin-btn" /></Menu.Item>
                            </Col>
                        </Row>
                    </Menu>

Update

Let me clarify myself. I do not want a Sidebar(as in my case it's a small website, not many pages). All I want is to have a top NavBar when re-sizing the Menu.Items can collapse and become to a hamburger icon. Also, I need 2 menu.items on the right side.

halfer
  • 19,824
  • 17
  • 99
  • 186
Franva
  • 6,565
  • 23
  • 79
  • 144

4 Answers4

23

I was looking at this question in a decision to pick Ant design for a project. Responsive navbar is common scenario, but I was wondering why there is no such thing in Ant Design? Then I searched for issues in the repo and found the Ant Design Mobile as a comment to an issue.

They have a separate package for mobile devices. Inside Ant Design Mobile there is separate section for web components. In that section you can find a Menu component which is suitable for mobile devices hamburger icon.

Hope this will be helpful for future readers.

user158
  • 12,852
  • 7
  • 62
  • 94
11

I was looking for such functionality not long ago as well and in order to make Ant Menu responsive, I have written a simple React Component.

This Component accepts Ant Menu markup as a prop and conditionally renders the Menu based on the viewport width, either as is (for desktop), or in a Popover component which will wrap passed menu markup (for mobile).

I'm including screenshots of how it may look once the viewport is narrow enough to render just the hamburger icon.

Default Ant Menu Responsive Ant Menu

You can find a Github repo with working example here.

Hope it helps.

Tom
  • 422
  • 3
  • 14
  • thanks Tomas, thanks for the good work you have done here. Just one question, if we have to write our own code even for such a simple purpose and the equivalent UI Frameworks e.g. Bootstrap have already implemented it, why would we still use Ant Design? This was the feeling about Ant Design when I figured out the NavBar from AntDesign isn't event responsive. – Franva Apr 06 '18 at 00:33
  • 5
    You are right, Franva and although this particular feature is still missing from Ant Design, there are way too many great features which are still missing in others UI frameworks. I would say it is always about compromises, what works for your project does not have to work for the other. As an example, let's compare Table component from Ant Design vs React Bootstrap - the one in Ant Design has way more features and options compared to the one in Bootstrap.I'm sure, the solution I proposed is just a temporary, and sooner or later responsive Meni will be part of the Ant Design :) – Tom Apr 06 '18 at 06:05
  • agreed :) hopefully it won't take too long. – Franva Apr 06 '18 at 06:37
4

First a clarification: What the antd docs mean by "responsive" (in this example in the docs) is not that the navbar items reflow, but rather that the sidebar collapses into a smaller menu or disappears with a hamburger trigger button appearing.

Second: Mixing Menu and Row/Col is a bad idea. The errors are happening because Menu.Item expects to be a direct child element of Menu, and you are making it a grandchild via Row/Col, who are not passing the same props.

There is no support in AntD for your requirements as explained in your clarification. One of my AntD based sites works in a similar way to what you are looking for. What I do on that site is render two sets of menus, one for a desktop navbar and one for a small screen sidebar with hamburger, and then use CSS media queries to hide one or the other on each side of the @screen-sm breakpoint.

Jesper We
  • 5,977
  • 2
  • 26
  • 40
  • 2
    Hi Jasper, thanks for your reply. Let me clarify myself. I do not want a Sidebar(as in my case it's a small website, not many pages). All I want is to have a top NavBar when re-sizing the Menu.Items can collapse and become to a hamburger icon. Also, I need 2 menu.items on the right side. – Franva Feb 22 '18 at 21:33
  • do we have a prop to make the Menu.Items collapse and become a hamburger icon? – Franva Feb 22 '18 at 21:47
  • @JesperWe thanks for your response. Do you use React? Can you please share your implementation which you described in your answer? – SaidAkh Mar 25 '18 at 13:13
4

For the responsive behavior use the "overflowedIndicator" property from antd's Menu component. You can choose any antd icon to be displayed when menu collapses. Control when the menu collapses by using the antd's Grid capabilities (Col xl,lg,md,sm,xs) properties.

Please, check the example bellow for a simple responsive NavBar:

import React from 'react';
import { Row, Col, Typography, Layout, Menu } from 'antd';
import { MenuOutlined } from '@ant-design/icons';

const { Header, Content } = Layout;
const { Title } = Typography;

export interface NavBarProps {
    selectedPage: string;
    children: React.ReactNode;
}

export const NavBar: React.FC<NavBarProps> = (props: NavBarProps) => {

const gotoPage = (page: string) => {
  //GO TO MENU ITEM PAGE
};

return (
<Row justify='center'>
  <Col xl={24} lg={24} md={24} sm={24} xs={24}>
    <Header className='header-fixed'>
      <Row>
        <Col xl={12} lg={12} md={12} sm={20} xs={20}>
          <Title id='title-button' level={4}>
            <a onClick={() => gotoPage('')}>My App</a>
          </Title>
        </Col>
        <Col xl={12} lg={12} md={12} sm={4} xs={4}>
          <Menu
            theme='dark'
            mode='horizontal'
            defaultSelectedKeys={["item1"]}
            overflowedIndicator={<MenuOutlined />}
          >
            <Menu.Item
              key="item1"
              onClick={() => gotoPage("item1")}
            >
              item1
            </Menu.Item>
            <Menu.Item
              key={"item2"}
              onClick={() => gotoPage("item2")}
            >
              item2
            </Menu.Item>
            <Menu.Item
              key={"item3"}
              onClick={() => gotoPage("item3")}
            >
              item3
            </Menu.Item>
          </Menu>
        </Col>
      </Row>
    </Header>
    <Content>{props.children}</Content>
  </Col>
</Row>
);
};

CSS:

.header-fixed {
  h4 {
      margin-top: 15px;
      margin-bottom: 20px;
  }
}

Then use the component as following:

<NavBar selectedPage=''>
  <YourPageComponent />
</NavBar>
Daniel Dantas
  • 371
  • 3
  • 5