Semantic-UI-react fixed sidebar
Asked Answered
A

6

5

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.

Ashburn answered 5/9, 2017 at 16:33 Comment(0)
S
11

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.

Squirmy answered 9/6, 2018 at 3:57 Comment(2)
Yup! Chuck it in semantic/src/modules/sidebar.overrides and then gulp npx build-css. Super helpful response: @Squirmy has the correct answer.Baptlsta
+1. The transform:'none' is the key according to github.com/Semantic-Org/Semantic-UI-React/issues/2897. For anyone who doesn't want to change the Semantic UI CSS file and/or install Gulp, you can add the CSS modification on the element: <Sidebar.Pushable style={{transform: 'none'}}>Yoder
O
2

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>
Optimist answered 10/8, 2018 at 5:14 Comment(1)
This should be the accepted answer. Also you may change it to animation='push' if you want to get a dashboard style out of it.Winn
J
1

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;
}
Jonejonell answered 7/9, 2017 at 18:23 Comment(0)
A
1

Everything is easier!

<Sidebar.Pusher style={{overflow: 'scroll', height: '100%'}}>

I think you yourself will understand why this works.

Arnhem answered 11/3, 2020 at 18:58 Comment(0)
G
0

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;
}
Grayback answered 5/9, 2017 at 16:45 Comment(0)
B
0

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.

Beamer answered 24/10, 2022 at 2:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.