Skip to content

Instantly share code, notes, and snippets.

@karmaniverous
Last active October 24, 2022 02:31
Show Gist options
  • Save karmaniverous/1f6174ccf54e6f1ca346f6cf2e8f9ad5 to your computer and use it in GitHub Desktop.
Save karmaniverous/1f6174ccf54e6f1ca346f6cf2e8f9ad5 to your computer and use it in GitHub Desktop.
Semantic React: Sticky Sidebar Inside Sidebar.Pushable

This gist is related to this Semantic React issue. The Semantic team closed the issue without actually fixing it: they just documented the problem and moved on. I NEEDED a fix, so here it is.

In brief, there's a use case for having a sticky menu in a desktop setting that turns into a sticky pushable overlay menu in a mobile setting.

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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment