When page loaded, able to focus all items via pressing TAB,But there is pop up, I want to focus its child element on next press TAB instead of regular order when toggle.
popper element:
<Popper
aria-label="Profile Options"
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
>
{({ TransitionProps, placement }) => (
<Grow>
<Paper aria-label="Profile Options" style={DROPDOWN} variant="outlined">
<ClickAwayListener onClickAway={handleClose}>
<MenuList style={{ padding: 0 }} id="split-button-menu">
<div
ref={divRef} // target item!!
onKeyDown={e => {
if (e.key === 'Enter') {
handleMenuItemClick(3)
}
}}
role="link"
tabIndex={0}
>
<MenuItem onClick={event => handleMenuItemClick(3)} style={MENU_ITEM_3}>
<Text
style={{
fontFamily: uiStore.branding.font_family,
}}
text="Log Out"
variant="body1Medium"
/>
</MenuItem>
</div>
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
toggle callback:
const divRef = React.useRef<HTMLDivElement>(null)
const handleToggle = () => {
anchorRef1?.current?.focus()// expect it to focus on item
setOpen(prevOpen => !prevOpen)
}
I need to see the focus effect as seem pic below when item focused programmatically.
Related
I have these tabs that have a close button on them, if the content in them has edits then the close icon turns to a circle, similar to visual code.
{tabs.map((tab, index) => {
const child = (
<StyledTab
label={
<span>
{tab.label + ':' + tab.hasEdit}
<IconButton size="small" component="span" onClick={() => closeClickHandler(tab.value)}>
{tab.hasEdit ? (
<CircleIcon style={{ fontSize: "12px" }} />
) : (
<CloseIcon style={{ fontSize: "18px" }} />
)}
</IconButton>
</span>
}
value={tab.value}
key={index}
/>
);
return (
<DraggableTab
label={
<span>
{tab.label}
<IconButton size="small" component="span" onClick={() => {
closeClickHandler(tab.value);
}}>
{tab.hasEdit ? (
<CircleIcon style={{ fontSize: "12px" }} />
) : (
<CloseIcon style={{ fontSize: "18px" }} />
)}
</IconButton>
</span>
}
value={tab.value}
index={index}
key={index}
child={child}
/>
);
})}
What I'm having trouble with is getting the icon to change from a circle to a close icon while hovering over the button.
Could someone give me a hand on a good way to implement this please?!
You could do this by adding a state for the items. Then add a onMouseEnter and onMouseLeave events on the IconButton. When hovering we can add the index to the array and finally remove when we're leaving. To determine if a icon needs to change we can check if the index in in the hoveringItems.
const [hoveringItems, setHoveringItems] = useState([]);
function handleHover(index, isLeaving) {
setHoveringItems((prevItems) => {
if (isLeaving) return prevItems.filter((item) => item !== index);
return [...prevItems, index];
});
}
return (
<IconButton
size="small"
component="span"
onClick={() => {
closeClickHandler(tab.value);
}}
onMouseEnter={() => handleHover(index, false)}
onMouseLeave={() => handleHover(index, true)}
>
{tab.hasEdit || hoveringItems.includes(index) ? (
<CircleIcon style={{ fontSize: "12px" }} />
) : (
<CloseIcon style={{ fontSize: "18px" }} />
)}
</IconButton>
);
I'm currently using the Data Grid Toolbar (a feature of the Material-UI Data Grid component) because I want the Column Show/Hide component, but I also want to add my own menu item in the form of an IconButton with a Menu that opens when clicked. The issue is when you click said button, the Toolbar appears to re-render, which causes the Menu to lose its anchor and render in the upper left. Is there a special way to get an anchor within the Data Grid Toolbar for the Menu popper to appear in the correct location?
function CustomToolbar() {
return (
<GridToolbarContainer>
<Box
height="65px"
width="100%"
display="flex"
flexDirection="row"
justifyContent="center"
>
<Box width="300px" display="flex" justifyContent="flex-start" alignItems="center">
<GridToolbarColumnsButton sx={{ ml: 2 }} />
</Box>
<Box width="100%" alignSelf="center" textAlign="center">
<Typography sx={{ flex: "1 1 100%" }} variant="h6" component="div">
Title Goes Here
</Typography>
</Box>
<Box width="300px" display="flex" justifyContent="flex-end" alignItems="center">
<Tooltip title="Filter">
<IconButton
color="primary"
component="span"
disabled={loading}
sx={{ mr: 2 }}
onClick={handleMenuClick}
>
<FilterList />
</IconButton>
</Tooltip>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={() => handleClose(menuState, filters)}
transformOrigin={{ horizontal: "right", vertical: "top" }}
anchorOrigin={{ horizontal: "right", vertical: "bottom" }}
PaperProps={MenuProps}
>
<MenuItem /> //Clipped
<MenuItem /> //Clipped
<MenuItem /> //Clipped
</Menu>
</Box>
</Box>
</GridToolbarContainer>
);
}
You must create the Toolbar component outside of your component that declares the DataGrid, and get the properties you need through the DataGrid's componentsProps property.
GridToolbarCustom Component:
type Props = {
selectionModel: GridSelectionModel;
}
const GridToolbarCustom = ({ selectionModel }: Props) => {
const [anchorElMenu, setAnchorElMenu] = useState<null | HTMLButtonElement>(null);
const openMenu = Boolean(anchorElMenu);
return (
<GridToolbarContainer>
<Grid container item xs>
{/* default buttons */}
<GridToolbarColumnsButton />
<GridToolbarFilterButton />
<GridToolbarDensitySelector />
<GridToolbarExport />
</Grid>
<Grid>
<Button
variant="contained"
size="small"
disabled={selectionModel.length === 0}
startIcon={<MoreVertIcon />}
onClick={(event: MouseEvent<HTMLButtonElement>) => {
setAnchorElMenu(event.currentTarget);
}}
>
Actions
</Button>
<Menu
id="menu-options"
anchorEl={anchorElMenu}
open={openMenu}
onClose={() => {
setAnchorElMenu(null);
}}
>
<MenuItem /> //Clipped
<MenuItem /> //Clipped
<MenuItem /> //Clipped
</Menu>
</Grid>
</GridToolbarContainer>
);
}
export default GridToolbarCustom;
MyComponent:
import GridToolbarCustom from './GridToolbarCustom';
const MyComponent = () => {
const [selectionModel, setSelectionModel] = useState<GridSelectionModel>([]);
return (
<DataGrid
//Clipped
components={{
Toolbar: GridToolbarCustom,
}}
componentsProps={{
toolbar: {
selectionModel,
},
}}
checkboxSelection
onSelectionModelChange={(newSelectionModel) => {
setSelectionModel(newSelectionModel);
}}
selectionModel={selectionModel}
/>
);
};
I am using AutoComplete button from material/ui for searching Google Maps Places. Everything is working properly so when user clicks on the one offered field in autocomplete it leads him to next page.
My question is: is it possible to add search button to active autocomplete if user clicks on button?
Here is code for autocomplete and I have added button but still nothing happens if someone clicks on it.
<div className="search">
<Autocomplete
id="google-map-demo"
key={reset}
ListboxProps={{ style: { maxHeight: 400, overflow: 'auto',fontSize:'0.7rem' } }}
getOptionLabel={(option) =>
typeof option === "string" ? option : option.description
}
filterOptions={(x) => x}
options={options}
onChange={(e, l) => {
customer.setMyaddress(l.description);
getMyDestination(l.place_id);
}}
renderInput={(params) => (
<TextField
{...params}
className={classes.root}
variant="standard"
fullWidth
onChange={(e, v) => {
setInputValue(e.target.value);
}}
/>
)}
renderOption={(option) => {
const matches =
option.structured_formatting.main_text_matched_substrings;
const parts = parse(
option.structured_formatting.main_text,
matches.map((match) => [
match.offset,
match.offset + match.length,
])
);
return (
<Grid container alignItems="center">
<Grid item>
<LocationOnIcon className={classes.icon} />
</Grid>
<Grid item xs>
{parts.map((part, index) => (
<span
key={index}
style={{ fontWeight: part.highlight ? 700 : 400 }}
>
{part.text}
</span>
))}
<Typography variant="body2" color="red" className={classes.noOptions} >
{option.structured_formatting.secondary_text}
</Typography>
</Grid>
</Grid>
);
}}
/>
<button className="btn btn-primary" style={{position: "absolute",
right: "0"}}
onClick={(e, v) => {
setInputValue(e.target.value);
}}>Find</button>
</div>
Anyone has idea how to fix this so when clicked on button I got same result as clicked on autocomplete field?
Thank you
you use the open prop which is in the Autocomplete , i've forked the Autocomplete example from material-ui check it out:
https://codesandbox.io/s/material-demo-forked-3n5lw?file=/demo.js
How to make the context menu open not in the center of the button, but to the left of the button? With using properties Material UI.
Working example from link:
https://codesandbox.io/s/2f33z
Now this:
I want this:
Here is a link to an example from the documentation:
https://material-ui.com/components/menus/#menulist-composition
<div>
<Button
ref={anchorRef}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
>
Toggle Menu Grow
</Button>
<Popper open={open} anchorEl={anchorRef.current} role={undefined} transition disablePortal>
{({ TransitionProps, placement }) => (
<Grow
{...TransitionProps}
style={{ transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom' }}
>
<Paper>
<ClickAwayListener onClickAway={handleClose}>
<MenuList autoFocusItem={open} id="menu-list-grow" onKeyDown={handleListKeyDown}>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
</div>
Your Popper component should have a placement property of value bottom-start:
// ...
<Popper
placement="bottom-start"
// ...
>
// ...
For more options look here: https://material-ui.com/components/popper/#positioned-popper.
I have a menu component that pops open in a table. When I copy the material ui example into the cell in the table it works perfectly.
https://codesandbox.io/s/gitl9
The material ui example uses hooks and I want to change it to a class component and use redux.
When I made the change the pop-up menu does not align beside the the button you press anymore.
The anchorEl attribute is responsible for passing the location of the button that has been called.
I added these attributes allow me to move the menu pop but it does not align with button that you click to open the menu.
const options = ["View", "Edit", "Delete"];
const ITEM_HEIGHT = 48;
class ActionsOptionMenu extends Component {
state = { anchorEl: null };
render() {
return (
<div>
<IconButton
aria-label='more'
aria-controls='long-menu'
aria-haspopup='true'
>
<MoreVertIcon />
</IconButton>
<Menu
getContentAnchorEl={null}
anchorOrigin={{
height: "54px",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
padding: `0 ${padding} 0 ${padding}`,
margin: "0 auto 7px auto"
}}
transformOrigin={{ vertical: "top", horizontal: "right" }}
id='long-menu'
anchorEl={anchorEl}
keepMounted
open={true}
PaperProps={{
style: {
maxHeight: ITEM_HEIGHT * 4.5,
width: 120
}
}}
>
{options.map(option => (
<MenuItem key={option}>{option}</MenuItem>
))}
</Menu>
</div>
);
}
}
I solved the issue doing it this way.
render() {
const { open } = this.state;
return (
<div>
<IconButton
aria-label='more'
aria-controls='long-menu'
aria-haspopup='true'
buttonRef={node => {
this.anchorEl = node;
}}
onClick={event => this.handleClick(event)}
>
<MoreVertIcon />
</IconButton>
<Popper
open={open}
anchorEl={this.anchorEl}
transition
disablePortal
style={{ zIndex: 100 }}
>
{({ TransitionProps, placement }) => (
<Grow
{...TransitionProps}
id='menu-list-grow'
style={{
zIndex: 1001,
transformOrigin:
placement === "bottom" ? "center top" : "center bottom"
}}
>
<Paper>
<ClickAwayListener
onClickAway={event => this.handleClose(event)}
>
<MenuList>
<MenuItem onClick={event => this.handleClose(event)}>
Profile
</MenuItem>
<MenuItem onClick={event => this.handleClose(event)}>
My account
</MenuItem>
<MenuItem onClick={event => this.handleClose(event)}>
Logout
</MenuItem>
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
</div>
);
}