How to create Tab Bar header as Fixed/Sticky in React/Antd? - css

I need to make fixed my tab bar headers which is opening in a drawer. Here is what I have tried.
Antd recommends react-sticky lib. Somehow it does not work. Maybe the reason is drawer scroll etc. Even if I hide the drawer scroll and create a scroll for tab body, sticky is not worked.
Ant Sticky Referans : https://ant.design/components/tabs/
react-sticky package : https://www.npmjs.com/package/react-sticky
position: -webkit-sticky;
position: sticky;
top: 0;
I also tried hard css but it does not work as well.

I look for Antd how handles the subject : fixed/sticky [sth]. So I find out Header from Layout component. Setting the style position fixed solved my problem. May be this is not a perfect solution but at least now in a drawer Tab Bar Headers are fixed.
Final codes are :
const renderTabBar = (props, DefaultTabBar) => (
<Layout>
<Header style={{ position: 'fixed', zIndex: 1, top: 0, padding: 0, width: '100%',
background: 'white' }}>
<DefaultTabBar {...props} style={{
top: 20,
}} />
</Header>
</Layout>
);
<Drawer
placement="right"
onClose={onClose}
visible={visible}
getContainer={false}
title={<> </>}
style={{ position: 'absolute' }}
width={"25%"}
keyboard={true}
closable={true}
closeIcon={<CloseOutlined />}
mask={false}
maskClosable={false}
headerStyle={{ border: 'none' }}>
<Tabs tabPosition="top"
renderTabBar={renderTabBar}
animated={true}
style={{ paddingTop: 20 }}>
{tabBody}
</Tabs>
</Drawer >

Related

Centering Buttons in Material-UI and React

