Sticky content scrolling up into fixed menu header Semantic UI - reactjs

So I've set up some sticky rail content using an example for the SUIR docs. However, when scrolling the main content, the rail content scrolls into my fixed header.
Do I need to set more rules on the style prop for <Rail>?
Codesandbox link here
To view the issue, navigate to Docs from the menu bar.
The <Rail> component is at the bottom of Overview.js file
export default class Overview extends Component {
contextRef = createRef();
render() {
return (
<div>
<FixedMenuLayout />
<Grid centered columns={3} style={{ marginTop: "7em" }}>
<Grid.Column>
<Ref innerRef={this.contextRef}>
<Segment>
<Docs />
<Rail position="left">
<Sticky context={this.contextRef}>
<Header as="h3">Getting Started</Header>
<List style={{ padding: "5px" }}>
<List.Item>Overview</List.Item>
<List.Item>Examples</List.Item>
<List.Item>Tutorial</List.Item>
</List>
<Header as="h3">How To</Header>
<List style={{ padding: "5px" }}>
<List.Item>Building</List.Item>
<List.Item>Standalone</List.Item>
<List.Item>Deployment</List.Item>
</List>
<Header as="h3">Development</Header>
<List style={{ padding: "5px" }}>
<List.Item>Road Map</List.Item>
<List.Item>Upcoming Features</List.Item>
</List>
</Sticky>
</Rail>
<Rail position="right">
<Sticky context={this.contextRef}>
<Header as="h3">Overview</Header>
<List style={{ padding: "5px" }}>
<List.Item>Overview</List.Item>
<List.Item>Examples</List.Item>
<List.Item>Tutorial</List.Item>
</List>
</Sticky>
</Rail>
</Segment>
</Ref>
</Grid.Column>
</Grid>
</div>
);
}
}

Well a rather easy fix just didn't see the correct prop that handles this exact issue.
The offset prop for <Sticky> needs to be set to an appropriate value.
In my case,
<Sticky offset={90} context={this.contextRef}>

Related

Some images not loading on github pages after deploying. React

Hi I deployed a new react app to ghpages. One of the pages has a Tab Container with 3 Nav Items that serve as a link. The first tab which auto loads with the page shows all the images correctly. The second and third tab do not show the pages. These images are rendered properly when I run it locally. They are all coded the same way. Anyone know how to solve this?
Link to ghpages https://johntrieseverything.github.io/starcraft2-unit-counter/
The error occurs under the "Units List" section when selecting the second or third tab.
Here is what my code looks like:
<Tab.Container defaultActiveKey="Protoss" >
<Container fluid className='unitListDisplayBackground'>\
<Row style={{ height: '10vh' }}></Row>
<Row className='mt-5'>
<h1>Units List</h1>
<p>This is a page where you can view all playable units and see their stats</p>
</Row>
<Row>
<Nav fill variant='tabs' defaultActiveKey="/home">
<Nav.Item >
<Nav.Link
style={{ backgroundColor: '#393e46', color: '#ADD8E6', marginBottom: '1vh' }}
eventKey="Protoss">
<img
src={process.env.PUBLIC_URL + "/assets/Icons/Protoss Icon.png"}
alt='Protoss Icon'
style={{ width: '50px', height: '50px' }}
/></Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
style={{ backgroundColor: '#393e46', color: '#ADD8E6', marginBottom: '1vh' }}
eventKey="Zerg">
<img
src={process.env.PUBLIC_URL + "/assets/Icons/Zerg Icon.png"}
alt='Zerg Icon'
style={{ width: '65px', height: '50px' }}
/>
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
style={{ backgroundColor: '#393e46', color: '#ADD8E6', marginBottom: '1vh' }}
eventKey="Terran">
<img
src={process.env.PUBLIC_URL + "/assets/Icons/Terran Icon.png"}
alt='Terran Icon'
style={{ width: '50px', height: '50px' }}
/>
</Nav.Link>
</Nav.Item>
</Nav>
<Tab.Content>
<Tab.Pane eventKey="Protoss" style={{ textAlign: 'center' }}>
{/* Display the Protoss Units */}
<ProtossUnits />
</Tab.Pane>
<Tab.Pane eventKey="Zerg" style={{ textAlign: 'center' }}>
{/* Display the Zerg Units */}
<ZergUnits />
</Tab.Pane>
<Tab.Pane eventKey="Terran" style={{ textAlign: 'center' }}>
{/* First 3 Terran units */}
<TerranUnits />
</Tab.Pane>
</Tab.Content>
</Row>
</Container>
</Tab.Container>
Another issue I'm having is the 404 error on page refresh. I read that the Hashbrowser is a quick work around but the react router doc says its not recommended. What are some other potential solutions?
Code for routing:
class App extends Component {
render() {
return (
<div>
<BrowserRouter basename="starcraft2-unit-counter">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/UnitsList" element={<UnitsList />} />
<Route path="/UnitCountersPage" element={<UnitCountersPage />} />
<Route path="/ArmyCounterPage" element={<ArmyCounterPage />} />
</Routes>
</BrowserRouter>
</div>
)
}
}
Thank you!
Tried looking online for similar problems but couldn't find one..

