How to right-align menu items in Ant Design? - reactjs

There is an open Git issue requesting props for the alignment of Menu items. In the meantime, what is the correct way to move some Navbar items (eg Login, logout) to the right side?
Here is there example code for a Menu, where all Menu items are on the left side.
import { Menu, Icon } from 'antd';
const SubMenu = Menu.SubMenu;
const MenuItemGroup = Menu.ItemGroup;
class App extends React.Component {
state = {
current: 'mail',
}
handleClick = (e) => {
console.log('click ', e);
this.setState({
current: e.key,
});
}
render() {
return (
<Menu
onClick={this.handleClick}
selectedKeys={[this.state.current]}
mode="horizontal"
>
<Menu.Item key="mail">
<Icon type="mail" />Navigation One
</Menu.Item>
<Menu.Item key="app" disabled>
<Icon type="appstore" />Navigation Two
</Menu.Item>
<SubMenu title={<span><Icon type="setting" />Navigation Three - Submenu</span>}>
<MenuItemGroup title="Item 1">
<Menu.Item key="setting:1">Option 1</Menu.Item>
<Menu.Item key="setting:2">Option 2</Menu.Item>
</MenuItemGroup>
<MenuItemGroup title="Item 2">
<Menu.Item key="setting:3">Option 3</Menu.Item>
<Menu.Item key="setting:4">Option 4</Menu.Item>
</MenuItemGroup>
</SubMenu>
<Menu.Item key="alipay">
Navigation Four - Link
</Menu.Item>
</Menu>
);
}
}
ReactDOM.render(<App />, mountNode);

Try giving the menu items you want on the right float: right via JSX styling or a CSS class.
Example pulling the Navigation Three item to the right with JSX inline styling, style={{float: 'right'}}:
<SubMenu style={{float: 'right'}} title={<span><Icon type="setting" />Navigation Three - Submenu</span>}>
<MenuItemGroup title="Item 1">
<Menu.Item key="setting:1">Option 1</Menu.Item>
<Menu.Item key="setting:2">Option 2</Menu.Item>
</MenuItemGroup>
<MenuItemGroup title="Item 2">
<Menu.Item key="setting:3">Option 3</Menu.Item>
<Menu.Item key="setting:4">Option 4</Menu.Item>
</MenuItemGroup>
</SubMenu>
UPDATE: (for Firefox):
If you have right and left menu elements, you need to add
style={{float: 'right'}} to the right MenuItem's and
style={{float: 'left'}} to the left ones.
Leaving out the latter will cause some browsers (Firefox) to render the underlying <li> tags with a break between them.

Due to some change in Ant design 4.16.3, style={{float: 'right'}} won't work anymore.
Instead, you can use style={{ marginLeft: 'auto' }}.
Source: Github issue

None of answers work if you want to align several items left and several right.
To do so, add style={{ display: 'block' }} to <Menu> and style={{ float: 'right' }} to <Menu.Item> you want on the right.
Works for horizontal menu, didn't tried on vertical...
<Menu style={{ display: 'block' }}>
<Menu.Item key='home'><Link to={'/'}>Home</Link></Menu.Item>
<Menu.Item key='option1'><Link to={'/option1'}>Option 1</Link></Menu.Item>
<Menu.Item key='notif' style={{ float: 'right' }}>
<Link to={'/notif'}>Notifications</Link>
</Menu.Item>
<Menu.Item key='logout' style={{ float: 'right' }}>
<Link to={'/notif'}>Logout</Link>
</Menu.Item>
</Menu>

This will solve the issue:
style={{ marginLeft: 'auto' }}

You can also use style={{justifyContent: 'flex-end'}}.
marginLeft: 'auto' didn't work for me because I needed to apply it to Menu rather than SubMenu

Related

React: How to render components based on MenuItem clicked?

