How to show dropdown options in fluent UI breadcrumbs - reactjs

i wanted to show dropdown in fluent ui breadcrumbs help on building the code. please refer below image
Reference image copied from azure devops

To show the dropdown menu at breadcrumbs, you need CommandBarButton as the trigger of the dropdown and menuProps that contain the menu's item objects and pass the CommandBarButton at Breadcrumb's last item onRenderContent event handler.
Don't forget to memoize both breadcrumb's items and dropdown menuProps.
import { CommandBarButton } from "#fluentui/react/lib/Button";
...
const menuProps: IContextualMenuProps = React.useMemo(() => {
return {
items: [
{
key: "def",
text: "Dev",
onClick: () => setEnvironment("Dev"),
onRenderContent: () => {
return <MenuItem label="Dev" environment={environment} />;
}
},
...
]
};
}, [environment, setEnvironment]);
const items: IBreadcrumbItem[] = React.useMemo(() => {
return [
{ text: "Files", key: "Files", onClick: _onBreadcrumbItemClicked },
{ text: "Folder 1", key: "f1", onClick: _onBreadcrumbItemClicked },
...
{ text: "Folder 6", key: "f6", onClick: _onBreadcrumbItemClicked },
{
text: "Folder 11",
key: "f11",
onClick: _onBreadcrumbItemClicked,
isCurrentItem: true,
onRenderContent: () => {
return (
<CommandBarButton
style={{
fontSize: 18,
fontWeight: "bold",
height: "30px",
padding: 0,
background: "transparent"
}}
text={environment}
iconProps={null}
disabled={false}
checked={false}
menuProps={menuProps}
/>
);
}
}
];
}, [environment, menuProps]);
This is the complete code:

Related

Material ui TreeItems change style conditionally based

I'm using TreeView, TreeItem of material ui.
I'm trying to style conditionally each node (selected, hover, focus).
actually what I'm trying to do is that only node that not disabledButton (props that come from outside) will be in right color.
only node that selectable will be in active color (expand node not means that node is selectable).
something like this example
I did this example, but the behavior is really weird, sometimes the "child-4" looks like the style of disabledButton even I sent the right props, maybe because it nested props, sometimes the other nested not get the right colors of the hover, focus and selected..
link for example (with colors)
example with different colors
I want it to be in real colors also with the theme (active should be like blue color, hover gray) so I created this example.
example with theme colors
sometimes it works as expected and sometimes is not.
I looked in this issue but it's not like my example but there it uses in classes but I don't want to send this way
After a little while this is what I got. I tried to match the design of the gif as good as possible.
I used this data which I derived from the question. This example has one disabled node and parent node (my-photo.jpg and zip directory). The data array can be expanded endlessly if it matches TreeData type.
export type TreeData = {
id: string;
name: string;
disabledButton: boolean;
children?: TreeData[];
};
const data: TreeData[] = [
{
id: "1",
name: "My Web Site",
disabledButton: false,
children: [
{
id: "2",
name: "images",
disabledButton: false,
children: [
{ id: "3", name: "logo.png", disabledButton: false },
{ id: "4", name: "body-back.png", disabledButton: false },
{ id: "5", name: "my-photo.jpg", disabledButton: true }
]
},
{
id: "6",
name: "resources",
disabledButton: false,
children: [
{
id: "7",
name: "pdf",
disabledButton: false,
children: [
{ id: "8", name: "brochure.pdf", disabledButton: false },
{ id: "9", name: "prices.pdf", disabledButton: false }
]
},
{
id: "10",
name: "zip",
disabledButton: true,
children: [{ id: "11", name: "test.zip", disabledButton: false }]
}
]
}
]
}
];
The CustomTreeView consists of CustomTreeItem that again makes use of CustomContent.
CustomContent is used to handle all events and to display another icon (folder) next to the expandIcon.
In the CustomTreeItem I set the width to fit-content to not select the whole row, but to match the example from the gif:
const CustomTreeItem = (props: TreeItemProps) => (
<TreeItem
ContentComponent={CustomContent}
{...props}
sx={{
width: "fit-content",
".MuiTreeItem-content": {
py: "2px",
width: "fit-content"
}
}}
/>
);
The interesting part is the styling of the CustomTreeView and its usage.
I have packed the classes into objects, which can be overwritten easily. The theming happens in the styles class which is in styles/Styles.ts.
// Styles.ts
import { createTheme } from "#mui/material";
export const getMuiTheme = () =>
createTheme({
palette: {
primary: {
main: "#2160dd"
},
secondary: {
main: "#d3d3d3"
}
}
});
// CustomTreeView.tsx
const classes = {
focused: {
bgcolor: "transparent",
py: "1px",
px: "7px",
border: `1px solid ${getMuiTheme().palette.secondary.main}`
},
selected: {
bgcolor: getMuiTheme().palette.primary.main,
color: "white"
}
};
const CustomTreeView = ({ data }: { data: TreeData[] }) => {
return (
<Box mt={2} ml={2} bgcolor="white" width="300px">
<ThemeProvider theme={getMuiTheme()}>
<TreeView
defaultCollapseIcon={<ArrowDropDownIcon />}
defaultExpandIcon={<ArrowRightIcon />}
defaultEndIcon={<InsertDriveFile />}
sx={{
".MuiTreeItem-root": {
".Mui-focused:not(.Mui-selected)": classes.focused,
".Mui-selected, .Mui-focused.Mui-selected, .Mui-selected:hover":
classes.selected
}
}}
>
{renderTreeData(data)}
</TreeView>
</ThemeProvider>
</Box>
);
};
To render arbitrarily nested data we make use of the recursive method renderTreeData. This way the data array can be expanded endlessly as long as it matches TreeData type.
export const renderTreeData = (data: TreeData[]) => {
return data.map((item) => (
<React.Fragment key={item.id}>
{item.children ? (
<CustomTreeItem
nodeId={item.id}
label={item.name}
disabled={item.disabledButton}
icon={<FolderOutlined />}
>
{renderTreeData(item.children)}
</CustomTreeItem>
) : (
<CustomTreeItem
nodeId={item.id}
label={item.name}
disabled={item.disabledButton}
icon={getFileIcon(item.name)}
/>
)}
</React.Fragment>
));
};
Live Demo

