How to make a dropdown notification list with and React? - css

Im trying to create a dropdown of notifications like Facebook using antd, React and components: Dropdown, List, Badge.
Actually the dropdown works, but the list of items render overlay the window, I don't know if I can render list inside dropdown or if only I must change sizes of the components:
const data = [
{
title: 'Ant Design Title 1',
},
{
title: 'Ant Design Title 2',
},
{
title: 'Ant Design Title 3',
},
];
const HeaderComp = (props) => {
return (
<Layout>
<Header className="header" style={{position:'fixed', zIndex: 1, width: '100%'}}>
<div style={{float:'left', marginRight:'5%'}}>
<img style={{width: 120, height:31}} src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Suzuki_Motor_Corporation_logo.svg/2560px-Suzuki_Motor_Corporation_logo.svg.png"/>
</div>
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['1']} >
<Menu.Item key="1" onClick={()=>navigation(root)}>Home</Menu.Item>
<Menu.Item key="3">About</Menu.Item>
</Menu>
<div style={{float:'right', marginLeft:'5%'}}>
<Dropdown overlay={<List itemLayout="horizontal"
dataSource={data}
renderItem={item => (
<List.Item style={{maxWidth:'50%'}}>
<List.Item.Meta
title={{item.title}}
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
/>
</List.Item>
)}
/>}>
<Badge count={notifications.length} size="small">
<BellOutlined style={{fontSize:'170%'}}/>
</Badge>
</Dropdown>
</div>
</Header>
</Layout>
)
}

Related

Framer Motion Page Transition Next JS Router.push

I made the following using the nextjs and framer motion
I have a list of images that I'm mapping over and assigning them a layoutid and an optional variant to animate. The layoutid corresponds to the layoutid on the model1, model2, model3 pages.
Current Behaviour
When first going to the home page and clicking on an image I update some state and set the variant animation to false, this then tells that image to use the layoutid, it then fades out the other images and animates the clicked image into place on the component that is loaded (model1, model2, model3)...Great it works!
If you then click home in the navigation and try clicking an item again it doesn't work, all images are faded out and the clicked image doesn't animated.
Click refresh on the homepage and it works as desired!
here is the code for the page, I suspect it could be something to do with the routing or settings in _app.js
export default function Home() {
const router = useRouter();
const [isClicked, setIsClicked] = useState(null);
const onHandlerClick = (item, href, e) => {
e.preventDefault();
setIsClicked(item);
router.push(href, { scroll: false });
};
return (
<div className="l-grid l-grid-outter">
<div className="c-home-maincontent">
<div>
<main>
<motion.div className="l-grid-3-col" initial="initial" animate="enter" exit="exit" variants={{ exit: { transition: { staggerChildren: 0.1 } } }}>
{images.map((item, index) => {
return (
<motion.div
key={index}
className="c-home-overflowimage c-home-overflowimage2"
layoutId={`imageAnimation${item}`}
variants={isClicked === item ? false : postVariants}
transition={{ ...transition }}
>
<a href={`/model${item}`} onClick={(event) => onHandlerClick(item, `/model${item}`, event)}>
<motion.img
src="/yasmeen.webp"
whileHover={{
scale: 1.1,
}}
/>
</a>
</motion.div>
);
})}
</motion.div>
</main>
</div>
</div>
<Footer />
</div>
);
}
function MyApp({ Component, pageProps }) {
const router = useRouter();
return (
<>
<DefaultSeo {...Seo} />
<AnimateSharedLayout type="crossfade">
<AnimatePresence exitBeforeEnter initial={false}>
<Component {...pageProps} key={router.asPath} />
</AnimatePresence>
</AnimateSharedLayout>
</>
);
}
export default MyApp;
Updated the code to include an animate set to false if its the clicked item
<motion.div className="l-grid-3-col" initial="initial" animate="enter" exit="exit">
{images.map((item, index) => {
return (
<motion.div
key={index}
className="c-home-overflowimage c-home-overflowimage2"
layoutId={`imageAnimation${item}`}
animate={isClicked === item ? false : true}
variants={isClicked === item ? false : postVariants}
transition={{ ...transition }}
>
<a href={`/model${item}`} onClick={(event) => onHandlerClick(item, `/model${item}`, event)}>
<motion.img
src="/yasmeen.webp"
whileHover={{
scale: 1.1,
}}
/>
</a>
</motion.div>
);
})}
</motion.div>

