SeaWarrior404
SeaWarrior404

Reputation: 4167

How to make the whole Card component clickable in Material UI using React JS?

Im using Material UI Next in a React project. I have the Card component which has an image(Card Media) and text(Card Text) inside it. I also have a button underneath the text. My question is..how to make the whole card clickable? ie. Whether a user presses on the card text, or the card image or the button, it should trigger the onClick event which I call on the button.

Upvotes: 59

Views: 133727

Answers (11)

Fathima Irfana
Fathima Irfana

Reputation: 99

In MUI 5.0 itcan be done by CardActionArea component

  export default function ActionAreaCard() {
    return (
     <Card sx={{ maxWidth: 345 }}>
      <CardActionArea>
        <CardMedia
          component="img"
          height="140"
          image="/static/images/cards/contemplative-reptile.jpg"
          alt="green iguana"
        />
        <CardContent>
          <Typography gutterBottom variant="h5" component="div">
            Lizard
          </Typography>
          <Typography variant="body2" color="text.secondary">
            Lizards are a widespread group of squamate reptiles, with over 6,000
            species, ranging across all continents except Antarctica
          </Typography>
        </CardContent>
      </CardActionArea>
    </Card>
  );
}

Upvotes: 2

Victor
Victor

Reputation: 3561

Using NextJS for routing, these two approaches worked for me.

  1. Wrap the <CardActionArea> with a (NextJS) <Link> component:
import Link from 'next/link'

<Card>
  <Link href='/your-target-path' passHref>
    <CardActionArea>
      ...
    </CardActionArea>
  </Link>
</Card>
  1. Use the effect useRouter to push the route on click:
import { useRouter } from 'next/router'

const router = useRouter()

<Card>
  <CardActionArea onClick={() => {router.push('/your-target-path')}}>
    ...
  </CardActionArea>
</Card>

Note that with this second approach, your browser won't recognize the URL, i.e., the activity bar (that appears on hover) won't be populated.

Upvotes: 3

T. Al Rashid
T. Al Rashid

Reputation: 923

In MUI5:

Put the card in a <Box /> then make the card an <a> tag component.

<Box component='a' href='/dashboard' sx={{ textDecoration: 'none' }}>
    <Card sx={{ height: '200px', cursor: 'pointer'}}>
        <CardContent>
           //CardContent
        </CardContent>
    </Card>
</Box>

Add styles like:

  • Remove text Decoration since you have added <a> tag
  • Give your card the preferred height
  • Change the cursor to pointer on hover over the card

Upvotes: 0

Ismail Moukafih
Ismail Moukafih

Reputation: 153

Just use onClick event like this.

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Card from '@material-ui/core/Card';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles((theme) => ({
  root: {
    flexGrow: 1,
  },
  card: {
    cursor: "pointer",
    padding: theme.spacing(2),
    textAlign: 'center',
    color: theme.palette.text.secondary,
  },
}));

function App() {
  const classes = useStyles();

  const clickMe = (event) => {
    console.log(event);
  }

  return (
      <div className={classes.root}>
        <Card className={classes.card} onClick={(event) => 
          {clickMe(event)}}>          
          <CardContent>
            <h4>test</h4>
          </CardContent>
          <CardActions>
            <Button size="small">Learn More</Button>
          </CardActions>
        </Card>
      </div>
  );
}

export default App;

Upvotes: 0

Just add onPress props in your card

 <Card
                          onPress = {() => {console.log('onclick')}}
                          style={styles.item}
                          status="basic"
                          header={(headerProps) =>
                            this.renderItemHeader(headerProps, item)
                          }>
                          <Text>{item.description}</Text>
                        </Card>

Upvotes: -1

425nesp
425nesp

Reputation: 7593

With Material UI 4.9.10, this works.

<Card>
    <CardActionArea href="https://google.com">
        <CardContent>
            <Typography>Click me!</Typography>
        </CardContent>
    </CardActionArea>
</Card>

If you're using react router, this also works.

<Card>
    <CardActionArea component={RouterLink} to="/questions">
        <CardContent>
            <Typography>Click me!</Typography>
        </CardContent>
    </CardActionArea>
</Card>

Upvotes: 60

Roy Hyunjin Han
Roy Hyunjin Han

Reputation: 5083

Here is the solution that worked for us, thanks to https://stackoverflow.com/a/50444524/192092

import { Link as RouterLink } from 'react-router-dom'
import Link from '@material-ui/core/Link'

<Link underline='none' component={RouterLink} to='/your-target-path'>
  <Card>
    <CardActionArea>
      ...
    </CardActionArea>
  </Card>
</Link>

Upvotes: 10

Uday
Uday

Reputation: 199

We can also use Link tag to make the whole Card component clickable and for navigation

import { Link } from 'react-router-dom';
function myCard() {
  return (
    <Link to={'/give_your_path'}>
     <Card>
      <Card text="This is text"/>
     </Card>
    </Link>
  );
}

Upvotes: 19

Rayne
Rayne

Reputation: 81

Just wrap the whole thing in the Material CardActionArea component. Everything inside of it will be clickable.

<CardActionArea>
   <CardMedia>
   .......Image Stuff
   </CardMedia>
   <CardContent>
   .......Content
   </CardContent>
</CardActionArea>

Upvotes: 7

Pier Paolo Ramon
Pier Paolo Ramon

Reputation: 2900

Update for v3 — 29 of August 2018

A specific CardActionArea component has been added to cover specifically this case in version 3.0.0 of Material UI.

Please use the following solution only if you are stuck with v1.

What you probably want to achieve is a Card Action (see specification) on the top part of the card.

The Material Components for Web library has this as its first usage example for the Card Component.

You can easily reproduce that exact behaviour by composing MUI Card* components with the mighty ButtonBase component. A running example can be found here on CodeSandbox: https://codesandbox.io/s/q9wnzv7684.

The relevant code is this:

import Card from '@material-ui/core/Card';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import Typography from '@material-ui/core/Typography';
import ButtonBase from '@material-ui/core/ButtonBase';

const styles = {
  cardAction: {
    display: 'block',
    textAlign: 'initial'
  }
}

function MyCard(props) {
  return (
    <Card>
      <ButtonBase
          className={props.classes.cardAction}
          onClick={event => { ... }}
      >
        <CardMedia ... />
        <CardContent>...</CardContent>
      </ButtonBase>
    </Card>
  );
}

export default withStyles(styles)(MyCard)

Also I strongly suggest to keep the CardActions component outside of the ButtonBase.

Upvotes: 58

Pandelis
Pandelis

Reputation: 1988

You could add an onClick={clickFunction} to the containing div of the card that links to the same function as the button.

Upvotes: 13

Related Questions