Below is the code:
import React from 'react';
import { Layout, Menu, Breadcrumb } from 'antd';
import { UserOutlined, ProfileFilled, CreditCardFilled, SearchOutlined, BankOutlined} from '#ant-design/icons';
const { SubMenu } = Menu;
const { Header, Content, Sider, Footer } = Layout;
function Admin(){
function handleClick(){
console.log("Search")
}
return(
<Layout>
<Header className="header">
<div className="logo" />
<Menu theme="light" mode="horizontal" defaultSelectedKeys={['2']} icon={<UserOutlined />}>
<Menu.Item key="1">Creame Cookies</Menu.Item>
</Menu>
</Header>
<Layout>
<Sider width={200} className="site-layout-background">
<Menu
theme="dark"
mode="inline"
defaultOpenKeys={['Dashboard']}
defaultSelectedKeys={['Dashboard']}
style={{ height: '250%', borderRight: 0, width: 250 }}
>
<Menu.Item key="Dashboard" icon={<UserOutlined />}>
Dashboard
</Menu.Item>
<Menu.Item onClick={handleClick} key="Search" icon={<SearchOutlined />}>
Search
</Menu.Item>
<SubMenu key="Profiles" icon={<ProfileFilled />} title="Profiles">
<Menu.Item key="1">Free Profiles</Menu.Item>
<Menu.Item key="2">Premium Profiles</Menu.Item>
</SubMenu>
<Menu.Item key="Payments" icon={<CreditCardFilled />}>
Payments
</Menu.Item>
</Menu>
</Sider>
<Layout style={{ padding: '0 72px 72px' }}>
<Content
className="site-layout-background"
style={{
padding: 24,
margin: 0,
minHeight: 500,
}}
>
<h1>Default</h1>
</Content>
</Layout>
</Layout>
{/*<Footer style={{ textAlign: 'center' }}>Creame Cookies Ltd</Footer> */}
</Layout>
)
}
export default Admin
Now, I need to render components at the location of the h1 tag with text as Default, based on the menuitem clicked. I am unsure of how to do this in react since I am new to it and feeling it difficult as compared to vannila javascript and jQuery in which I have already worked.
<h1>{someCondition ? 'Text A': 'Text B'}</h1> is generally how you handle this. You can always do the condition at the top of the component before your return statement if you prefer.
{ } is syntax to wrap an expression in React. You could put a ternary or just a variable in there to render.
Could also do <h1>{someCondtion ? <ComponentA /> : <ComponentB />}</h1>.

How to center menu-item in navbar like example

Similar to the example of the top navbar.
I would like to have a centered menu item and two items floated all the way to the right of the navbar.
So far I've figured out how to float the two items to the right, but I'm not sure how to center the title item. What's the antd way to center a menu item?
<Menu mode="horizontal">
<Menu.Item>Centered</Menu.Item>
<Menu.Item style={{float:"right"}}>Right</Menu.Item>
<Menu.Item style={{float:"right"}}>Right</Menu.Item>
</Menu>
Try using flexbox
const centerStyle = {
position: 'relative',
display: 'flex',
justifyContent: 'center'
};
const rightStyle = { position: 'absolute', top: 0, right: 0 };
function App() {
return (
<Menu style={centerStyle} mode="horizontal">
<Menu.Item> Cookies </Menu.Item>
<Menu.Item> Cookies2 </Menu.Item>
<Menu.Item style={rightStyle}> Right </Menu.Item>
</Menu>
);
}

Adding color for a span inside a Link component doesn't change the color of the span?

import React, { Component } from 'react';
import { Menu, Icon } from 'antd';
import { Link } from 'react-router-dom';
const Sidebar = () => (
<div style={{ width: '164px', padding: '20px 0px' }}>
<Menu
style={{ width: '164px' }}
defaultSelectedKeys={['1']}
defaultOpenKeys={['sub1']}
mode="inline"
>
<Menu.Item key="1">
<Icon type="home" />
<Link to='/'><span style={{ color: 'rgb(199, 143, 95)' }}>Home</span></Link>
</Menu.Item>
<Menu.Item key="2">
<Icon type="tags" />
<Link to='/tags'><span style={{ color: 'rgb(199, 143, 95)' }}>Tags</span></Link>
</Menu.Item>
<Menu.Item key="3">
<Icon type="team" />
<Link to='/users'><span style={{ color: 'rgb(199, 143, 95)', backgroundColor: 'yellow' }}>Users</span></Link>
</Menu.Item>
</Menu>
</div>
);
export default Sidebar;
I used antd as a ui framework. Since Link component hides the texts in the span elements i want to change the color of span elements but adding color prop doesn't have any effect.
I don't fully understand your question, but if you want to have the write "Tags" (which is also a link) written in red, you might try one these two ways:
<Link to='/tags'><span style={{ color: 'red !important' }}>Tags</span></Link>
This way, you are saying that your CSS rules should override already existing ones. Though, you should try to avoid using the !important keyword, unless extreme cases;
<Link to='/tags' class='myLink'><span>Tags</span></Link> This way, first you give a class to the link you want in red, then you need to write some a CSS rule:
a.myLink:link, a.myLink:visited, a.myLink:hover, a.myLink:active {
color: red;
}
Of course, whit this rule you will the red link anytime (if you click it, if you are hover it,..) You can customize that by dividing the CSS rules.

How to make an input field as wide as possible inside a menu item in a top menu using semantic-ui-react

