how to focus an item programmatically reactjs - reactjs

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

How to swap MUI icon on IconButton when hovering

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>
);

Custom Menu Item in MUI Data Grid Toolbar

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}
/>
);
};

Search button to activate autocomplete googl maps places (React.js)

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

react material ui grow on left side

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.

Material ui anchor without hooks

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>
);
}

Resources