I have successfully centered the Hello There button.
But my problem is, a little bit of lines are appearing on it.
I could put a background-color: white to solve it, but is there a better way to do this and a better coding? Like not using position: absolute etc....?
CLICK HERE FOR CODESANDBOX
<Stack
alignItems={"center"}
sx={{
marginTop: 2,
position: "absolute",
display: "flex",
left: 0,
right: 0
}}
>
<Button variant="outlined">Hello There</Button>
</Stack>
The Button variant you are using is the varian="outlined" which has a transparent background. So when is positioned above the dashed border they are shown behind it. In this case if you wan to keep this style of Button you have to add a background-colour of white to it.
Another option would be to use the contained variant like below but this would change the style of the button.
<Button variant="contained">
Hello there
</Button>
UPDATED:
or (for any reason you don't want to add the background colour to the button) you can add using :after or :before at the button, an element that will be behind the button and hide the dashed border. As a solution is not optimal as this will not work for dynamic backgrounds, or if they have an image or even a gradient color.
<Button
variant="outlined"
sx={{
position: "relative",
zIndex: "1",
"&:before": {
content: `''`,
background: "white",
width: "100%",
height: "10px",
position: "absolute",
zIndex: "-1"
}
}}
>
Hello There
</Button>
I think your question should be clearer but here is the answer of what I am thinking.
<Stack
sx={{
marginTop: 2,
position: "absolute",
width: "100%"
}}
>
<Button
variant="outlined"
sx={{
margin: "0px auto"
}}
>
Hello There
</Button>

Next.js Image Fill in Masonry List

I'm facing issue where normal HTML img tag works just fine inside my Masonry List, but when I'm using Next.js Image Component with layout fill, it doesn't render anything.
My Styles:
const ImageList = styled('ul', {
columnCount: 3,
columnGap: 10,
display: 'block',
listStyleType: 'none',
overflowY: 'auto',
padding: 0,
margin: 0
})
const ImageListItem = styled('li', {
position: 'relative',
display: 'inline-block',
lineHeight: 0,
height: 'auto',
marginBottom: 10
})
HTML Skeleton:
<ImageList>
{detailImage.map((image, idx) => {
return (
<ImageListItem key={`_${idx}`}>
<Image
src={image.src}
alt={image.alt}
blurDataURL={image.blurDataURL}
placeholder={'blur'}
layout={'fill'}
objectFit={'cover'}
/>
{/* <img
src={image.src}
style={{
width: '100%',
height: '100%',
objectFit: 'cover'
}}
/> */}
</ImageListItem>
)
})}
</ImageList>
EDIT
Because I'm getting all images from CMS and have width/height I used the padding-top trick to create box and then I use next/image with object-fit: cover.
Code Example:
<ImageListItem key={`_${idx}`}>
<Box
css={{
display: 'inline-flex',
pt: `${100 / (image.width! / image.height!)}%`
}}
>
<Box css={{ position: 'absolute', inset: 0, m: 0 }} as={'figure'}>
<Image
src={image.src}
alt={image.alt}
blurDataURL={image.blurDataURL}
placeholder={'blur'}
layout={'fill'}
objectFit={'cover'}
/>
</Box>
</Box>
</ImageListItem>
When you use layout='fill' it's necesary a parent container for each image and this container needs to have position: relative;. Maybe it doesn't show anything because its parent elements don't have the width property.
This is the description in the documentation:
When fill, the image will stretch both width and height to the
dimensions of the parent element, provided the parent element is
relative. This is usually paired with the objectFit property. Ensure
the parent element has position: relative in their stylesheet.

how can i show the avatar image outside the drawer in mui reactjs?

i am trying to show the avatar image curve outside the sidebar border line.
i took the persistent drawer from mui v5 as an example and here is the codesandbox link
my target is to be like follows
in this example my drawer style is as followed:
<Drawer
sx={{
width: drawerWidth,
flexShrink: 0,
//position: "relative",
"& .MuiDrawer-paper": {
width: drawerWidth,
boxSizing: "border-box"
}
}}
variant="persistent"
anchor="left"
open={open}
>
and the Avatar's style inside the drawer header as followed:
<Avatar
alt="test"
src="./test.jpg"
sx={{
//position: "absolute",
width: "120px",
height: "120px",
marginLeft: "150px"
}}
/>
how can i achieve such style? please help me on this
Add following styles
<Drawer
sx={{
"& .MuiDrawer-paper": {
position: "relative",
overflowY: "visible"
},
}}
>
<Avatar
sx={{
position: "absolute",
top: 20,
right: -60,
}}
/>
Besides setting its position to absolute, you need to divide the Avatar size by 2, then negate it to move half of the Avatar outside of the Drawer. See this example:
<Avatar
sx={{
position: "absolute",
top: 40,
right: -60 / 2, // half the avatar size. negate it to move half outsize
width: 60,
height: 60
}}
{...}
/>

MUI Card text overlay

I'm using the MUI Card and CardMedia components in my app but can't figure out how to overlay text on top of the image. This is a simplified example of what I'm trying:
<Card>
<CardMedia image={this.props.preview} style={styles.media}/>
<div style={styles.overlay}>
this text should overlay the image
</div>
</Card>
const styles = {
media: {
height: 0,
paddingTop: '56.25%' // 16:9
},
overlay: {
position: 'relative',
top: '20px',
left: '20px',
color: 'black',
backgroundColor: 'white'
}
}
I've tried placing the text div in above the CardMedia, below it, inside it, outside the Card entirely, and using different position values but can't figure this out at all. The beta versions of MUI included an overlay property on the CardMedia, but the v1 library doesn't seem to have anything like that.
Any know how to properly do this? Thanks in advance for any help!
Your CSS is off, you'll want to absolutely position the styles.overlay, and make sure the Card is position relative
Try something like this:
<Card style={styles.card}>
<CardMedia image={this.props.preview} style={styles.media}/>
<div style={styles.overlay}>
this text should overlay the image
</div>
</Card>
const styles = {
media: {
height: 0,
paddingTop: '56.25%' // 16:9
},
card: {
position: 'relative',
},
overlay: {
position: 'absolute',
top: '20px',
left: '20px',
color: 'black',
backgroundColor: 'white'
}
}
Use the code below if you want to have an overlay like the Card in version 0. Remember to set the position of the container to relative so the absolute position of the overlay can take effect:
<Card sx={{ maxWidth: 345 }}>
<Box sx={{ position: 'relative' }}>
<CardMedia
component="img"
height="200"
image="https://mui.com/static/images/cards/contemplative-reptile.jpg"
/>
<Box
sx={{
position: 'absolute',
bottom: 0,
left: 0,
width: '100%',
bgcolor: 'rgba(0, 0, 0, 0.54)',
color: 'white',
padding: '10px',
}}
>
<Typography variant="h5">Lizard</Typography>
<Typography variant="body2">Subtitle</Typography>
</Box>
</Box>
{...}
</Card>

MUI Progress Indicator center align horizontally

Stack: Meteor + React + MUI
Here's my full code of my 'main' renderer components:
// Sorry for not giving material-UI CSS,
// cause it cannot be served as stand-alone CSS
render() {
return (
<div className = "container">
<AppBar title = "test" />
<Tabs /> // Tab contents goes here
<RefreshIndicator
left={70} // Required properties
top={0} // Required properties
status="loading"
style={{
display: 'inline-block',
position: 'relative',
margin: '0 auto' }} />
</div>
);
},
I want to make Refresh Indicator horizontally center aligned beneath of myTabs like this whirling circle in this picture :
In the document of MUI here, this indicator comes with following styles:
display: 'inline-block',
position: 'relative',
With this styles I cant align it center horizontally, and without this styles, I can`t even locate it where I wanted.
What I have tried :
margin: 0 auto --> failed
text-align: center --> failed
display: flex --> failed
combination of 1 & 2 --> failed
left={$(window).width/2-20} --> This works but I'd like to use CSS only
The solution below centres progress indicator without any hacky calculations that cause element to be offset:
<div style={{display: 'flex', justifyContent: 'center'}}>
<RefreshIndicator status="loading" />
</div>
Here is how I did to ensure it's horizontally centered. Works great for me.
Set the parent component style to position: 'relative'.
Set the refresh indicator style to marginLeft: '50%', and left={-20} (assuming the size is 40).
here is the code (I put it in a CardText component).
...
<CardText style={{position: 'relative'}}>
<RefreshIndicator
size={40}
left={-20}
top={10}
status={'loading'}
style={{marginLeft: '50%'}}
/>
</CardText>
...
In MUI v5, there is a Stack component which serves as a flexbox container. By default the direction is column, to center it horizontally you can set alignItems to center:
<Stack alignItems="center">
<CircularProgress />
</Stack>
Live Demo
circularprocess in material ui and text middle of page stackoverflow
<div style={{ alignItems: "center", display: "flex", justifyContent: "center", height: "100vh", width: "100vw" }}>
<CircularProgress />
<span style={{ justifyContent: "center", position: "fixed", top: "55%" }}>Loading...please wait</span>
</div>[![enter image description here][1]][1]
The Backdrop Component will place the progress indicator in the center and also can add a dimmed layer over your application. This component is available with MUI V5.
<Backdrop open={enabled} sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}><CircularProgress color="secondary" /></Backdrop>

Resources