I have a header for my app. And it is a menu with many items. I have a menu.item which wraps an input field (its purpose is to search the given input site-wide). I want that menu.item to be as wide as the remaining space with input field as its children. My problem is very similar to this visually. And yes, I have tried fluid prop in many permutations, unfortunately it did not help. Any help or insight on this problem? My Sample code is below and related codepen is here.
<Menu inverted={true} fixed="top" size="small" color="violet">
<Menu.Item as="a" header={true} >
<Icon inverted={true} size="big" name="image" />
</Menu.Item>
<Container fluid={true}>
<Menu.Item >
<Input
inverted={true}
transparent={true}
icon="search"
iconPosition="left"
placeholder="Search.."
/>
</Menu.Item>
</Container>
<Menu.Item as="a" header={true} position="right">
<Icon inverted={true} size="big" name="mail" />
</Menu.Item>
</Menu>
Semantic UI uses flexbox styles on their responsive menu. This not as much of a Semantic UI React issue as it is a CSS issue. I do not believe there is a class that exists in Semantic UI styles to make a menu item grow. You'll have to solve this with CSS. It only requires one change.
The Menu is display:flex in CSS. The Menu.Item components are all children. The one with the search inside should have this added as an inline style: style={{ flexGrow: 2 }}
You also don't need the Container component. Here's everything:
<Menu inverted={true} fixed="top" size="small" color="violet">
<Menu.Item as="a" header={true}>
<Icon inverted={true} size="big" name="image" />
</Menu.Item>
<Menu.Item style={{ flexGrow: 2 }}>
<Input
inverted={true}
transparent={true}
icon="search"
iconPosition="left"
placeholder="Search..."
/>
</Menu.Item>
<Menu.Item as="a" header={true} position="right">
<Icon inverted={true} size="big" name="mail" />
</Menu.Item>
</Menu>
And here is a working codesandbox example: https://codesandbox.io/s/5x0x6ppm3k

Semantic-UI-react fixed sidebar