React Native SectionList with columns

I am trying to get a section list shown up having multiple columns.
Since section list have that feature not out of the box, I thought it might be a good idea to render a flatlist for every section item.. but I do not get it to work.
import React, { Component } from 'react';
import { StyleSheet, View, Text } from 'react-native';
import { FlatList } from "react-native";
import { SectionList } from "react-native";
class Account extends Component {
data2 =
[
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
data3 =
[
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28adfba',
title: '22--First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91adafa97f63',
title: '22--Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571efadfee29d72',
title: '22--Third Item',
},
];
data4 = ['a', 'b', 'c']
data = [
{sectionTitle: 'test-title-alpha', data: [this.data2]},
{sectionTitle: 'test-title-beta', data: [this.data3]},
];
_renderItem = ({item}) => {
console.log('render-item', item);
return (
<Text>item: {item}</Text>
)
}
_renderSectionHeader = ({item}) => {
console.log('section-header', item);
return (
<Text>section header: {item}</Text>
)
}
_renderSectionListItem = ({item}) => {
console.log('section-list-item', item);
return (
<FlatList
data={item}
numColumns={3}
renderItem={this._renderItem}
//keyExtractor={item => item.id}
/>
)
}
render () {
console.log('render', this.data);
console.log(this.data[0].sectionTitle);
return (
<SectionList
sections={this.data}
renderSectionHeader={this._renderSectionHeader}
renderItem={this._renderSectionListItem}
//keyExtractor={item => item.id}
/>
)
}
}
export default Account;
using data4 seems to proceed, using data2 or data3 seems not.
Anybody see my failure(s)?
Final output should be somethink near to:
first-section-title
item1.id item2.id item3.id
item1.title item2.title item3.title
item1.whatever item2.whatever item3.whatever
second-section-title
item4.id item5.id item6.id
item4.title item5.title item6.title
item4.whatever item5.whatever item6.whatever
...
(grid view, with x items per row)
from source
data = [
{
sectionTitle: 'first-section-title',
data: [
[
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d43',
title: 'and so on',
},
]
]
},
{
sectionTitle: 'second-section-title',
data: [
[
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: '5 Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: '6 Item',
},
]
]
},
];
working example (if somebody else should although need it)
import React, { Component } from 'react';
import { Text, View, FlatList, SectionList } from "react-native"
const sections = [
{
title: "Vegetables",
key: "vegetables",
data: [
{
list: [
{
name: "Carrot",
color: "Orange",
},
{
name: "Cabbage",
color: "Purple",
},
],
},
],
},
{
title: "Fruits",
key: "fruits",
data: [
{
list: [
{
name: "Apple",
color: "Green",
},
{
name: "Banana",
color: "Yellow",
},
{
name: "Strawberry",
color: "Red",
},
{
name: "Blueberry",
color: "Blue",
},
],
},
],
},
]
class Account extends Component {
renderSection = ({ item }) => {
return (
<FlatList
data={item.list}
numColumns={2}
renderItem={this.renderListItem}
keyExtractor={this.keyExtractor}
/>
)
}
renderSectionHeader = ({ section }) => {
return <Text>{section.title}</Text>
}
renderListItem = ({ item }) => {
return (
<View style={{height: 50, width: 100, borderColor: "green", borderWidth: 1 }}>
<Text>{item.name}</Text>
<Text>{item.color}</Text>
</View>
)
}
keyExtractor = (item) => {
return item.name
}
render () {
return (
<SectionList
sections={sections}
renderSectionHeader={this.renderSectionHeader}
renderItem={this.renderSection}
/>
)
}
}
export default Account;