Progress bar component not showing up within Group/Stack

Whenever I try to place a progress bar inside a Group/Stack, it does not show up on my webpage. It works only when I place it outside the Group/Stack. Here is the code and results:
import { Stack, ThemeIcon, Text, Progress, Group, Button } from "#mantine/core";
interface SkillProps {
name: string;
icon: JSX.Element;
}
function Skill(props: SkillProps) {
return (
<>
<Group>
<ThemeIcon size={50} radius={25} variant="outline">
{props.icon}
</ThemeIcon>
<Stack align="center" spacing={5}>
<Text>{props.name}</Text>
</Stack>
<Progress value={50} />
</Group>
</>
);
}
export default Skill;
When placed within Group/Stack: Result
When placed outside Group/Stack: Result
Anyone has any idea why this is happening?
It seems that this might be because Progress does not have a specified width from parent container when in Group or Stack.
For use in Group, try add flex:"1" to Progress with the sx prop, which will make it take the remaining space in Group:
<Group>
<ThemeIcon size={50} radius={25} variant="outline">
{props.icon}
</ThemeIcon>
<Stack align="center" spacing={5}>
<Text>{props.name}</Text>
</Stack>
<Progress value={20} sx={{ flex: "1" }} />
</Group>
For use in Stack, try add alignSelf: "stretch" instead for similar result:
<Group>
<ThemeIcon size={50} radius={25} variant="outline">
{props.icon}
</ThemeIcon>
<Stack align="center" spacing={5}>
<Text>{props.name}</Text>
<Progress value={20} sx={{ alignSelf: "stretch" }} />
</Stack>
</Group>

react-infinite-scroll not working inside Material UI Drawer

I am currently using react-infinite-scroll-component to paginate the comments from a certain post. There is a button in the comment section which shows a drawer that is supposed to show the paginated comments. The problem is, the react-infinite-scroll-component doesn't work, as it does not fire
the "next" function.
Here is the code:
<div>
<Drawer
anchor={"bottom"}
open={open}
onClose={handleDrawer}
style={{ height: "100vh", overflow: "auto", margin: "0px 4px" }}
>
<Toolbar>
<Typography variant="h4" style={{ flexGrow: 1 }}>
Comments
</Typography>
<IconButton onClick={handleDrawer}>
<CloseIcon />
</IconButton>
</Toolbar>
<Divider />
<br />
<CommentForm
comment={comment}
handleChange={handleChange}
handleSubmit={handleSubmit}
/>
<InfiniteScroll
dataLength={page}
next={More}
hasMore={hasMore}
loader={
<>
<br />
<CircularProgress />
</>
}
style={{
overflow: "hidden",
}}
scrollThreshold={1}
>
<CommentList comments={comments} id={session.id} />
</InfiniteScroll>
</Drawer>
</div>
The drawer is mostly similar to Youtube's comment drawer on the mobile app. Is there anything I am missing here?
Probably, the problem is the relation with Drawer and Infinite Scroll height. The height of Infinite Scroll is not reaching the right point to trigger next function. If you provide the demo in Codesandbox would be easier to understand.
Fixed height of infinite scroll container
<Box sx={{ height: 500 }}>
<InfiniteScroll
dataLength={page}
next={More}
hasMore={hasMore}
loader={
<>
<br />
<CircularProgress />
</>
}
style={{
overflow: "hidden",
}}
scrollThreshold={1}
>
<CommentList comments={comments} id={session.id} />
</InfiniteScroll>
</Box>

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.

