How to horizontally align card elements (rmwc) in React? - html

In my parent component:
{
this.state.projectList.map(dat => <Item data = {dat}/>)
}
in the child component Item
render() {
return (
<div style={{'width':'100%', 'textAlign':'center'}}>
<Card style={{ width: '25rem', padding: '1rem', display: 'inline-block' }}>
<CardPrimaryAction>
<div style={{ padding: '0 1rem 1rem 1rem' }}>
<Typography use="headline6" tag="h2">
{this.props.data.name}
</Typography>
<Typography use="body1" tag="div" theme="text-secondary-on-background">
{this.props.data.description}
</Typography>
</div>
</CardPrimaryAction>
</Card>
</div>
);
}
I am using the rmwc Card component to put some stuff.
Right now it just puts all rendered items vertically like a stack. What I actually want is the small sketch in a blue pen on the right side of the image.
I tried to give the wrapping div 'width':'100%', 'textAlign':'center' and the Card itself an inline-block but it's still the same.

In parent component enclose your map function with GridList component of material-ui specifying the required columns. Then enclose your data in GridListTile. This is shown below,
<div>
<GridList cols={2} spacing={16}>
this.state.projectList.map(dat =>
<GridListTile item key={dat} xs={6}>
<Item data = {dat}/>
<GridListTile/>
))}
</GridList>
</div>
In child component, remove the parent <div> and you are good to go.
Please do import necessary dependencies.

Related

Display flex is breaking material-ui grid

I want to implement grid system from material-ui but facing a problem. Resizing the browser window has no effect on my grid items - they don't resize. I found out that this problem is caused by a parent div which has the style property "display": "flex".
I'm using a material-ui app-bar and drawer. Further I've built a reuseable container component for all the content and childrens. Without the style property "display": "flex" my whole page style gets broke. So how can I solve this? Any Idea?
Here is my code and the class root with the property "display": "flex"
Container.tsx
return (
<div className={classes.root}>
<TopBar /> // Material-UI AppBar
<Drawer /> // Reuseable Drawer Component
<main className={classes.contentContainer}>
<div>{children}</div>
</main>
</div>
);
Container Styles
const useStyles = makeStyles((theme: Theme) =>
createStyles({
contentContainer: {
flexGrow: 1,
marginTop: 63,
position: 'relative',
backgroundColor: colors.whiteB_8,
height: `calc(100vh - 63px)`,
// padding: theme.spacing(3),
'& > div:first-child': {
padding: `calc(${theme.spacing(1)}px + 35px)`,
},
},
root: {
display: 'flex',
},
}),
);
Then I can pass any component to this Container. Here my example component, where I want to have 3 columns inside my content container:
return (
<Grid container item xs={12} spacing={2}>
<Grid item xs={4}>
<Paper
style={{ backgroundColor: 'grey' }}
>
Test
</Paper>
</Grid>
<Grid item xs={4}>
<Paper
style={{ backgroundColor: 'grey' }}
>
Test
</Paper>
</Grid>
<Grid item xs={4}>
<Paper
style={{ backgroundColor: 'grey' }}
>
Test
</Paper>
</Grid>
</Grid>
);
The output looks like this:
And the items are not resized:
If I remove "display": "flex" it looks like this - the content is below the drawer:
I can't specifically recreate your issue, but I have a feeling if you add width: '100%' with the display: 'flex' that you say is breaking, it may help with the resizing, as currently the flexbox has no defined width, and so it is just going to shrink and fit to the components inside of it, but not shrink any further when you make the window smaller. As long as you define the width as some relative amount, either % or vw, it should shrink the content inside.

Design of a custom accordion

