How to indent list and sublist menu? - html

I am trying to style the list and sublist menu. Some list items have name and some list items having sublist items having svg added infront of list item. in doing so, the list item without sublist item is not indented correctly. how can i achieve it. could somebody help me. Below is what i have tried.
return (
{this.props.expanded &&
<Drawer className="drawer">
<header>
<h4>List items</h4>
</header>
<ListItems listitemss={this.props.listitems} />
</Drawer>
}
</div>
);
};
}
class ListItemss extends React.PureComponent {
render() {
return <ul className="listitems_list">
<div className="lists">
{this.props.layers.map((list, index) => {
return <List key={index} list={list} />
})}
</div>
</ul>
}
}
class List extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
expanded: false,
hidden: false,
};
}
expand = () => {
this.setState({expanded: true});
};
collapse = () => {
this.setState({expanded: false});
};
hide_layer = () => {
this.setState({hidden: true});
};
show_layer = () => {
this.setState({hidden: false});
};
render() {
return <li>
<div className="list">
{this.props.list.children && !this.state.expanded &&
<SvgAccDown width="14" height="8" onClick={this.expand} />
}
{this.props.list.children && this.state.expanded &&
<SvgAccUp width="20" height="18" onClick={this.collapse} />
}
<span>{this.props.list.name}</span>
</div>
{this.props.list.children && this.state.expanded &&
<ListItems lists={this.props.list.children}/>
}
</li>;
}
}
.listitems_list {
height: 100%;
overflow: auto;
.lists {
height: 100%;
margin-left: 12px;
overflow: auto;
.list {
background-color: #fff;
display: flex;
flex-direction: row;
align-items: center;
cursor: pointer;
span {
padding-right: 12px;
padding-top: 12px;
padding-bottom: 12px;
padding-left: 2px;
font-size: 16px;
font-weight: bold;
}
}
}
}

If it is an external CSS file, and you are using something like Create React App, you can just import 'mystyle.css;`

Related

How can I make a song progress bar for my audio player?

I've made a simple audio player, but now I want to add a song progress bar that fills up the timeline as the song plays, this is my html:
<div id="ap-timeline" onClick={this.mouseMove} ref={(timeline) => { this.timeline = timeline }}>
<div id="ap-handle" onMouseDown={this.mouseDown} ref={(handle) => { this.handle = handle }} />
<div id="ap-handle-circle" onMouseDown={this.mouseDown} ref={(handleCircle) => { this.handleCircle = handleCircle }} />
</div>
And this is my CSS:
#ap-timeline{
display: flex;
flex-direction: row;
align-items: center;
width: 550px;
height: 4px;
border-radius: 15px;
background: $audio-slider-gray;
margin: 0 10px;
#ap-handle {
background: $white;
height: 4px;
}
#ap-handle-circle {
width: 13px;
height: 13px;
border-radius: 50%;
background: $white;
transform: scale(0.25);
}
}
}
The ap-handle is the progress bar that I'm trying to use to fill up the timeline as the song plays.
I'm not much of a react person so excuse any poor practices here:
#progress-bar {
height: 20px;
background: red;
transform: scaleX(0);
transform-origin: center left;
}
class App extends Component {
constructor() {
super();
this.interval = null; // setInterval
this.audioEl = new Audio(
"https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3"
);
this.audioEl.addEventListener("canplaythrough", () => {
this.setState({
duration: this.audioEl.duration
});
});
this.state = {
currentTime: 0,
duration: 0
};
}
playAudio() {
this.audioEl.play();
// requestAnimationFrame would probably be better, but
// for example sake we'll use setInterval
this.interval = setInterval(() => {
this.setState({
currentTime: this.audioEl.currentTime,
progress: Math.ceil((this.audioEl.currentTime / this.audioEl.duration) * 100) / 100
});
}, 100);
}
stopAudio() {
clearInterval(this.interval);
this.audioEl.pause();
}
render() {
return (
<div>
<button onClick={() => this.playAudio()}>Play</button>
<button onClick={() => this.stopAudio()}>Stop</button>
<div
style={{ transform: `scaleX(${this.state.progress})` }}
id="progress-bar"
/>
</div>
);
}
}
Blitz