Have Googled, searched within semantic ui's docs and issues page, and searched within stackoverflow. Couldn't find the answer.
Within Semantic-ui-react, how do I make a sidebar whose content is fixed to the screen? What I currently have is this:
<Sidebar.Pushable as={Segment}>
<Sidebar
id="sidebar"
as={Menu}
animation="overlay"
direction="right"
visible={this.state.visible}
vertical
inverted
>
{this.getMenuItems()}
</Sidebar>
<Sidebar.Pusher>
<Route path="/" component={Filler} />
</Sidebar.Pusher>
</Sidebar.Pushable>
There doesn't seem to be any word in it in the semantic-ui-react documentation, and making Sidebar.Pushable, Sidebar, or any of the Menu Items position:fixed; doesn't seem to work either.
I was able to achieve a sticky sidebar with the help of this answer.
Basically, it states that in order to have a fixed sidebar that sticks to the our infinite scrolling page, we must remove the transform attribute
on the parent container. The reasoning is because the transform changes the positioning context from the viewport to the
rotated element. As a result, the "fixed" child element, behaves as if it has "absolute" positioning.
I added this to the sidebar.overrides file
/* Page Context */
.pushable:not(body) {
transform: none;
}
.pushable:not(body) > .ui.sidebar,
.pushable:not(body) > .fixed,
.pushable:not(body) > .pusher:after {
position: fixed;
}
This solution is meant for the base semantic-ui library. Since semantic-ui-react requires semantic-ui, this ends up working for semantic-ui-react sidebars as well.
Give a try with below code.
<Sidebar as={Menu} animation='overlay' icon='labeled' inverted vertical visible width='wide'>
<Menu.Item as={Link} to="/admin">
<Icon name='building' />
Rubykraft
</Menu.Item>
<Menu.Item as='a'>
<Icon name='user' />
Shan
</Menu.Item>
<Menu.Item as='a'>
<Icon name='user' />
Vishnu
</Menu.Item>
</Sidebar>
I've used classes from semantic-ui's Sidebar module to create the desired fixed sidebar. If you want a more Component(ish) code, you should replace the pusher class with it's correspondent Sidebar.Pusher Component.
Here's my code:
import React, { Component } from 'react'
import { Dropdown, Icon, Input, Menu } from 'semantic-ui-react'
export default class MySidebar extends Component {
state = {}
handleItemClick = (e, { name }) => this.setState({ activeItem: name })
componentDidMount() {}
render() {
const { activeItem } = this.state
return(
<div className='pusher'>
<div className='full height'>
<div className='toc'>
<Menu className='inverted vertical left fixed'>
<Menu.Item>
Home
<Icon name='dashboard' />
<Menu.Menu>
<Menu.Item name='search' active={activeItem === 'search'} onClick={this.handleItemClick}>
Search
</Menu.Item>
<Menu.Item name='add' active={activeItem === 'add'} onClick={this.handleItemClick}>
Add
</Menu.Item>
<Menu.Item name='about' active={activeItem === 'about'} onClick={this.handleItemClick}>
Remove
</Menu.Item>
</Menu.Menu>
</Menu.Item>
<Menu.Item name='browse' active={activeItem === 'browse'} onClick={this.handleItemClick}>
<Icon name='grid layout' />
Browse
</Menu.Item>
<Menu.Item name='messages' active={activeItem === 'messages'} onClick={this.handleItemClick}>
Messages
</Menu.Item>
<Dropdown item text='More'>
<Dropdown.Menu>
<Dropdown.Item icon='edit' text='Edit Profile' />
<Dropdown.Item icon='globe' text='Choose Language' />
<Dropdown.Item icon='settings' text='Account Settings' />
</Dropdown.Menu>
</Dropdown>
</Menu>
</div>
<div className='article'>
<div>Content</div>
</div>
</div>
</div>
)
}
}
And the style:
.toc {
width: 200px;
}
.article {
margin-left: 210px;
}
Everything is easier!
<Sidebar.Pusher style={{overflow: 'scroll', height: '100%'}}>
I think you yourself will understand why this works.
You would need to manually do it with some CSS/SCSS. Basically, you need to set the height to a fixed value.
#media only screen and (max-width: 768px) {
.ui.wide.left.sidebar, .ui.wide.right.sidebar {
height: 100vh !important;
position: absolute;
}
.pusher {
margin-left: 20px;
}
}
.pushable {
min-height: 100vh;
}
.ui.wide.left.sidebar, .ui.wide.right.sidebar {
height: 100vh;
position: fixed !important;
bottom: 0px !important;
top: 0px !important;
}
Based on the Semantic React documentation, there's an obvious way to do this, but the behavior it produces is extremely wonky: the desktop sidebar menu sticks to the top of the window as expected until you scroll near the bottom, then zooms down and attaches to the BOTTOM of the screen.
Pretty awful. This appears to be a solid fix. I've only tested it in my own setup, but it should be fairly universal, or at least a good starting point!
In order to get the sticky sidebar/mobile overlay combo described above, you would expect the relevant part of your _app.jsx to look something like this. NOT THE ONLY WAY! But also not the point, adapt to your own situation. For clarity, anything below prefixed with my... is your responsibility.
// _app.jsx
<Sidebar.Pushable>
<Sticky>
<Sidebar
as={Menu}
animation="overlay"
direction="left"
inverted
onClick={myOnHideSidebar}
onHide={myOnHideSidebar}
size="huge"
vertical
visible={mySidebarVisible}
>
<MySidebarItems />
</Sidebar>
</Sticky>
<Sidebar.Pusher dimmed={mySidebarVisible}>
<Container>
<MyPageHeader />
<Grid>
<Grid.Row>
<Grid.Column computer={4} only="computer">
<Menu fluid size="huge" vertical>
<MySidebarItems />
</Menu>
</Grid.Column>
<Grid.Column mobile={16} tablet={16} computer={12}>
<Component {...pageProps} />
</Grid.Column>
</Grid.Row>
</Grid>
<MyPageFooter />
</Container>
</Sidebar.Pusher>
</Sidebar.Pushable>
In practice, this produces the weird behavior I described above.
Here's the fix. Look for the STICKYFIX comments, and note the stylesheet entry, which is necessary because of the -webkit style.
// _app.jsx
<Sidebar.Pushable style={{ transform: 'none' }}> // STICKYFIX
<Sticky>
<Sidebar
as={Menu}
animation="overlay"
direction="left"
inverted
onClick={myOnHideSidebar}
onHide={myOnHideSidebar}
size="huge"
vertical
visible={mySidebarVisible}
>
<MySidebarItems />
</Sidebar>
</Sticky>
<Sidebar.Pusher
dimmed={mySidebarVisible}
style={{ minHeight: '100vh' }} // STICKYFIX
>
<Container>
<MyPageHeader />
<Grid>
<Grid.Row>
<Grid.Column computer={4} only="computer">
<Menu className="sidebar-menu" fluid size="huge" vertical> // STICKYFIX
<SidebarItems />
</Menu>
</Grid.Column>
<Grid.Column mobile={16} tablet={16} computer={12}>
<Component {...pageProps} />
</Grid.Column>
</Grid.Row>
</Grid>
<MyPageFooter />
</Container>
</Sidebar.Pusher>
</Sidebar.Pushable>
// styles.css
.sidebar-menu {
position: sticky;
position: -webkit-sticky;
top: 20px;
}
Here's my gist detailing the fix.

Resources