React Material - MUIDataTable - how to update row data

I'm looking to implement an efficient way of updating individual row entries.
My way seems does not work. Just to add, i'm getting my data from redux state.
I was contemplating on using popup modals but i'm looking to implement a more efficient way.
// action
import { HrEmployeeData } from "../../actions/employeeHR";
const EmployeeTable = (props) => {
useEffect(() => {
props.HrEmployeeData();
}, []);
const classes = useStyles();
const columns = [
{ name: "name", label: "Name" },
{ name: "phone_no", label: "Contact" },
{ name: "email", label: "Email" },
{ name: "department", label: "Department" },
{ name: "job_title", label: "Title" },
{ name: "salary", label: "Salary" },
{ name: "date_employed", label: "Date Employed" },
{
name: "Action",
options: {
filter: true,
sort: false,
empty: true,
customBodyRender: (value, tableMeta, updateValue) => {
return (
<button
onClick={() =>
window.alert(`Clicked "Edit" for row ${value}`)
}
>
Edit
</button>
);
},
},
},
];
return (
<div className={classes.root}>
<Grid container spacing={3}>
<Grid item xs={12}>
<Paper className={classes.paper}>
<MUIDataTable
title={"Employees Records"}
data={props.employeesDetail}
columns={columns}
options={options}
/>
</Paper>
</Grid>
</Grid>
</div>
);
};
export default connect(mapStateToProps, { HrEmployeeData })(EmployeeTable);

How can I use a material-ui Popover with the actions of material-table in react?

