How to conditionally change colour of button based on a keyword - css

I am wishing to display card's which hold a Bootstrap badge at the top of each card. I would like to conditionally change the colour of the badge depending on status of the pet.
render() {
const isAdmin = true;
const post = this.props.post;
const id = this.props.post.post_ID;
console.log(post);
return (
<div>
<Card id="card-main" style={{ width: '18rem', margin: '12px' }}>
<span class="badge badge-secondary">{post.petStatus}</span>
<Card.Img id="card-img-top" variant="top" src={post.img_path} />
<Card.Body>
<Card.Title>{post.pet_name}</Card.Title>
<Card.Text id="PetName">
<strong>{post.petName} </strong>
</Card.Text>
<Card.Text id="content">
{post.content}
</Card.Text>
<Card.Text>
<strong>Posted By: </strong>{post.name}
</Card.Text>
<Card.Text
<strong>Posted: </strong>{post.postedOn}
</Card.Text>
</Card>

Depending on the number of colors your need, you could either do it inline:
<Card id="card-main" style={{ width: '18rem', margin: '12px' }}>
<span class="badge badge-secondary" style={{color: post.petStatus === "adopted" ? "blue" : "red"}}>{post.petStatus}</span>
... or if you need several colors probably better to write a helper that returns a style based on the status:
getStyleForStatus = (status)=>{
let statusColor
switch (status){
case "adopted":
statusColor = "blue"
break;
case "lost":
statusColor = "red"
break;
default:
//
return {color:statusColor}
}
}
render() {
const isAdmin = true;
const post = this.props.post;
const id = this.props.post.post_ID;
console.log(post);
return (
<div>
<Card id="card-main" style={{ width: '18rem', margin: '12px' }}>
<span class="badge badge-secondary" style={getStyleForStatus(post.petStatus)}>{post.petStatus}</span>
{/* ... */}
</Card>

Related

How to bring the image to the right of react Card

I have a react Card.
I want to bring the image on the card to the right-side of card and it should also be parellel to the Name Pankaj Rout, and should be responsive.
This is what I have tried so far,
var userMap = [
{name: "Pankaj Rout", email: "pankaj.rout#somedomain.com"}
]
userData.map((data) => {
return (
<div key={data.email}>
<Card style={cardStyle}>
<Card.Body>
<div class="col-sm-6 text-right">
<img
className={classes.img}
style={cardImgStyle}
src="https://www.w3schools.com/howto/img_avatar.png"
alt="sans"
/>
</div>
<Card.Title> {data.name} </Card.Title>
<Card.Subtitle className="mb-2 text-muted">
General Manager
</Card.Subtitle>
<Card.Text> {data.email} </Card.Text>
<Button> Delete </Button>
<Button> Email </Button>
<Button> Chat </Button>
</Card.Body>
</Card>
</div>
);
classes is used from withStyles hook
const useStyles = (theme) => ({
img: {
justifyContent: 'right',
}
});
following style is referring to cardImgStyle
const cardImgStyle = {
width: "30%",
height: "30%",
borderRadius: "50%",
display: "flex",
flexWrap: "wrap",
};
Could anyone please point out what is wrong here?
Thanks!!
justifyContent : 'space-beetwin' ;
or
for img :
float :' right';

Button sit at bottom of page centered

I would like a scroll to the top button to sit at the bottom, much like a footer. Current Behavior: I have an array I'm filtering through and displaying different lengths of data. When there is only one item in a certain category the button will move all the way to the top of the page under the item. Wanted Behavior: I would like the button to stay at the bottom and not move, but not sticky. my button styling is as follows:
import React, { useState, useContext } from "react"
// components
import SelectStatus from "../components/SelectStatus"
import RepoCard from "../components/RepoCard"
// Context
import { GithubContext } from "../context/GithubContext"
// Material UI Stuff
import TextField from "#material-ui/core/TextField"
import CardContent from "#material-ui/core/CardContent"
import Button from "#material-ui/core/Button"
import Card from "#material-ui/core/Card"
import Grid from "#material-ui/core/Grid"
import { makeStyles } from "#material-ui/core/styles"
import Container from "#material-ui/core/Container"
// context
const useStyles = makeStyles((theme) => ({
cardGrid: {
paddingTop: theme.spacing(8),
paddingBottom: theme.spacing(8),
},
card: {
display: "flex",
marginBottom: 10,
minHeight: 90,
},
form: {
display: "flex",
alignItems: "center",
width: "100%",
},
content: {
display: "flex",
alignItems: "center",
width: "100%",
justifyContent: "space-between",
},
jobField: {
margin: 0,
padding: 0,
},
grid: {
padding: 0,
},
dashboardContainer: {
marginTop: 70,
padding: 10,
},
loading: {
textAlign: "center",
},
}))
const INITIAL_STATE = {
language: "All",
search: "",
}
const Profile = () => {
const [formData, setFormData] = useState(INITIAL_STATE)
const [updated, setUpdated] = useState(false)
const [created, setCreated] = useState(false)
const { data } = useContext(GithubContext)
const handleUpdated = () => {
setUpdated(!updated)
data &&
data.sort((a, b) => {
if (updated) return a.updated_at > b.updated_at ? -1 : 1
return a.updated_at > b.updated_at ? 1 : -1
})
}
const handleCreated = () => {
setCreated(!created)
data &&
data.sort((a, b) => {
if (created) return a.created_at > b.created_at ? -1 : 1
return a.created_at > b.created_at ? 1 : -1
})
}
const handleInputChange = (field) => (e) => {
setFormData({ ...formData, [field]: e.target.value })
}
const classes = useStyles()
return (
<>
<div style={{ marginTop: 85, marginBottom: 85 }}>
<Container className={classes.dashboardContainer}>
<Card className={classes.card} style={{ width: "100%" }}>
<CardContent className={classes.content}>
<div className={classes.form}>
<Grid
container
spacing={2}
alignItems='center'
justify='space-between'
>
<Grid item sm={4} xs={12} className={classes.grid}>
<SelectStatus
language={formData.language}
handleInputChange={handleInputChange}
/>
</Grid>
<Grid item sm={4} xs={12} className={classes.grid}>
<TextField
className={classes.jobField}
margin='normal'
fullWidth
id='search'
name='search'
label='Search by Title'
placeholder='Search by Title'
onChange={handleInputChange("search")}
value={formData.search}
/>
</Grid>
<Grid item sm={2} xs={12} className={classes.grid}>
<Button
fullWidth
variant='contained'
color='primary'
onClick={handleUpdated}
>
Updated {updated ? "(oldest)" : "(newest)"}
</Button>
</Grid>
<Grid item sm={2} xs={12} className={classes.grid}>
<Button
fullWidth
variant='contained'
color='primary'
onClick={handleCreated}
>
Created {created ? "(oldest)" : "(newest)"}
</Button>
</Grid>
</Grid>
</div>
</CardContent>
</Card>
</Container>
{!data ? (
<h1 className={classes.loading}>Initializing Repos...</h1>
) : (
<Container style={{ padding: 10 }}>
{!data ? (
<div style={{ placeItems: "center" }}>Loading...</div>
) : (
<Grid container alignItems='center' spacing={4}>
{data &&
data
.filter((data) => {
if (formData.language === "All") return true
return data.language === formData.language
})
.filter((data) => {
if (formData.search === "") return true
return (data.name + data.language)
.toLowerCase()
.includes(formData.search.toLowerCase())
})
.map((user) => <RepoCard key={user.id} user={user} />)}
</Grid>
)}
</Container>
)}
<Button
variant='contained'
color='primary'
disableElevation
style={{
borderRadius: 0,
display: "block",
marginLeft: "auto",
marginRight: "auto",
position: "relative",
marginTop: "80px"
}}
>
Back to Top
</Button>
</div>
</>
)
}
export default Profile
You can use flex and space-around feature. like below:
<div class="container">
<div>
your items
</div>
<Button
variant='contained'
color='primary'
disableElevation
style={{
borderRadius: 0,
elevation: "disabled",
display: "block",
marginLeft: "auto",
marginRight: "auto",
marginTop: "80px",
}}
>
Back to Top
</Button>
</div>
Style:
.container{
display: flex;
flex-direction:column;
justify-content: space-between;
}
Using this you split your content to two part.
First part which will be your array items will be shown at the top.
The second part which is your button will be shown at the bottom.
This is because your making a space between first part and second part by using space-around of justify-content.
without sticky or fixed the only thing i can think of is using position: absolute; and bottom: 0; or placing them in a container with some combination of the same, then positioning it as needed. same as Joeri in the comments, would need a bit more context to help :) good luck!

Modify image on div mouseover

I have a basic Card.
I want the image to change its src when I mouseover on the card.
I can change the image when I mouseover on the <img/> tag itself like so :
<img src={item.iconUrl}
onMouseOver={e => (e.currentTarget.src = item.iconHoverUrl)}
onMouseOut={e => (e.currentTarget.src = item.iconHoverUrl)}
className="mr-3 avatar-lg rounded" alt="app_icon"
/>
But I don't find any way to reference this image's src when I'm out of it's scope.
I tried setting the content of src into a variable and changing it's value on the card's mouseover but that won't trigger an update of the src of the image so it doesn't work either.
Here is the code of the component if it helps :
<Card className="app-hover" style={{ marginTop: '10px', height: '92%', overflow: 'hidden' }}>
<CardBody className="p-3">
<Media>
<img src={item.iconUrl}
onMouseOver={e => (e.currentTarget.src = item.iconHoverUrl)}
onMouseOut={e => (e.currentTarget.src = item.iconHoverUrl)}
className="mr-3 avatar-lg rounded" alt="app_icon" />
<Media body>
<Row style={{ marginLeft: '4px', marginTop: '15px' }}>
<h5 className="mt-1 mb-0">{this.props.i18n.language === 'en' ? item.title : item.titleFR}</h5>
</Row>
</Media>
</Media>
<Row>
<Col lg={6}>
<Media>
<CreditCard className="icon-dual align-self-center mr-2"></CreditCard>
<Media body>
<h5 className="mt-2 pt-1 font-size-16">{this.props.i18n.language === 'en' ? 'Not Owned' : 'Non-Acquis'}</h5>
</Media>
</Media>
</Col>
<Col lg={6}>
<Media>
<Users className="icon-dual align-self-center mr-2"></Users>
<Media body>
<h5 className="mt-2 pt-1 font-size-16">
{
item.stats ? item.stats.users : ''
}
</h5>
</Media>
</Media>
</Col>
</Row>
<Row className="mt-2 border-top pt-2" style={{ paddingLeft: '8px', paddingRight: '8px' }}>
<p className="text-muted">{this.props.i18n.language === 'en' ? item.shortDescription : item.shortDescriptionFR}</p>
</Row>
</CardBody>
Is it possible to do it the way I have it setup? As you can obviously see from the code, the image is fetched from an api and always changing so I can't simply hardcode the animation in CSS.
You should not try to change the DOM "directly", instead you should call a function that mutate the state and use the new icon from the state itself. Let me explain with an example:
const [icon, setIcon] = useState("");
const onMouseOver = () => setIcon("the-over-icon");
const onMouseOut = () => setIcon("the-not-over-icon");
// ...
<Card onMouseOver={onMouseOver} onMouseOut={onMouseOut}>
<img src={icon} />
</Card>
I will extract img into functional component. In Typescript something like.
import React from "react";
import { useState } from "react";
interface IMyImgProps{
iconUrl: string;
iconHoverUrl: string;
}
export const MyImg: React.FunctionComponent<IMyImgProps> = props => {
const [icon, setIcon] = useState(props.iconUrl);
const onMouseOver = () => setIcon(props.iconHoverUrl);
const onMouseOut = () => setIcon(props.iconUrl);
return <img src={icon} onMouseOver={onMouseOver} onMouseOut={onMouseOut} />
}

Making the card component responsive using material ui

I am trying to make my card responsive to mobile applications
const styles = {
edit: {
width: "40%",
marginLeft: 270,
background: "#76ff03"
},
add: {
width: "100%",
background: "#18ffff",
size: "large"
},
root: {
minHeight: 210,
minWidth: 100
}
};
<Container maxWidth="md">
{/*marginTop:15*/}
<Typography component="div" style={{ borderColor:'#00c853' }}>
{/*style={{ height: '30vh' }}*/}
<Card style={styles.root}>
<Typography variant="overline" color="secondary" style={{fontFamily:'Roboto',margin:10}}>
All about your needs
</Typography>
<form onSubmit={this.validateItem} autoComplete='off'>
<TextField id="outlined-full-width" label="Input" style={{ width:'90%',marginTop:30 ,marginLeft:40 }}
placeholder="Add A Todo Item " margin="normal" InputLabelProps={{
shrink: true,
}} error={this.state.errorState} helperText={ this.state.errorState
&& "Item name can't be blank" } size="large" variant="outlined" value={newItem} onChange={handleInput} />
<Grid container justify='center' alignContent='center'>
<Grid item xs={12} md={6}>
{buttonChange()}
</Grid>
</Grid>
</form>
</Card>
</Typography>
</Container>
</div>
The above code is the user interface for the card component , i am trying to make the card component mobile responsive , but the interface i get instead is given below
The card and the text field should be able to be responsive to the screen size, but i am unable to make it work. Is there a way i can make it happen?
Hello and thank you for asking your question,
you can use the breakpoint of [theme.breakpoints.down("(XS, sm,md, lg, xl,)")] : {
maxWidth: 200 // you can change the size of your card component.
}
Here is a clearer example from the material ui Card component
Here is the component from the material UI Card component page, I only added the useTheme and useMediaQuery imports, and added a medium breakpoint inside useStyle under classes.root Here is a useful link on "useMediaQuery" https://material-ui.com/components/use-media-query/#usemediaquery
import { useTheme } from "#material-ui/styles";
import useMediaQuery from "#material-ui/core/useMediaQuery";
const useStyles = makeStyles(theme => ({
root: {
maxWidth: 345,
[theme.breakpoints.down("md")] : {
maxWidth: 200
}
},
media: {
height: 140
}
}));
const Card = () => {
const classes = useStyles();
const theme = useTheme();
const matches = useMediaQuery(theme.breakpoints.up("sm"));
return (
<Card className={classes.root}>
<CardActionArea>
<CardMedia
className={classes.media}
title="Contemplative Reptile"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
Lizard
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
Lizards are a widespread group of squamate reptiles, with over 6,000
species, ranging across all continents except Antarctica
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<Button size="small" color="primary">
Share
</Button>
<Button size="small" color="primary">
Learn More
</Button>
</CardActions>
</Card>
);
}
Hope this helps

Add Hover effect to Font Awesome Stars

I would like a simple method, whereby you hover over them and they are a solid yellow.
const styles = theme => ({
root: {
flexGrow: 1,
overflow: 'hidden',
padding: theme.spacing(0, 3),
},
paper: {
maxWidth: 800,
margin: `${theme.spacing(2)}px auto`,
padding: theme.spacing(2),
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
width: 200,
},
playButton: {
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
position: "relative",
"& .playButton": {
position: "absolute",
top: "60%",
left: "-55px",
transform: "translateY(-50%)",
},
}
});
function Tasks(props) {
const { classes } = props;
return (
<div className={classes.root}>
<Paper className={classes.paper}>
<Grid container spacing={2}>
<Grid item xs={12} sm container>
<Grid item xs container direction="column" spacing={2}>
<Grid item xs>
<div className="name-label">
Name
</div>
<Typography variant="h6" gutterBottom>
{props.name}
</Typography>
<div className="form-divider"></div>
<Typography variant="body2" color="textSecondary">
{props.description}
</Typography>
</Grid>
</Grid>
<Grid item classes={{ root: props.classes.playButton}}>
<Grid item xs={3} className="playButton">
<i class="far fa-play-circle fa-2x"></i>
</Grid>
<div className="workers-assigned-label">
Workers Assigned
</div>
<Typography variant="h6" gutterBottom>
0/25
</Typography>
<div class="star-rating">
<label class="far fa-star fa-2x"></label>
<label class="far fa-star fa-2x"></label>
<label class="far fa-star fa-2x"></label>
</div>
<div>
unassigned
</div>
</Grid>
</Grid>
</Grid>
</Paper>
</div>
);
}
export default withStyles(styles)(Tasks);
If anyone has any suggestions as to how to get them to change from https://fontawesome.com/v4.7.0/icon/star-o to having the centre fill with yellow that would be much appreciated. Whether it be best done with CSS or something using React.
Taking a look at the content of that particular font, the 2 you'll use are content: "\f006" and content: "\f005". f005 is the filled star that you'll want to turn yellow.
const styles = theme => ({
playButton: {
"& .rating": {
"& .fa-star-o": {
"&:hover": {
"&::before": {
content: "\f005",
color: "yellow"
}
}
}
},
},
});
And like the other person said, make sure the package is working.
Did you check the version of Font Awesome you use? This icon seems to be in the 4.7.0. I've had multiple problems with icons not showing and usually it was because I was using an outdated version or the icon I wanted to use was in a newer version of Font Awesome.
And if you use a newer one, check if the icon still exists for this version, it may have been removed or renamed.

Resources