Make element's height adaptative to what's inside

I want to make a grey-colored background for my list in ReactJS.
The problem is that the background seems to have a fixed height which seems to be smaller than the inside's height...
I never met this problem before, and the only way I found to have the background size bigger than the element's is to put height: XXXpx, which is not suitable...
Can someone explain me what I did wrong ?
Here is my class file :
import React, { Component } from "react";
import { ListGroupItem } from "react-bootstrap";
import { LinkContainer } from "react-router-bootstrap";
import { API } from "aws-amplify";
import "./ProjectList.css";
export default class ProjectList extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
projects: [],
reducedView: true,
projectsNumber: 1000,
numberOfElementsToDisplay: 1000
};
}
async componentDidMount() {
try {
const projects = await this.projects();
console.log(projects)
this.setState({ projects });
} catch (e) {
alert(e);
}
this.setState({ isLoading: false });
}
projects() {
return API.get("economics-endpoint", "/list");
}
handleClick(e) {
this.setState({ reducedView: false });
e.preventDefault();
}
renderNotesList(projects) {
return [{}].concat(projects).map(
(note, i) => {
if(i !== 0){
if((this.state.reducedView && i <= this.state.numberOfElementsToDisplay) || !this.state.reducedView){
return(
<div className="element">
<ListGroupItem className="mainContainer">
<div>
ProjectName#{i}
</div>
</ListGroupItem>
</div>
);
}
}
else{
if(this.state.projectsNumber === 0){
return(
<div className="element">
<LinkContainer to={`/econx/new`}>
<ListGroupItem className="new">
<div>
+ Create New Project
</div>
</ListGroupItem>
</LinkContainer>
<div className="errorMessage">
You don't have any existing project yet.
</div>
</div>
);
}
else{
return(
<div className="element">
<LinkContainer to={`/econx/new`}>
<ListGroupItem className="new">
<div>
+ Create New Project
</div>
</ListGroupItem>
</LinkContainer>
</div>
);
}
}
}
);
}
render() {
return (
<div className="ProjectList">
<div className="projects">
{!this.state.isLoading &&
this.renderNotesList(this.state.projects)}
</div>
</div>
);
}
}
And my css file :
.ProjectList .notes h4 {
font-family: "Open Sans", sans-serif;
font-weight: 600;
overflow: hidden;
line-height: 1.5;
white-space: nowrap;
text-overflow: ellipsis;
}
.projects{
background-color: #E0E0E0;
border-radius: 10px;
padding: 1%;
}
.list-group-item{
margin-bottom: 3px;
padding: 0px;
line-height: 200px;
text-align: center;
vertical-align: middle;
border-radius: 6px;
padding-bottom: 50px;
}
.list-group-item:first-child{
padding: 0px;
border-radius: 6px;
}
.list-group-item:hover{
vertical-align: baseline;
}
.element{
width: 20%;
float: left;
padding: 0% 1% 1% 1%;
}
This doesn't answer your CSS question. I did have some thoughts on the JavaScript, though. I'll offer my refactor for your consideration. Hopefully I interpreted your original logic correctly:
import React, { Component } from "react";
import { ListGroupItem } from "react-bootstrap";
import { LinkContainer } from "react-router-bootstrap";
import { API } from "aws-amplify";
import "./ProjectList.css";
export default class ProjectList extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
projects: [],
reducedView: true,
projectsNumber: 1000,
numberOfElementsToDisplay: 1000
};
}
async componentDidMount() {
try {
const projects = await this.fetchProjects();
console.log(projects);
this.setState({ projects });
} catch (e) {
alert(e);
} finally {
this.setState({ isLoading: false });
}
}
fetchProjects = () => {
return API.get("economics-endpoint", "/list");
};
handleClick = e => {
e.preventDefault();
this.setState({ reducedView: false });
};
render() {
const {
isLoading,
numberOfElementsToDisplay,
projectsNumber,
reducedView
} = this.state;
const projects = reducedView
? this.state.projects.slice(0, numberOfElementsToDisplay)
: this.state.projects;
return (
<div className="ProjectList">
<div className="projects">
{!isLoading && (
<React.Fragment>
<div className="element">
<LinkContainer to={`/econx/new`}>
<ListGroupItem className="new">
<div>+ Create New Project</div>
</ListGroupItem>
</LinkContainer>
{projectsNumber === 0 && (
<div className="errorMessage">
You don't have any existing projects yet.
</div>
)}
</div>
{projects.map((project, index) => (
<div className="element">
<ListGroupItem className="mainContainer">
<div>ProjectName#{index}</div>
</ListGroupItem>
</div>;
))}
</React.Fragment>
)}
</div>
</div>
);
}
}
This fixes your off-by-one issue by hopefully capturing your intentions as I understand them:
If it's not loading...
Show a "Create New Project" item
If they don't have any projects yet, show them a message
If they do have projects, create a new element for each one
It's worth considering whether your projectsNumber could be replaced with projects.length. If so, you can probably combine (2) and (3) above to be an either-or scenario: If they don't have projects, show a message, if they do, show the projects.