I am trying to design a custom accordion with these fancy red lines connecting parent and children (see photo).
I am using Grommet components here but in summary, the layout it's just a bunch of divs (the Box tag) and a collapsible panel component for the children(the Collapsible tag). Children panels can be opened and show more content.
After a couple of tries, what I did to connect parent and children is to wrap the outer box with a left-border and then remove the extra border on the bottom using a white box on top of it (the Stack tag of the second example code). The horizontal line connecting the card and the left-border is just a styled div placed next to the Child tab ( inside the SubMenuElement component ).
I think this is quite an intricate solution ( also because I need to make the white box responsive ) but I couldn't think about a simpler one.
Do you have any suggestion on how can I improve or re-do the red connections?
Thanks in advance for the help!
Please note that I am aware all the panels are using the same variables on click
<MenuButton
open={openMenu}
label="PARENT TAB-XYZ"
onClick={() => {
const newOpenMenu = !openMenu;
setOpenMenu(newOpenMenu);
setOpenSubmenu1(!newOpenMenu ? false : openSubmenu1);
}}
/>
<Collapsible open={openMenu}>
<Box background="antiquewhite" margin={{ left: 'small' }} border={{ side: 'left', size: '2px', color: 'red' }}>
{Tabs.map(el => {
return (
<SubMenuElement
key={el.title}
open={openSubmenu1}
label={el.title}
onClick={() => setOpenSubmenu1(!openSubmenu1)}
/>
);
})}
</Box>
</Collapsible>
<MenuButton
open={openMenu}
label="PARENT TAB-POU"
onClick={() => {
const newOpenMenu = !openMenu;
setOpenMenu(newOpenMenu);
setOpenSubmenu1(!newOpenMenu ? false : openSubmenu1);
}}
/>
<Collapsible open={openMenu}>
<Stack anchor="bottom-left">
<Box
background="antiquewhite"
margin={{ left: 'small' }}
border={{ side: 'left', size: '2px', color: 'red' }}
>
{Tabs.map(el => {
return (
<SubMenuElement
key={el.title}
open={openSubmenu1}
label={el.title}
onClick={() => setOpenSubmenu1(!openSubmenu1)}
/>
);
})}
</Box>
<Box background="white" height="39px" width="35px"></Box>
</Stack>
</Collapsible>
</Box>
);
Based on one of my answer for someone who needed a divider, I can propose you something like that: repro on Stackblitz
You will find the original divider code on the first link. for your needs, i modified it a little so it just add the link on the left of the content. There is still a border-left on the content wrapper tho, it seems the easiest solution for me.
Your main file :
import React, { Component } from "react";
import { render } from "react-dom";
import Divider from "./divider";
import "./style.css";
const App = () => {
const toggleAccordion = e => {
e.target.classList.toggle("hidden");
};
return (
<>
<div className="accordion hidden" onClick={toggleAccordion}>
accordion header
<div className="accordion-content-wrapper">
<Divider>
<div>Content</div>
</Divider>
<Divider>
<div>Content</div>
</Divider>
<Divider>
<div>Content</div>
</Divider>
</div>
</div>
</>
);
};
render(<App />, document.getElementById("root"));
My accordion css (your component already have this feature i guess, i just made a minimal reproduction):
.accordion.hidden {
height: 18px;
overflow: hidden;
}
.accordion-content-wrapper{
margin-left: 10px;
border-left: 1px solid black;
}
And for the divider, there not a lot of change from my original answer, here is the code:
import React from 'react';
const Divider = ({ children }) => {
return (
<div className="divider-component">
<div className="container">
<div className="border" />
<span className="content">{children}</span>
</div>
</div>
);
};
export default Divider;
css:
.divider-component .container{
display: flex;
align-items: center;
}
.divider-component .border{
border-bottom: 1px solid black;
width: 15px;
}
.divider-component .content {
width: 100%;
}
Even if you'll have to edit it to fit your needs, the idea is to add a flex container so you can add the little link on the left of your content, correctly aligned with your content.
For whoever will encounter the same issue, I ended up using two 50% height flexboxes inside a div that replace the horizontal line. This allows managing the responsive resize automatically while giving flexibility on the last item border.
const SubMenuElement = ({ last, label, open, onClick }: { last?: boolean; label: string; open: any; onClick: any }) => {
return (
<Box direction="row">
<Line last={last} />
<Box width="100%" margin={{ vertical: 'small' }}>
<Card background="white" onClick={onClick}>
....
</Card>
</Box>
</Box>
);
};
Where the Line is
const Line = ({ last }: { last?: boolean }) => (
<Box direction="column" width="20px" flex="grow">
<Box height="50%" style={{ borderLeft: '1px solid red', borderBottom: '1px solid red' }} />
<Box height="50%" style={last ? {} : { borderLeft: '1px solid red' }} />
</Box>
);

Typography is giving line breaks instead of aligning it in one row

