I've made a table with a folder icon that is clickable link. To improve UX, I'd like to make the clickable area of the link bigger. I would like to make the entire contents of 3 of 4 of the cells in a row should be clickable as a link.
Here's what I mean
I can successfully make each cell contents (as in icons or text) clickable, but that still represents only a small area in each cell.
I've tried wrapping the entire cell contents in the link, but it leads to messy mapping, and still does not make the entire contents of the cell clickable.
Here's where I'm at so far
...
interface IProps extends Omit<unknown, 'children'> {
folders?: IGetAllRequestDTO<IFolderDTO> | null;
reload: boolean;
}
const RootFoldersTable = ({ folders, reload }: IProps): JSX.Element => {
const [selectedRow, setSelectedRow] = useState('');
const classes = useStyles();
const dispatch = useDispatch();
const getCorrectFormat = useCallback(cell => {
return cell instanceof Date
? format(cell as Date, "MM/dd/yyyy hh:mmaaaaa'm'")
: cell;
}, []);
const getAllFolders = () => {
dispatch(appActions.getAllFoldersRequest({}));
};
useEffect(() => {
getAllFolders();
}, [reload]);
const openDialogWithId = (folderId: string) => {
dispatch(appActions.setDialogFormFolderId(folderId));
dispatch(appActions.setDialogOpen());
};
const onDeleteFolder = (id: string) => {
dispatch(appActions.deleteFolderRequest(id));
};
const tableHeadElements = [
{ label: 'Name', key: 'name', sortable: false },
{ label: 'Last Modified', key: 'updateAt', sortable: false },
{ label: 'Actions', sortable: false }
];
const tableHeadElements = [
{ label: 'Name', key: 'name', sortable: false },
{ label: 'Last Modified', key: 'updateAt', sortable: false },
{ label: 'Actions', sortable: false }
];
return (
<div className={classes.tableContainer}>
<TableContainer className={classes.tableBodyContainer}>
<Table className={classes.table} size="small">
<TableHead>
<TableRow className={classes.tableHeadRow}>
{tableHeadElements.map(e => (
<TableCell key={e.key} align="center">
{e.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{folders?.items.map((folder: IFolderDTO, index: number) => {
const { id, name, updatedAt } = folder;
return (
<TableRow
className={classes.tableRow}
classes={{ selected: classes.selectedRow }}
selected={selectedRow === id}
onClick={() => setSelectedRow(id)}
key={index}
>
<Link to={APP_DASHBOARD_CHILD_FOLDER_CONTENTS_PATH(id)}>
<TableCell align="center">
<IconButton color="default" size={'small'}>
<FolderIcon fontSize="default" />
</IconButton>
</TableCell>
</Link>
{[name, new Date(updatedAt)].map(cell => (
<TableCell key={index} align="center">
<Link to={APP_DASHBOARD_CHILD_FOLDER_CONTENTS_PATH(id)}>
{getCorrectFormat(cell)}
</Link>
</TableCell>
))}
<FolderActionsMenu
folderId={id}
onDeleteFolder={onDeleteFolder}
openDialogWithId={openDialogWithId}
/>
</TableRow>
);
})}
</TableBody>
Thanks!
You can create a header cell data array that describes anything you need to render the TableCell
:
const headerCellData = [
{
name: 'Calories',
link: '/',
},
{
name: 'Fat (g)',
link: '/?filter=fat',
align: 'right',
},
{
name: 'Carbs (g)',
link: '/?filter=carbs',
align: 'right',
},
{
name: 'Protein (g)',
align: 'right',
},
];
Then map each data item to the TableCell
:
<TableHead>
<TableRow>
{headerCellData.map((c) => (
<TableCell align={c.align}>
{c.link ? <Link to={c.link}>{c.name}</Link> : c.name}
</TableCell>
))}
</TableRow>
</TableHead>
make the entire contents of the cell clickable
If you want the entire cell clickable (not just the text), you need to play around with CSS a little bit. Remove the padding of TableCell
where it's unclickable and set the padding of the container that holds the link to 16px
which is the padding of the TableCell
we just removed:
<TableCell align={c.align} sx={{ padding: 0 }}>
<Box sx={{ padding: '16px' }}>
{c.link ? <Link to={c.link}>{c.name}</Link> : c.name}
</Box>
</TableCell>