Material-UI: Remove TimelineItem missingOppositeContent:before element - css

I'm using Material-UI and building a timeline. My code is as follows:
<Timeline align="right" className={classes.monthlyContainer}>
<TimelineItem >
<TimelineSeparator className={classes.timelineSeparator}>
<TimelineDot className={classes.timelineDot} />
<TimelineConnector className={classes.timelineConnector} />
</TimelineSeparator>
{(data.map(url =>
<TimelineContent className={classes.memsImageContainer}>
<img
className={classes.memsImage}
src={url}
alt="MEMs"
/>
</TimelineContent>
))}
</TimelineItem>
</Timeline>
When I render the webpage, the Material-UI timeline keeps creating a .MuiTimelineItem-missingOppositeContent:before element which is shifting the layout of my timeline to the left.
When I inspect the element, this is what I see:
<li class="MuiTimelineItem-root MuiTimelineItem-alignRightMuiTimelineItem-missingOppositeContent">
<div class="MuiTimelineSeparator-root makeStyles-timelineSeparator-4">
<span class="MuiTimelineDot-root makeStyles-timelineDot-5 MuiTimelineDot-defaultGrey">
</span>
<span class="MuiTimelineConnector-root makeStyles-timelineConnector-6">
</span>
</div>
</li>
When I inspect the styles, this is what I have:
.MuiTimelineItem-missingOppositeContent:before {
flex: 1;
content: "";
padding: 6px 16px;
padding-left: 0px;
padding-right: 0px;
I have recreated it in codesandbox here
How can I remove this element?

The definition of the default styles for the missingOppositeContent element is as follows:
/* Styles applied to the root element if no there isn't TimelineOppositeContent provided. */
missingOppositeContent: {
'&:before': {
content: '""',
flex: 1,
padding: '6px 16px',
},
},
You can override the default styles using the same structure. Overriding this in the theme would look like the following:
const Theme = createMuiTheme({
overrides: {
MuiTimelineItem: {
missingOppositeContent: {
"&:before": {
display: "none"
}
}
}
}
});
You can also do this on a case-by-case basis (in case you have other situations in your code where you want the missing-opposite-content styling) using withStyles:
const TimelineItem = withStyles({
missingOppositeContent: {
"&:before": {
display: "none"
}
}
})(MuiTimelineItem);

You won't believe that you just need to add the <TimelineOppositeContent> component and set display property as 'none'. And it will be solved.

Related

React jsx style tag not applied to tags returned by functions

I'm trying to apply styling to tags that are generated from a for loop inside a function. The problem is that styling within a tag doesn't apply to these generated tags. Possibly because they're generated after the styling is applied? I'm not sure. Here's an example:
generateTags = (size) => {
let tags = []
for (var i = 0; i < size; i++) {
tags.push(<img className="image-tag" src={this.state.imagePath} alt="image" key={Math.random() * Math.floor(100000)}/>)
}
return tags
}
render() {
return (
<div className="main">
<div className="left-container">
{this.generateTags(10)}
</div>
<style jsx> {`
.main { <-- This is properly applied
position: relative;
width: 100%;
height: 100%;
}
.image-tag { <-- This doesn't work
position: absolute;
width: 50px;
}
`} </style>
</div>
)
}
The width: 50px is not applied to the image, and nothing I place makes any difference. But when I add styling within the tag like this:
<img className="image-tag" style={{width: "50px"}} src={this.state.imagePath} alt="image" key={Math.random() * Math.floor(100000)}/>
Then the style is applied correctly. Does this mean I can't have css within the style tag if the elements are return from a function?
It looks like you are using Styled JSX. One of the principles of Styled JSX is that the CSS is component specific. Since your <img> tags are being created outside of the render() function where your styles are defined, they are not being applied.
In this instance, I would recommend to instead have a GenerateTags React component, instead of a function. That way, you can generate your tags as needed, as well as apply component specific styling, like so:
GenerateTags = (props) => {
const {size} = props
let tags = []
for (var i = 0; i < size; i++) {
tags.push(i)
}
return(
<>
{tags.map((tag, index) => (
<img className="image-tag" src={this.state.imagePath} alt="image" key={Math.random() * Math.floor(100000)}/>
))}
<style jsx>{`
// This will now work as it is in the same scope as the component
.image-tag {
position: absolute;
width: 50px;
}
`}</style>
</>
)
return tags
}
render() {
return (
<div className="main">
<div className="left-container">
<GenerateTags size={10} />
</div>
<style jsx> {`
.main { <-- This is properly applied
position: relative;
width: 100%;
height: 100%;
}
`} </style>
</div>
)
}
Otherwise, if you wanted these styles to be applied outside of the scope of the component, you could use the global option:
<style jsx global>
...
</style>

React - Apply **active** class to an element using CSS modules

I'm diving into React and I found a little problem managing active class names when using CSS modules.
Suppose I want to develop a Tabs React component. I would like to apply an active class to the current list item. The tab headers is built by the following component:
import React, { Component } from 'react';
import styles from './Tabs.scss';
export default class TabHeader extends Component {
render() {
let activeTabIndex = this.props.activeTabIndex;
return (
<ul className={styles['tabs-header']}>
{
this.props.data.map((item, index) => {
return (
<li key={index}>
<a className={(index === activeTabIndex) ? 'active' : ''} href="#">
<span>{item.header}</span>
</a>
</li>
)
})
}
</ul>
);
}
}
As you can see, I conditionally added the class active to the interested list item. The stylesheet code is Tabs.scss:
.tabs-header {
display: table;
width: 100%;
list-style-type: none;
& li {
display: table-cell;
text-align: center;
color: #ECF0F1;
cursor: pointer;
a {
display: block;
padding: 15px;
background: #212F3D;
transition: all .2s ease-in;
transform: skew(-40deg);
&:hover {
background: #2471A3;
color: #F7F9F9;
}
& span {
display: block;
transform: skew(40deg);
}
&.active {
background: #2471A3;
}
}
}
}
With this setup, the active item is not using the active css code. How can I solve the problem?
EDIT: the prop activeTabIndex (integer greater than or equal to zero) is correctly working. If I inspect the elements, I can see the class active being added to the active item list, but it is not pointing to the class defined in Tabs.scss. Just to point this out, when using className={styles['tabs-header']} in the ul element, this is going to be converted to Tabs__tabs-header__2LSPG.
I’d need to try it out to be confident of this, but I think you should be using styles.active instead of 'active’.
this should work<a
className={${index === activeTabIndex && css.active}}
href="#"
{item.header}
Your condition would leave an empty space in a class name because of the condition:
(index === activeTabIndex) ? 'active' : ''
Instead you can do a short-circuit evaluation:
<a className={(index === activeTabIndex) && styles['active']} href="#">
<span>{item.header}</span>
</a>
All about CSS modules in React:
For a className with the dash use: style["upper-level"]
Single word className: style.active
To combine a multiple classNames use: style["upper-level"] + " " + style.active
import style from "./style.module.css";
...
className={
menuOpened
? style["upper-level"] + " " + style.active
: style["upper-level"]
}

Can't get buttons to wrap to new line instead of overflowing container

I couldn't get a JSFiddle to work properly with React and some other dependencies, so I hope the link to this Github repo is sufficient for demonstrating the issue:
https://github.com/ishraqiyun77/button-issues/
Basically, a group of buttons is rendered and they should be auto-widened to fill white space and take up the whole row. This works in Chrome, Edge, Safari, and Firefox. It looks like this:
This isn't happening in IE. I've been messing with it for hours and haven't made much progress:
Here is the code, although could clone the repo I posted above:
// component.jsx
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import {
Button,
Col,
Modal,
ModalBody,
ModalHeader,
Row
} from 'reactstrap';
import styles from '../assets/scss/app.scss';
class TestPrint extends Component {
constructor(props) {
super(props);
this.state = {
modal: false,
}
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({
modal: !this.state.modal
})
}
renderContent() {
let buttons = [];
for (let i = 1; i < 50; i++) {
buttons.push(
<Col key={i}>
<Button
key={i}
className='cuts-btn'
>
{i} - Test
</Button>
</Col>
);
};
return buttons;
}
render() {
return (
<div>
<Button
style={
{
position: 'fixed',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)'
}
}
onClick={this.toggle}
>
Open Modal for Buttons
</Button>
<Modal
size='lg'
isOpen={this.state.modal}
toggle={this.toggle}
className='results-modal'
>
<ModalHeader toggle={this.toggle}>
Button Issues
</ModalHeader>
<ModalBody>
<div className='results-bq-cuts'>
<Row>
{this.renderContent()}
</Row>
</div>
</ModalBody>
</Modal>
</div>
)
}
}
ReactDOM.render(<TestPrint />, document.getElementById('app'));
.results-modal {
max-width: 1200px;
.modal-content {
.modal-body {
margin-left: 13px;
margin-right: 13px;
.results-bq-cuts {
width: 100%;
.col {
padding:2px;
}
.cuts-btn {
font-size: 11px;
padding: 3px;
width: 100%;
box-shadow: none;
}
// .col {
// padding: 2px;
// display: table-cell;
// flex-basis: 100%;
// flex: 1;
// }
// .cuts-btn {
// font-size: 11px;
// padding: 3px;
// width: 100%;
// box-shadow: none;
// }
}
}
}
}
I have all of the <Button> wrapped in <Col> because that should be what is filling the white space by increasing the size of the button.
Thanks for the help!
IE11 doesn't like working out the width of flex items. If you add flex-basis: calc( 100% / 24 ); to .col it works :) Obviously use any width you want, but what I've given replicates the 21 boxes on one line. But essentially flex-basis needs a defined width to work.
​
Or add an extra class to each element (such as col-1 ) This'll also achieve the same thing.

