I want to use Transfer Component from antd but I don't need the drop down menu as you can see in the below picture . How can I remove it?
It looks like the only way is through css selection since the component API doesn't have any control over it via props. Put below code in your css file:
span.ant-transfer-list-header-dropdown {
display: none;
}
DEMO
EDIT
It's possible to "change" the menu options by setting the selectAllLabels props of the component but you'd have to build the dropdown menu yourself. You'll still have to hide their header dropdown in CSS since you're replacing their menu with your own menu.
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Transfer, Dropdown, Menu, Space, Button } from "antd";
import { DownOutlined } from "#ant-design/icons";
const mockData = [];
for (let i = 0; i < 20; i++) {
mockData.push({
key: i.toString(),
title: `content${i + 1}`,
description: `description of content${i + 1}`
});
}
const initialTargetKeys = mockData
.filter((item) => +item.key > 10)
.map((item) => item.key);
const App = () => {
const [targetKeys, setTargetKeys] = useState(initialTargetKeys);
const [selectedKeys, setSelectedKeys] = useState([]);
const onChange = (nextTargetKeys, direction, moveKeys) => {
console.log("targetKeys:", nextTargetKeys);
console.log("direction:", direction);
console.log("moveKeys:", moveKeys);
setTargetKeys(nextTargetKeys);
};
const onSelectChange = (sourceSelectedKeys, targetSelectedKeys) => {
console.log("sourceSelectedKeys:", sourceSelectedKeys);
console.log("targetSelectedKeys:", targetSelectedKeys);
setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
};
const onScroll = (direction, e) => {
console.log("direction:", direction);
console.log("target:", e.target);
};
const leftLabel = ({ selectedCount, totalCount }) => (
<Space size={5}>
<Dropdown
placement="bottomLeft"
overlay={
<Menu>
<Menu.Item>
<a>Option 1</a>
</Menu.Item>
<Menu.Item>
<a>Option 2</a>
</Menu.Item>
<Menu.Item>
<a>Option 3</a>
</Menu.Item>
</Menu>
}
>
<DownOutlined style={{ fontSize: 11 }} />
</Dropdown>
{selectedCount > 0 ? `${selectedCount}/${totalCount}` : totalCount} items
</Space>
);
const rightLabel = ({ selectedCount, totalCount }) => (
<Space size={5}>
<Dropdown
placement="bottomLeft"
overlay={
<Menu>
<Menu.Item>
<a>Option A</a>
</Menu.Item>
<Menu.Item>
<a>Option B</a>
</Menu.Item>
<Menu.Item>
<a>Option C</a>
</Menu.Item>
</Menu>
}
>
<DownOutlined style={{ fontSize: 11 }} />
</Dropdown>
{selectedCount > 0 ? `${selectedCount}/${totalCount}` : totalCount} items
</Space>
);
return (
<Transfer
dataSource={mockData}
titles={["Source", "Target"]}
targetKeys={targetKeys}
selectedKeys={selectedKeys}
onChange={onChange}
onSelectChange={onSelectChange}
onScroll={onScroll}
render={(item) => item.title}
selectAllLabels={[leftLabel, rightLabel]}
/>
);
};
ReactDOM.render(<App />, document.getElementById("container"));
DEMO
Related
I have two buttons that show two different components when toggling them. For UX reasons (to know which component is showing) I would like to style the buttons according to if the value of the state is true or false (give them an underline and a darker color if the state is true). Is this possible in any way?
This is my GitHub repo: https://github.com/uohman/Portfolio2022
And this is the component where I handle the buttons:
`
import React, { useState } from 'react'
import ReactDOM from 'react-dom';
import { Subheading } from 'GlobalStyles';
import { FrontendProjects } from './FrontendProjects'
import { GraphicDesignProjects } from './GraphicDesignProjects';
import 'index.css'
export const FeaturedProjects = () => {
const [buttons, setButtons] = useState([
{ label: 'Development', value: true },
{ label: 'Graphic design', value: false }
]);
const handleButtonsChange = () => (label) => {
const newButtonsState = buttons.map((button) => {
if (button.label === label) {
return (button = { label: button.label, value: true });
}
return {
label: button.label,
value: false
};
});
setButtons(newButtonsState);
};
return (
<>
<Subheading><span>Featured projects</span></Subheading>
<SpecialButton {...{ buttons, setButtons, handleButtonsChange }} />
{buttons[0].value && <FrontendProjects />}
{buttons[1].value && <GraphicDesignProjects />}
</>
);
};
const SpecialButton = ({ buttons, setButtons, handleButtonsChange }) => {
return (
<div className="button-container">
{buttons.map((button, index) => (
<button
key={`${button.label}-${index}`}
onClick={() => handleButtonsChange({ buttons, setButtons })(button.label)}>
{button.label.toUpperCase()}
</button>
))}
</div>
);
};
const rootElement = document.getElementById('root');
ReactDOM.render(<FeaturedProjects />, rootElement);
`
I've given the buttons the pseudo element :focus and that nearly solves my problem, but still as a default the buttons are the same color although it is one of the components that is showing. Thankful for suggestions on how to solve this!
You can provide a style props to any html component.
You should pass an object where attributes are camelcased.
<button
style={{ // double bracket to pass an object
backgroundColor: yourVariable ? 'red' : undefined // notice css background-color became backgroundColor
}}
>
{button.label.toUpperCase()}
</button>
You can do the same with classes
<button
className={yourVariable && "yourClass"}
>
{button.label.toUpperCase()}
</button>
You can set styles for button based on a condition.
In this use case, you already have the state button.value which can be used as a condition to set inline styles (or classes) for the mapped button.
Example:
const SpecialButton = ({ buttons, setButtons, handleButtonsChange }) => {
return (
<div className="button-container">
{buttons.map((button, index) => (
<button
key={`${button.label}-${index}`}
// ๐ This property is added
style={{
backgroundColor: button.value ? "#aaa" : "#eee",
textDecoration: button.value ? "underline" : "none",
}}
onClick={() =>
handleButtonsChange({ buttons, setButtons })(button.label)
}
>
{button.label.toUpperCase()}
</button>
))}
</div>
);
};
The buttons are set to become darker when selected in the above example, but you can further customize the styles for the desired result.
More about inline styles
On a side note, it is not necessary to pass state values to the the event by onClick={() => handleButtonsChange({ buttons, setButtons })(button.label)}.
The parent component always have these values, so you do not need to pass it down to SpecialButton and pass it back.
Hope this will help!
Full example:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Subheading } from "GlobalStyles";
import { FrontendProjects } from "./FrontendProjects";
import { GraphicDesignProjects } from "./GraphicDesignProjects";
import "index.css";
export const FeaturedProjects = () => {
const [buttons, setButtons] = useState([
{ label: "Development", value: true },
{ label: "Graphic design", value: false },
]);
const handleButtonsChange = (label) => {
const newButtonsState = buttons.map((button) => {
if (button.label === label) {
return (button = { label: button.label, value: true });
}
return {
label: button.label,
value: false,
};
});
setButtons(newButtonsState);
};
return (
<>
<Subheading>
<span>Featured projects</span>
</Subheading>
<SpecialButton {...{ buttons, handleButtonsChange }} />
{buttons[0].value && <FrontendProjects />}
{buttons[1].value && <GraphicDesignProjects />}
</>
);
};
const SpecialButton = ({ buttons, handleButtonsChange }) => {
return (
<div className="button-container">
{buttons.map((button, index) => (
<button
key={`${button.label}-${index}`}
// ๐ This property is added
style={{
backgroundColor: button.value ? "#aaa" : "#eee",
textDecoration: button.value ? "underline" : "none",
}}
onClick={() =>
handleButtonsChange(button.label)
}
>
{button.label.toUpperCase()}
</button>
))}
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<FeaturedProjects />, rootElement);
I wanted to change the style of an item with one click in a list and remove it if I click another item
I did like this but when I click on the second it doesnโt change to the first
const ref = useRef();
const handleClick = () => {
if (ref.current.style.backgroundColor) {
ref.current.style.backgroundColor = '';
ref.current.style.color = '';
} else {
ref.current.style.backgroundColor = 'green';
ref.current.style.color = 'white';
}
};
<Card ref={ref} elevation={6} style={{ marginBottom: "5px"}} onClick={()=>{ handleClick()}} >
<CardContent style={{ height: "10px" }}>
<Typography >
{user}
</Typography>
</CardContent>
</Card>
);
};
any help please!
I like using a package like classnames ( yarn add classnames or npm i classnames) to apply conditional styling through classes rather than having to inline the element's styling directly.
You could pass the selected attribute to your Card component using React's useState (or Redux) and then apply conditional styling to selected cards (i.e. <Card selected />).
Component.js
import { useState } from 'react';
import { useSelector } from 'react-redux';
import Card from './Card';
const Component = () => {
const [selectedId, setSelectedId] = useState(null);
const items = useSelector(state => state.items);
const handleClick = (id) => {
setSelectedId(id);
};
return items.map(({id}) =>
<Card
key={id}
onClick={() => handleClick(id)}
selected={id === selectedId}
>
...
</Card>
);
};
export default Component;
Card.js
import { classNames } from 'classnames';
const Card = ({ children, onClick, selected = false }) => (
<div
className={
classNames('Card', {
'Card--Selected': selected
})
}
onClick={onClick}
>
{ children }
</div>
);
export default Card;
Card.scss
.Card {
// Card styling...
&--Selected {
// Selected card styling...
}
}
I'm trying to change styling of Typography component embedded inside MenuItem. I'm unable to add styling on ListItem but unable to do so
Here is the link to my code: https://codesandbox.io/s/dztbc?file=/demo.tsx:1481-1804
Expected behavior: Change styling when selected. Color of Access should turn green and fontWeight bolder on selection
Current behavior: Styling only getting applied to 'light mail' when selected. How can I resolve it?
MenuItem accepts a style rule for the selected item as in classes prop by the key name selected. But for this to work item should also receive a boolean select prop, whether the item is selected or not.
const StyledMenuItem = withStyles((theme) => ({
root: {
"&:focus": {
backgroundColor: theme.palette.primary.main,
},
},
selected: {
color: "red",
}
}))(MenuItem);
export default function CustomizedMenus() {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [selected, setSelected] = React.useState(null);
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const handleMenuItemClick = (e, index) => {
setSelected(index);
};
const menuArr = [
{
Icon: SendIcon,
text: "Sent mail"
},
{
Icon: DraftsIcon,
text: "Sent mail"
},
{
Icon: InboxIcon,
text: "Inbox"
}
];
return (
<div>
<Button
aria-controls="customized-menu"
aria-haspopup="true"
variant="contained"
color="primary"
onClick={handleClick}
>
Open Menu
</Button>
<StyledMenu
id="customized-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
{menuArr.map((item, index) => (
<StyledMenuItem
selected={index === selected}
onClick={(event) => handleMenuItemClick(event, index)}
>
<ListItemIcon>
<item.Icon fontSize="small" />
</ListItemIcon>
<ListItemText primary={item.text} />
</StyledMenuItem>
))}
</StyledMenu>
</div>
);
}
Here is a working demo:
I'm trying to get rid of the labelDisplayedRows function from the table pagination actions in Material UI's table.
I just want to display the next/previous icons in the footer.
I can disable the option to select a number of rows by making the options list a single number, and that gets rid of the select menu from the footer, but I can't find a way to get rid of the label showing the counter (eg: 1 of 5).
I've seen this documentation and this API outline but I can't find a way to ask for that counter not to be displayed.
Currently I have:
import React from 'react';
import PropTypes from 'prop-types';
import { makeStyles, useTheme } from '#material-ui/core/styles';
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import TableContainer from '#material-ui/core/TableContainer';
import TableFooter from '#material-ui/core/TableFooter';
import TablePagination from '#material-ui/core/TablePagination';
import TableRow from '#material-ui/core/TableRow';
import Paper from '#material-ui/core/Paper';
import IconButton from '#material-ui/core/IconButton';
import FirstPageIcon from '#material-ui/icons/FirstPage';
import KeyboardArrowLeft from '#material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRight from '#material-ui/icons/KeyboardArrowRight';
import LastPageIcon from '#material-ui/icons/LastPage';
const useStyles1 = makeStyles((theme) => ({
root: {
flexShrink: 0,
marginLeft: theme.spacing(2.5),
},
}));
function TablePaginationActions(props) {
const classes = useStyles1();
const theme = useTheme();
const { count, page, rowsPerPage, onChangePage } = props;
const handleFirstPageButtonClick = (event) => {
onChangePage(event, 0);
};
const handleBackButtonClick = (event) => {
onChangePage(event, page - 1);
};
const handleNextButtonClick = (event) => {
onChangePage(event, page + 1);
};
const handleLastPageButtonClick = (event) => {
onChangePage(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
};
return (
<div className={classes.root}>
<IconButton
onClick={handleFirstPageButtonClick}
disabled={page === 0}
aria-label="first page"
>
{theme.direction === 'rtl' ? <LastPageIcon /> : <FirstPageIcon />}
</IconButton>
<IconButton onClick={handleBackButtonClick} disabled={page === 0} aria-label="previous page">
{theme.direction === 'rtl' ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
</IconButton>
<IconButton
onClick={handleNextButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="next page"
>
{theme.direction === 'rtl' ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
</IconButton>
<IconButton
onClick={handleLastPageButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="last page"
>
{theme.direction === 'rtl' ? <FirstPageIcon /> : <LastPageIcon />}
</IconButton>
</div>
);
}
TablePaginationActions.propTypes = {
count: PropTypes.number.isRequired,
onChangePage: PropTypes.func.isRequired,
page: PropTypes.number.isRequired,
};
function createData(number, icon, heading, explanation) {
return { number, icon, heading, explanation };
}
const rows = [
createData(1, "sdkfj", 'Cupcake 2', 305),
createData(2, "sdksdfs fj",'Cupcake3', 305),
createData(3, "sdksddddfs fj",'Cupcake3', 305),
createData(4, "sdk ff sdfs fj",'Cupcake3', 305),
].sort((a, b) => (a.number < b.number ? -1 : 1));
const useStyles2 = makeStyles({
table: {
// minWidth: 500,
},
});
export default function CustomPaginationActionsTable() {
const classes = useStyles2();
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(1);
// const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
return (
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="The design studio supports research">
<TableBody>
{(rowsPerPage > 0
? rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
: rows
).map((row) => (
<TableRow key={row.number}>
<TableCell align="right">
{row.icon}
</TableCell>
<TableCell component="th" scope="row" style={{ width: "80%" }}>
{row.heading}
{row.explanation}
</TableCell>
</TableRow>
))}
</TableBody>
<TableFooter>
<TableRow>
<TablePagination
colSpan={3}
rowsPerPage={rowsPerPage}
rowsPerPageOptions={[1]}
onChangePage={handleChangePage}
ActionsComponent={TablePaginationActions}
/>
</TableRow>
</TableFooter>
</Table>
</TableContainer>
);
}
This won't map over the data options (I'll try to figure out why later). For now, I'm trying to find a way to get rid of the page counter from the footer.
For now - I render a NaN:
One of the common methods you can try to use CSS by including styles.
import './custom.css'
custom.css file
.MuiTablePagination-caption { /* Class generated from your code */
display: none;
}
Output:
Codesandbox demo: https://codesandbox.io/s/intelligent-monad-75y7b
Note that it only hides it from the user but the element is still on the DOM. You can see it through the Developer Tools.
Just set the rowsPerPageOptions to a single array item. The library automatically hides
rowsPerPagesOptions that are less than two.
In your case
<TablePagination
colSpan={3}
rowsPerPageOptions=[10] //rowPerPageOption takes array parameters
...
/>
I have Navigation Tab of material-ui used for my React Project.The selected active Tab must have background color and then switch back to original color when not active.The transparent is applied to both tabs and not the selected active tabs in the below code.I want to apply some background color for active tabs only. Any solution?
Here is the code for Navigation Tab
import React from 'react';
import PropTypes from 'prop-types';
import SwipeableViews from 'react-swipeable-views';
import { makeStyles, useTheme } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Tabs from '#material-ui/core/Tabs';
import Tab from '#material-ui/core/Tab';
import Typography from '#material-ui/core/Typography';
import Box from '#material-ui/core/Box';
import ForecastDays from '../forecast/index';
const TabPanel = (props) => {
const { children, value, index, ...other } = props;
return (
<Typography
component="div"
role="tabpanel"
hidden={value !== index}
id={`full-width-tabpanel-${index}`}
aria-labelledby={`full-width-tab-${index}`}
{...other}
>
<Box p={3}>{children}</Box>
</Typography>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.any.isRequired,
value: PropTypes.any.isRequired,
};
const a11yProps = (index) => {
return {
id: `full-width-tab-${index}`,
'aria-controls': `full-width-tabpanel-${index}`
};
}
const useStyles = makeStyles(theme => ({
root: {
backgroundColor: 'none',
width: 275,
marginLeft:72,
marginTop:40
},
}));
const DailyHourly = (props) => {
const classes = useStyles();
const theme = useTheme();
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
const handleChangeIndex = index => {
setValue(index);
};
const {forecastdays, hourlyforecast} = props
return (
<div className={classes.root}>
<AppBar position="static" color="default" style={{background: 'transparent'}}>
<Tabs
value={value}
onChange={handleChange}
indicatorColor="secondary"
textColor="primary"
variant="fullWidth"
aria-label="full width tabs example"
>
<Tab label="Daily" {...a11yProps(0)}
/>
<Tab label="Hourly" {...a11yProps(1)}
/>
</Tabs>
</AppBar>
<SwipeableViews
axis={theme.direction === 'rtl' ? 'x-reverse' : 'x'}
index={value}
onChangeIndex={handleChangeIndex}
>
<TabPanel value={value} index={0} dir={theme.direction}>
<ForecastDays forecastdays={forecastdays}/>
</TabPanel>
<TabPanel value={value} index={1} dir={theme.direction}>
<ForecastDays hourlyforecast={hourlyforecast}/>
</TabPanel>
</SwipeableViews>
</div>
);
}
export default DailyHourly
Watch out images for reference below.
Any suggestions highly appreciated... Thanks in advance
You can add a class based on the current active tab value. Something like below. You may have to create another function , if you don't know the number of tabs beforehand.
<Tab className={value === 0 ? classes.active : ""} label="Daily" {...a11yProps(0)}
/>
<Tab className={value === 1 ? classes.active : ""} label="Hourly" {...a11yProps(1)}
/>
Codesandbox - https://codesandbox.io/s/pedantic-ives-t7sir