How to have multiple row tabs in Material UI Tabs

I have almost 30 tabs inside Material UI Tabs, the user has to scroll two times to see all the tabs, I would like to show the tabs in two rows with scroll instead of one row with scroll, this will help the user to see most of the tabs in one glance.
How can I do something like this ?, I looked over Material UI document but i couldn't find anything useful, I tried manually giving it CSS style but I wasn't able to achieve my goal (my CSS skills are mediocre).
To show what I mean by multiple row tabs, here is a sample image :
Any help is much appreciated.
I did a little hack:
Use 2 different Tabs components and adjust indexes:
<Box sx={{ display: 'flex',justifyContent: 'center', flexWrap: 'wrap'}}>
<Tabs value={value} onChange={handleChange}>
<Tab label='Precios'/>
<Tab label='Usuarios'/>
<Tab label='Plan'/>
</Tabs>
<Tabs value={value - 3 } onChange={handleChange2}>
<Tab label='Empleados'/>
</Tabs>
</Box>
And manage change for this adjustment:
const handleChange = (event, newValue) => {
setValue(newValue);
};
const handleChange2 = (event, newValue) => {
setValue(newValue + 3);
};
You just change the number 3 for the number of tabs in your first component.
Saludos
I am struggling with similar problem. I have gone throw the documentation and looks like this is not possible using Tabs/Tab features. For now I can see two options:
Use properties variant="scrollable" and scrollButtons="auto" like mentioned above. This will not give you what you expected but at least it is working.
Implement your own tabs. You can use Grid for it. Below example is just to show an approach. It is not redy solution, but it can be easily adjusted.
const useStyles = makeStyles((theme) => ({
navigationLinkContainer: {
// up to you
},
navigationLinkButtonActive: {
color: '#ffffff',
// up to you
},
}));
const NavigationLink = (props) => {
const classes = useStyles();
return (
<Grid item className={classes.navigationLinkContainer}>
<Button
component={Link}
onClick={props.onClick}
>
{props.children}
</Button>
</Grid>
);
};
const NavigationHeaders = (props) => {
const classes = useStyles();
const { headers, className } = props;
const [activeTab, setActiveTab] = React.useState('');
const isActive = (headerId) => headerId === activeTab;
return (
<>
<Grid container >
{headers.map((header) => (
<NavigationLink
className={classnames(isActive(header.id) && classes.navigationLinkButtonActive)}
key={header.id}
onClick={() => setActiveTab(header.id)}
>
{header.title}
</NavigationLink>
))}
</Grid>
{/* some content here shown base on activeTab */}
</>
);
};
I also came to the conclusion that this is not currently possible with Tabs/Tab. I tried using <br />, <hr />, <Divider />, functions to insert breaks, making multiple rows of tabs (which messed up selection), wrapping Tabs in span with max-width (also messed up selection), you name it. I ultimately decided to use scroll on small screens.
I figured out the smallest screen size that would show my tabs properly, then used scroll for any smaller.
const mql = window.matchMedia('(max-width: 2000px)');
const smallScreen = mql.matches;
<Tabs
value={tabValue}
onChange={handleTabChange}
orientation="horizontal"
variant={smallScreen ? 'scrollable' : 'standard'}
centered={!smallScreen}
>
<Tab label="1" />
<Tab label="1" />
<Tab label="3" />
<Tab label="4" />
<Tab label="5" />
</Tabs>
You could add an event handler to change on resize, but was not necessary for my use case
You can set flexWrap: 'wrap' in the tab container component which is a flexbox:
<Tabs
// disable the tab indicator because it doesn't work well with wrapped container
TabIndicatorProps={{ sx: { display: 'none' } }}
sx={{
'& .MuiTabs-flexContainer': {
flexWrap: 'wrap',
},
}}
{...}
>
https://codesandbox.io/s/69733826-material-ui-responsive-tabs-5q57p?file=/demo.js
Try going through the doc of any stuff you use to safe unnecessary problems in future
visit this for more details and full code https://material-ui.com/components/tabs/
<div className={classes.root}>
<AppBar position="static">
<Tabs value={value}
onChange={handleChange}
aria-label="simple tabs example"
indicatorColor="primary"
textColor="primary"
variant="scrollable"
scrollButtons="auto"
aria-label="scrollable auto tabs example"
>
<Tab label="Item One" {...a11yProps(0)} />
<Tab label="Item Two" {...a11yProps(1)} />
<Tab label="Item Three" {...a11yProps(2)} />
</Tabs>
</AppBar>
<TabPanel value={value} index={0}>
Item One
</TabPanel>
<TabPanel value={value} index={1}>
Item Two
</TabPanel>
<TabPanel value={value} index={2}>
Item Three
</TabPanel>
</div>
Edit: please notice the variant in Tabs