I'm new on React and this is my first page that I created, I'm using material-table and material-ui to help me.
This is my code:
import React, { useState, useEffect } from 'react';
import { Fade } from "#material-ui/core";
import MaterialTable from 'material-table';
import { makeStyles } from '#material-ui/core/styles';
import api from '../../services/api.js';
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
width: '70%',
margin: 'auto',
marginTop: 20,
boxShadow: '0px 0px 8px 0px rgba(0,0,0,0.4)'
}
}));
function User(props) {
const classes = useStyles();
const [checked, setChecked] = useState(false);
const [tableData, setTableData] = useState([]);
let config = {
columns: [
{ title: 'Name', field: 'name' },
{ title: 'Sector', field: 'sector' },
{ title: 'E-mail', field: 'email'},
{ title: 'Tel', field: 'tel'}
],
actions: [
{ icon: 'create', tooltip: 'Edit', onClick: (event, rowData) => alert('Edit')},
{ icon: 'lock', tooltip: 'Block', onClick: (event, rowData) => alert('Block')},
{ icon: 'delete', tooltip: 'Delete', onClick: (event, rowData) => alert('Delete') },
{ icon: 'visibility', tooltip: 'Last Access', onClick: (event, rowData) => alert('Last') },
{ icon: "add_box", tooltip: "Add", position: "toolbar", onClick: () => { alert('Add') } }
],
options: {
headerStyle: { color: 'rgba(0, 0, 0, 0.54)' },
actionsColumnIndex: -1,
exportButton: true,
paging: true,
pageSize: 10,
pageSizeOptions: [],
paginationType: 'normal'
},
localization: {
body: {
emptyDataSourceMessage: 'No data'
},
toolbar: {
searchTooltip: 'Search',
searchPlaceholder: 'Search',
exportTitle: 'Export'
},
pagination: {
labelRowsSelect: 'Lines',
labelDisplayedRows: '{from} to {to} {count} itens',
firstTooltip: 'First',
previousTooltip: 'Previous',
nextTooltip: 'Next',
lastTooltip: 'Last'
},
header: {
actions: 'Actions'
}
}
}
useEffect(() => {
setChecked(prev => !prev);
async function loadUsers() {
const response = await api.get('/users');
setTableData(response.data);
}
loadUsers();
}, [])
return (
<>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<Fade in={checked} style={{ transitionDelay: checked ? '300ms' : '0ms' }}>
<div className={classes.root}>
<MaterialTable editable={config.editable} options={config.options} localization={config.localization} title="Usuários" columns={config.columns} data={tableData} actions={config.actions}></MaterialTable>
</div>
</Fade>
</>
);
}
export default User;
This code works, and list the users that I have on my database. My next step is create a Popover on actions Block and Delete to show to user a question to confirm if he really wanna delete or block the user on the line.
I have searched in documentation of material-ui (https://material-ui.com/components/popover/) how can I use the Popover with my table, but I cannot do this. I think I cannot use this prop aria-describedby={id}, but I don't know.
Someone can help me to achieve this or help to find a way?
I think you are not looking for a popover which is more like a small tooltip, but for a dialog, which needs attention from the user and blocks him from doing anything else.
Material-UI has a dialog component. You place it somewhere in the code. If the property "open" is true it blocks the user from doing anything else but confirming/canceling the deletion. If it set to false the dialog is not visible.
https://material-ui.com/components/dialogs/

Material ui v1 autocomplete - how to style it/ pass props to it?

Looking forward for any hint how to style new material ui v1 autocomplete or how to pass props to it.
Here's a codesandbox code (working example):
https://codesandbox.io/s/xrzq940854
In my particular case - I would like to style the label (which goes up after entering some value into input) and that horizontal line (underline under the input value).
Thank u for any help. (dropping code also in the snippet)
P.S. I got also a question how to pass props to the styles function. If anyone knows, please let me know :)
import React from 'react';
import PropTypes from 'prop-types';
import Autosuggest from 'react-autosuggest';
import match from 'autosuggest-highlight/match';
import parse from 'autosuggest-highlight/parse';
import TextField from 'material-ui/TextField';
import Paper from 'material-ui/Paper';
import { MenuItem } from 'material-ui/Menu';
import { withStyles } from 'material-ui/styles';
const suggestions = [
{ label: 'Afghanistan' },
{ label: 'Aland Islands' },
{ label: 'Albania' },
{ label: 'Algeria' },
{ label: 'American Samoa' },
{ label: 'Andorra' },
{ label: 'Angola' },
{ label: 'Anguilla' },
{ label: 'Antarctica' },
{ label: 'Antigua and Barbuda' },
{ label: 'Argentina' },
{ label: 'Armenia' },
{ label: 'Aruba' },
{ label: 'Australia' },
{ label: 'Austria' },
{ label: 'Azerbaijan' },
{ label: 'Bahamas' },
{ label: 'Bahrain' },
{ label: 'Bangladesh' },
{ label: 'Barbados' },
{ label: 'Belarus' },
{ label: 'Belgium' },
{ label: 'Belize' },
{ label: 'Benin' },
{ label: 'Bermuda' },
{ label: 'Bhutan' },
{ label: 'Bolivia, Plurinational State of' },
{ label: 'Bonaire, Sint Eustatius and Saba' },
{ label: 'Bosnia and Herzegovina' },
{ label: 'Botswana' },
{ label: 'Bouvet Island' },
{ label: 'Brazil' },
{ label: 'British Indian Ocean Territory' },
{ label: 'Brunei Darussalam' },
];
function renderInput(inputProps) {
const { classes, autoFocus, value, ref, ...other } = inputProps;
return (
<TextField
autoFocus={autoFocus}
className={classes.textField}
value={value}
inputRef={ref}
label="Country"
InputProps={{
classes: {
input: classes.input,
},
...other,
}}
/>
);
}
function renderSuggestion(suggestion, { query, isHighlighted }) {
const matches = match(suggestion.label, query);
const parts = parse(suggestion.label, matches);
return (
<MenuItem selected={isHighlighted} component="div">
<div>
{parts.map((part, index) => {
return part.highlight ? (
<span key={String(index)} style={{ fontWeight: 300 }}>
{part.text}
</span>
) : (
<strong key={String(index)} style={{ fontWeight: 500 }}>
{part.text}
</strong>
);
})}
</div>
</MenuItem>
);
}
function renderSuggestionsContainer(options) {
const { containerProps, children } = options;
return (
<Paper {...containerProps} square>
{children}
</Paper>
);
}
function getSuggestionValue(suggestion) {
return suggestion.label;
}
function getSuggestions(value) {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
let count = 0;
return inputLength === 0
? []
: suggestions.filter(suggestion => {
const keep =
count < 5 && suggestion.label.toLowerCase().slice(0, inputLength) === inputValue;
if (keep) {
count += 1;
}
return keep;
});
}
const styles = theme => ({
container: {
flexGrow: 1,
position: 'relative',
height: 200,
},
suggestionsContainerOpen: {
position: 'absolute',
marginTop: theme.spacing.unit,
marginBottom: theme.spacing.unit * 3,
left: 0,
right: 0,
},
suggestion: {
display: 'block',
},
suggestionsList: {
margin: 0,
padding: 0,
listStyleType: 'none',
},
textField: {
width: '100%',
},
label: {
color: 'yellow',
}
});
class IntegrationAutosuggest extends React.Component {
state = {
value: '',
suggestions: [],
};
handleSuggestionsFetchRequested = ({ value }) => {
this.setState({
suggestions: getSuggestions(value),
});
};
handleSuggestionsClearRequested = () => {
this.setState({
suggestions: [],
});
};
handleChange = (event, { newValue }) => {
this.setState({
value: newValue,
});
};
render() {
const { classes } = this.props;
return (
<Autosuggest
theme={{
container: classes.container,
suggestionsContainerOpen: classes.suggestionsContainerOpen,
suggestionsList: classes.suggestionsList,
suggestion: classes.suggestion,
}}
renderInputComponent={renderInput}
suggestions={this.state.suggestions}
onSuggestionsFetchRequested={this.handleSuggestionsFetchRequested}
onSuggestionsClearRequested={this.handleSuggestionsClearRequested}
renderSuggestionsContainer={renderSuggestionsContainer}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={{
autoFocus: true,
classes,
placeholder: 'Search a country (start with a)',
value: this.state.value,
onChange: this.handleChange,
}}
/>
);
}
}
IntegrationAutosuggest.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(IntegrationAutosuggest);
Material-UI v1 uses React-autosuggest module.
Check the below link
https://github.com/moroshko/react-autosuggest/blob/master/src/Autosuggest.js

Resources