I am using Material ui Typography to display the content in Chip, but my contents are showing up in two different rows instead of one, i do not need line break. Below is my code
<Typography className={classes.title} style={{ display: 'inline' }} color="textSecondary" gutterBottom>
{chipName}
<img src={chipIIcon} style={{ marginLeft: '90%' }} alt="chipIIcon" />
</Typography>
What's wrong in my code and how can i show both chipName and img in same one row?
You can replace the marginLeft: 90% by float: right:
<Typography color="textSecondary" gutterBottom>
{chipName}
<img src={chipIIcon} style={{ float: 'right' }} alt="chipIIcon" />
</Typography>
Or, you can change the display of Typography to flex and set justifyContent to space-between (Ideally you will be using classes instead of inline styling):
<Typography style={{ display: "flex", justifyContent: "space-between"}} color="textSecondary" gutterBottom>
chipName
<img src={"chipIIcon"} alt="chipIIcon" />
</Typography>
Demo

How to vertically center using Responsive React grid system built with styled-components?

I'm using grid-styled to make a layout.
I currently have the following:
How can I make the red/green items vertically centered in the blue container?
Here is my code, am I doing this correctly?
......
const Container = styled(Box)`
max-width: 1100px;
background: violet;
`;
Container.defaultProps = {
mx: 'auto',
};
.....
<Box style={{ backgroundColor: 'darkBlue', minHeight: 500 }}>
<Container>
<Flex wrap>
<Box
p={36}
width={[1, 1 / 2]}
style={{ backgroundColor: 'red' }}
>
{content[0]}
</Box>
<Box
p={36}
width={[1, 1 / 2]}
style={{ backgroundColor: 'green' }}
>
{content[1]}
</Box>
</Flex>
</Container>
</Box>
help appreciated.
You need to pass props to tell the Flex (flexbox) what you are trying to do.
<Flex> accepts the flexDirection align and justify props which will tell it how to align the children.
Try this:
<Flex flexDirection="row" align="center" justify="center" wrap>

Making full-size main content with semantic-UI Sidebar react components

I'm trying to make a Webapp with react using Semantic Ui components. However, I'm really struggling to make the main content component take up the full-size of the screen (see image). I want the main content component to fill up the rest of the space but it seems like it's only taking up as much space as it needs to. Ultimately I want to be able to have the sidebar sticky and only scroll the main content
render() {
const { visible } = this.state
return (
<div>
<Button onClick={this.toggleVisibility}>Toggle Visibility</Button>
<Sidebar.Pushable as={Segment}>
<Sidebar as={Menu} animation='push' width='thin' visible={visible} icon='labeled' vertical inverted>
<Menu.Item name='home'>
<Icon name='home' />
Home
</Menu.Item>
<Menu.Item name='gamepad'>
<Icon name='gamepad' />
Games
</Menu.Item>
<Menu.Item name='camera'>
<Icon name='camera' />
Channels
</Menu.Item>
</Sidebar>
<Sidebar.Pusher>
<Segment basic>
<Header as='h3'>Application Content</Header>
<Image src='/assets/images/wireframe/paragraph.png' />
</Segment>
</Sidebar.Pusher>
</Sidebar.Pushable>
</div>
)
}
I've tried to apply the style inline {height:100%} to everything from within the up the hierarchy to the root component but nothing seems to make it fill the rest of the page. I know that this seems like such a simple problem, but I'm stuck haha. Any ideas?
Cheers
desired outcome
The sidebar will take the same height as its enclosing div. It looks like you want the content to stretch to exactly 100% of the viewport. If this is the case, you can set height on the enclosing div to '100vh'.
<div style={{height: '100vh'}} />
If you want the height to possibly go beyond, you can set min-height to '100vh'.
<div style={{minHeight: '100vh'}} />
If you want it to just take up the rest of the page before or after some other content, you can do the following:
<div style={{minHeight: '100vh', display: 'flex', flexFlow: 'column nowrap'}}>
<div>Content Before</div>
<div style={{flex: 1}}>
Main Content with Sidebar
</div>
<div>Content After</div>
</div>
Add new class for segment basic with height 100vh
I know I'm late but this will sure help others.
you can actually override the default css style of pusher for example:
.pushable:not(body) {
-webkit-transform: none;
-ms-transform: none;
transform: none;
}
.pushable:not(body) > .ui.sidebar,
.pushable:not(body) > .fixed,
.pushable:not(body) > .pusher:after {
position: fixed;
}