how to make padding for Drawer in react js material ui

I have Drawer class component and I want to make marginTop for that Drawer, but I can't this is my code
const theme = createMuiTheme({
root: {
marginTop: '40px'
},
})
class PageMenu extends React.Component {
render () {
return (
<div>
<Drawer
classes={{paper: classes.drawerPaper }}
>
<List>
{['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
<Divider />
</Drawer>
</div>
)}
i want to make it working in class component
You can just add another class name to it and then style it in your CSS file by the following lines of code:
.classname{
margin-top:yourNumber;
}

adding an image background to a button component in React Typescript

I'm using a material UI library in a React project using react typescript. I want this button to have a picture as a background. However, the button does not accept src or imageURL and returns a typescript error and the css style background doesn't show the picture either. this is my code:
const noticon = require ('./../../images/nicon.png')
const Avatarpic = require ('./../../images/Avatar.png')
const ExampleButton = ({
// useOpenState hook handlers
handleToggle, handleClose, handleOpen, setOpenState, isOpen
}: DropdownButtonProps) => (
<Button onClick={handleToggle} style={{backgroundImage: '{noticon}'}} square>
</Button>
)
function Navbar () {
return (
<>
<TopBar style={{ backgroundColor: '#e6edec' }}>
<TopBarSection>
<TopBarTitle>
<Avatar imgUrl={Avatarpic} name='حسین ساداتی پور' style={{ fontFamily: 'IranSans', fontSize: '20px' }} />
</TopBarTitle>
<Dropdown ButtonComponent={ExampleButton}>
<DropdownItem>Item to click</DropdownItem>
</Dropdown>
</TopBarSection>
{// <TopBarSection>
// burger menu Icon
// </TopBarSection>
}
</TopBar>
<section
style={{
padding: 50,
textAlign: 'center'
}}
>
Some content
</section>
</>
)
}
export default Navbar
you need to do this instead:
<Button onClick={handleToggle} style={{backgroundImage: `url(${noticon})`}} square>

Material-UI dialog font overwriting

I've made a custom User Confirmation Dialog from Material UI Dialog component like here
I faced a problem to overwrite the Dialog's font. I can overwrite color or background color, but fonts in Dialog's header or buttons are inherited from Material-UI. I successfully overwrote Material-UI fonts in other components, but not in this part with callback:
const UserConfirmation = (
message: string,
callback: (shouldNavigate: boolean) => void
) => {
const container = document.createElement('div')
container.setAttribute('custom-confirmation-navigation', '')
document.body.appendChild(container)
const closeModal = (shouldNavigate: boolean) => {
ReactDOM.unmountComponentAtNode(container)
callback(shouldNavigate)
}
ReactDOM.render(
<>
<Dialog
fullWidth={true}
maxWidth="sm"
open={true}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitleWrapper
style={{fontFamily: `BuenosAires !important`, color: `orange`}}
>
Discard draft?
</DialogTitleWrapper>
<DialogContent>
<p> {message} </p>
</DialogContent>
<DialogActionsWrapper>
<Button
onClick={() => closeModal(true)}
fullWidth={true}
variant="outlined"
label="Discard"
/>
<div style={{ width: '80%' }} />
<Button
onClick={() => closeModal(false)}
fullWidth={true}
variant="contained"
label="Cancel"
/>
</DialogActionsWrapper>
</Dialog>
</>,
container
)
}
export default UserConfirmation
Thank Alex
That works brilliant for me:
<DialogTitle disableTypography="true">
Also, buttons' labels were fixed by that:
label={<h5 style={{ textTransform: 'none' }}>Cancel</h5>}
You can use classes object to Override or extend the styles applied to the component.
here
create custom styles like below
const useStyles = makeStyles({
customDialogTitle: {
fontFamily:'Impact'//sans-serif
}
});
and assign to classes
<DialogTitle disableTypography="true"
classes={{
root: classes.customDialogTitle
}}
>
.....
</DialogTitle>
sample sandbox

Resources