Buttons not wrapping and overflowing container in Safari 10 (fine in Edge and Chrome)

Supposed to look like the below (does in Edge & Chrome):
But looks like this in Safari 10:
I've read a few SO questions that have not help resolve the issue. Most recently this one:
Flexbox not working on button or fieldset elements
The answers are not resolving my issue.
How do I get a new button to wrap to a new line instead of overflowing the container?
Here is the Sass and ReactJS component I have. Also, I am using Bootstrap 4.
class BasicQueryCuts extends Component {
constructor(props) {
super(props);
this.state = {
cuts: {}
}
this.clearSelection = this.clearSelection.bind(this);
this.selectAll = this.selectAll.bind(this);
}
clearSelection() {
this.setState({
cuts: {}
})
this.props.clearCuts();
}
// pieces together the cuts that are selected
onCutSelect(cut, str) {
// want to make sure it stays a number
// so that it matches the server data
// tends to convert to string if not specific
cut = Number(cut);
this.setState(
({cuts: prevCuts}) => (
this.state.cuts[cut] && str !== 'all'
?
{cuts: {...prevCuts, [cut]: undefined }}
:
{cuts: {...prevCuts, [cut]: cut }}
),
() => this.props.basicQueryResults(this.state.cuts)
)
}
selectAll() {
const { country } = this.props;
let { query_data } = this.props;
if (query_data) {
if (query_data[0].Country && country) {
var data = _.filter(query_data, {'Country': country});
} else {
var data = query_data;
}
}
_.map(
data, c => {
this.onCutSelect(c.SortOrder, 'all');
}
)
}
// These buttons will allow selecting everything, or clearing the selection
renderAllNothingButtons() {
let { query_data } = this.props;
// generate the list of cuts
if (query_data) {
return (
<Row>
<Col>
<Button color='primary' key='all' className='cuts-btn' onClick={this.selectAll}>
Select All
</Button>
</Col>
<Col>
<Button color='danger' key='cancel' className='cuts-btn' onClick={this.clearSelection}>
Clear All
</Button>
</Col>
</Row>
)
}
}
// renders the cut multi-list, by first ordering what comes from
// the server and then depending on the survey
// setting up the option and value keys
renderCutsButtons() {
const { country } = this.props;
let { query_data } = this.props;
if (query_data) {
if (query_data[0].Country && country) {
var data = _.filter(query_data, {'Country': country});
} else {
var data = query_data;
}
}
// generate the list of cuts
return (
<Row>
{_.map(data, c => {
var cut = c.RptCutCat + ': ' + c.RptCut
return (
<Col key={c.SortOrder}>
<Button
className={this.state.cuts[c.SortOrder] ? 'cuts-btn-active' : 'cuts-btn'}
key={c.SortOrder}
value={c.SortOrder}
onClick={event => this.onCutSelect(event.target.value, 'single')}
>
<span>{cut}</span>
</Button>
</Col>
)}
)}
</Row>
)
}
render() {
const { query_data } = this.props;
return (
<div className='results-bq-cuts'>
{this.renderCutsButtons()}
{query_data
?
<hr />
:
null
}
{this.renderAllNothingButtons()}
{query_data
?
<hr />
:
null
}
</div>
)
}
}
.results-modal {
#media all and (max-width: 1250px) {
max-width: 95%;
}
max-width: 1200px;
.modal-content {
.modal-body {
// padding: 0;
margin-left: 13px;
margin-right: 13px;
.results-bq-cuts {
.col {
padding:2px;
}
.cuts-btn {
font-size: 11px;
padding: 3px;
width: 100%;
box-shadow: none;
}
.cuts-btn-active {
font-size: 11px;
padding: 3px;
width: 100%;
background-color: $croner-blue;
box-shadow: none;
}
h5 {
text-align: left;
}
hr {
margin-top: 5px;
margin-bottom: 5px;
}
}
}
}
}
Compiled HTML here:
Turns out it was an issue with Safari 10.0.0. Upgraded the VM I have macOS running in which upgraded Safari and now the issue is gone. Saw some responses that seemed to indicate the issue was addressed in Safari 10.1.