How to make a Drawer like in Google Inbox with Material-UI

I'm building an app with Meteor, React and Material-UI. I have a custom left nav component based on Drawer.
class LeftNav extends Component {
constructor(props){
super(props);
}
render() {
return (
<Drawer open={this.props.open}
docked={false}
onRequestChange={this.props.handleOnRequestChange}
>
<Card >
<CardMedia overlay={<div><Avatar src='avatar.png' size={50} style={styles.avatar} /> <CardTitle title="Phil Cruz" subtitle="phil#philcruz.com" titleColor={darkWhite} subtitleColor={lightWhite}/></div>} >
<img src="/left_nav_wallpaper.jpg" />
</CardMedia>
</Card>
<MenuItem primaryText="testdomain1.com" leftIcon={<ActionGrade />} />
<MenuItem primaryText="testdomain2.com" leftIcon={<ActionHttp />}/>
<MenuItem primaryText="Add site..." leftIcon={<ContentAdd />} />
<Divider />
<MenuItem primaryText="Settings" leftIcon={<Settings />} />
<MenuItem primaryText="Help & About" leftIcon={<HelpOutline />} />
</Drawer>
);
}
};
I want to make it so it behaves like the Google InBox left nav/drawer. It has 3 sections: The top with the cover image and avatar, middle section and the bottom section.
I want the same behavior where:
the bottom menu items are fixed to the bottom (in red in the below
image)
the top section can scroll
How can I do that?
By reading these questions/answers:
How to create a sticky footer inside the LeftNav?
Get viewport/window height in ReactJS
Reactjs - Rerender on browser resize
I was able to come up with a solution. Basically, you need to put the content in 2 divs. Use absolute positioning in the bottom div to make it fixed to the bottom. You then need to calculate the height of the top div based on the height of the window minus the height of the footer div. Listen to the resize window event so you can update the div height manually as the browser is resized.
Here's the code:
class LeftNav extends Component {
constructor(props){
super(props);
this.state = { };
this.updateDimensions = this.updateDimensions.bind(this);
}
componentDidMount(){
this.updateDimensions();
window.addEventListener("resize", this.updateDimensions);
}
updateDimensions() {
this.setState({
height: window.innerHeight,
footerHeight: document.getElementById('leftNavFooter').clientHeight
});
}
render() {
return (
<Drawer open={this.props.open}
docked={false}
onRequestChange={this.props.handleOnRequestChange}
>
<div style={{overflowY: 'auto', overflowX: 'hidden', height: (this.state.height - this.state.footerHeight) + 'px'}}>
<Card >
<CardMedia overlay={<div><Avatar src='avatar.png' size={50} style={{ marginLeft: 16 }} /> <CardTitle title="Phil Cruz" subtitle="phil#philcruz.com" titleColor={darkWhite} subtitleColor={lightWhite}/></div>} >
<img src="/left_nav_wallpaper.jpg" />
</CardMedia>
</Card>
<Menu>
<MenuItem primaryText="testdomain1.com" leftIcon={<ActionGrade />} />
<MenuItem primaryText="testdomain2.com" leftIcon={<ActionHttp />}/>
<MenuItem primaryText="Add site..." leftIcon={<ContentAdd />} />
</Menu>
</div>
<div id="leftNavFooter" style={{position: 'absolute', bottom: 0, width: '100%', overflow: 'hidden'}}>
<Divider />
<Menu>
<MenuItem primaryText="Settings" leftIcon={<Settings />} />
<MenuItem primaryText="Help & About" leftIcon={<HelpOutline />} />
</Menu>
</div>
</Drawer>
);
}
};

Resources