I'm converting existing SCSS code to JSS, I'm stuck at converting the following nested classes

I'm attaching the code for SCSS and react elements below
.chatPane {
height: 100%;
overflow: hidden;
.form-control, .form-control:focus, .form-control:active {
border-bottom: 0;
}
}
render() {
const { isLoaded, messages, handleSendMessage, user } = this.props;
const dialogChildren = (
<div className="modalBox">
<h1 className="modalBox-header">Join chat</h1>
<form onSubmit={this.onCreateUser}>
<input className="modalBox-input" placeholder="Type your name" onChange={this.onNameChange} />
<hr className="modalBox-horizontal"/>
<div className="modalFooter">
<Link className="modalBox-link" to="/chat">close</Link>
<button className="modalBox-button" onClick={this.onCreateUser} type="submit">join</button>
</div>
</form>
</div>
);
I want some help in converting this code into JSS
You need default presets or particularly jss-nested plugin, which replaces & with the parent rule selector.
{
a: {
'& .b, & .c:focus, & .d:focus': {
color: 'red'
}
}
}
Also if you need all selectors global, which is a bad idea, you can use jss-global plugin (also part of default preset)
'#global': {
'.a': {
color: 'green',
'& .b, & .c:focus, & .d:focus': {
color: 'red'
}
}
}

How to set background color to $actionsheet in ionic frameworks

Here is the code, very simple and copy paste from office website
$scope.show = function() {
// Show the action sheet
var hideSheet = $ionicActionSheet.show({
destructiveText: 'Delete Photo',
titleText: 'Modify your album',
cancelText: 'Cancel <i class="icon ion-no-smoking"></i>',
cancel: function() {
// add cancel code..
},
buttonClicked: function(index) {
return true;
}
});
// For example's sake, hide the sheet after two seconds
$timeout(function() {
hideSheet();
}, 2000);
};
I want to change the cancel button have a red color background, how I can achieve it in ionic frameworks?
Easiest way is to look at the markup using your browser (after running ionic serve in your terminal), for example in Chrome ctrl+shift+i, where you can choose the button and see what classes are attached. In your case you'll see something like this:
<div class="action-sheet-group action-sheet-cancel" ng-if="cancelText">
<button class="button ng-binding"
ng-click="cancel()"
ng-bind-html="cancelText">Cancel</button>
</div>
Which has styles that for the parent div, and child button something like this:
.action-sheet-group {
margin-bottom: 8px;
border-radius: 4px;
background-color: #fff;
overflow: hidden;
}
.action-sheet .button {
display: block;
padding: 1px;
width: 100%;
border-radius: 0;
border-color: #d1d3d6;
background-color: transparent;
color: #007aff;
font-size: 21px;
}
Just change these values either in Sass or directly in your styles sheet if you're not using Sass.

Resources