display a overlay when input is clicked in react

I'm trying to display a overlay when a certain Input field is clicked. I'm doing this in react. How can I do this?
This is my code
import React, { Component } from 'react';
import cam from '../../Resources/img/cam.png';
import SinglePost from '../../Components/Post/single_post';
class Middle extends Component {
constructor(props) {
super(props);
this.state = {
posts: []
}
}
render() {
function popup_ques(e) {
e.preventDefault();
alert("now the overlay should appear");
}
return (
<div className="middle_div">
<input className='post_data_input' placeholder="Ask your question here" ref="postTxt" onClick={popup_ques}/>
</div>
);
}
}
export default Middle;
What is the approach I should take?
I have created a sample react component.
I hope this will help you in somewhat way to achieve what you want.
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
style : {
width : 350
}
};
this.openNav = this.openNav.bind(this);
this.closeNav = this.closeNav.bind(this);
}
componentDidMount() {
document.addEventListener("click", this.closeNav);
}
componentWillUnmount() {
document.removeEventListener("click", this.closeNav);
}
openNav() {
const style = { width : 350 };
this.setState({ style });
document.body.style.backgroundColor = "rgba(0,0,0,0.4)";
document.addEventListener("click", this.closeNav);
}
closeNav() {
document.removeEventListener("click", this.closeNav);
const style = { width : 0 };
this.setState({ style });
document.body.style.backgroundColor = "#F3F3F3";
}
render() {
return (
<div>
<h2>Fullscreen Overlay Nav Example</h2>
<p>Click on the element below to open the fullscreen overlay navigation menu.</p>
<p>In this example, the navigation menu will slide in, from left to right:</p>
<span style={{fontSize:30,cursor:"pointer"}} onClick={this.openNav}>☰ open</span>
<div
ref = "snav"
className = "overlay"
style = {this.state.style}
>
<div className = "sidenav-container">
<div className = "text-center">
<h2>Form</h2>
<p>This is a sample input form</p>
</div>
<a
href = "javascript:void(0)"
className = "closebtn"
onClick = {this.closeNav}
>
×
</a>
<div className = "list-group">
{/*your form component goes here */}
{this.props.children}
</div>
</div>
</div>
</div>
);
}
}
ReactDOM.render(
<Test/>,
document.getElementById('test')
);
.overlay {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0, 0.9);
overflow-x: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 25%;
width: 100%;
text-align: center;
margin-top: 30px;
}
.overlay a {
padding: 8px;
text-decoration: none;
font-size: 36px;
color: #818181;
display: block;
transition: 0.3s;
}
.overlay a:hover, .overlay a:focus {
color: #f1f1f1;
}
.overlay .closebtn {
position: absolute;
top: 20px;
right: 45px;
font-size: 60px;
}
#media screen and (max-height: 450px) {
.overlay a {font-size: 20px}
.overlay .closebtn {
font-size: 40px;
top: 15px;
right: 35px;
}
}
.overlay h2, .overlay p {
color:white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="test"></div>
Input:
<input onFocus={() => this.setState({show_overlay: true})} />
somewhere arround in same render() function add overlay div:
<div
style={{display: this.state.show_overlay === true ? 'block' : 'none'}}
>
overlay
</div>
of course add styling to div as needed to have proper overlay effect, what's needed by your UI
To turn overlay off, you will need to add another event listener on some action, like e.g. click
<button onClick={() => this.setState({show_overlay: false})}>
Close overlay
</button>

open a overlay with form onFocus in react

Hello I've searching a way to display a overlay with a form when I give the focus to a certain input field. I want to do this using react. How can I do this?
my code
import React, { Component } from 'react';
class Middle extends Component {
constructor(props) {
super(props);
this.state = {
posts: []
}
}
render() {
function popup_ques(e) {
e.preventDefault();
alert("now the overlay should appear");
}
return (
<div className="middle_div">
<input className='post_data_input' placeholder="Ask your question here" ref="postTxt"
onClick={popup_ques}/>
</div>
);
}
}
export default Middle;
I have written a function to display an alert when the input field is clicked.. instead of the alert I want to display a transparent overlay with a form.
I want to do something like this
http://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_overlay
Thanks inadvance.
So here i have written code to change the className of the side bar. Every time you call toggleSideBar it will change className from hideSideBar to showSideBar and vice versa. css for hideSideBar and showSideBar should be written as in the link of code school. Hope it will work.
import React, { Component } from 'react';
class Middle extends Component {
constructor(props) {
super(props);
this.state = {
sidebar: 'hideSideBar',
posts: [],
}
}
toggleSideBar() {
if(this.state.toggleBar === 'showSideBar') {
this.setState({ toggleBar: 'hideSideBar' });
} else {
this.setState({ toggleBar: 'showSideBar' });
}
}
render() {
return (
<div className="middle_div">
<input
className='post_data_input'
placeholder="Ask your question here"
ref="postTxt"
onClick={this.toggleSideBar.bind(this)}
/>
<div className={this.state.sidebar} />
// This will be the sidebar
</div>
</div>
);
}
}
export default Middle;
I have created a react component based on link you have given in question.
I hope this will help you in somewhat way to achieve what you want.
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
style : {
width : 350
}
};
this.openNav = this.openNav.bind(this);
this.closeNav = this.closeNav.bind(this);
}
componentDidMount() {
document.addEventListener("click", this.closeNav);
}
componentWillUnmount() {
document.removeEventListener("click", this.closeNav);
}
openNav() {
const style = { width : 350 };
this.setState({ style });
document.body.style.backgroundColor = "rgba(0,0,0,0.4)";
document.addEventListener("click", this.closeNav);
}
closeNav() {
document.removeEventListener("click", this.closeNav);
const style = { width : 0 };
this.setState({ style });
document.body.style.backgroundColor = "#F3F3F3";
}
render() {
return (
<div>
<h2>Fullscreen Overlay Nav Example</h2>
<p>Click on the element below to open the fullscreen overlay navigation menu.</p>
<p>In this example, the navigation menu will slide in, from left to right:</p>
<span style={{fontSize:30,cursor:"pointer"}} onClick={this.openNav}>☰ open</span>
<div
ref = "snav"
className = "overlay"
style = {this.state.style}
>
<div className = "sidenav-container">
<div className = "text-center">
<h2>Form</h2>
<p>This is a sample input form</p>
</div>
<a
href = "javascript:void(0)"
className = "closebtn"
onClick = {this.closeNav}
>
×
</a>
<div className = "list-group">
{/*your form component goes here */}
{this.props.children}
</div>
</div>
</div>
</div>
);
}
}
ReactDOM.render(
<Test/>,
document.getElementById('test')
);
.overlay {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0, 0.9);
overflow-x: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 25%;
width: 100%;
text-align: center;
margin-top: 30px;
}
.overlay a {
padding: 8px;
text-decoration: none;
font-size: 36px;
color: #818181;
display: block;
transition: 0.3s;
}
.overlay a:hover, .overlay a:focus {
color: #f1f1f1;
}
.overlay .closebtn {
position: absolute;
top: 20px;
right: 45px;
font-size: 60px;
}
#media screen and (max-height: 450px) {
.overlay a {font-size: 20px}
.overlay .closebtn {
font-size: 40px;
top: 15px;
right: 35px;
}
}
.overlay h2, .overlay p {
color:white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="test"></div>