Override officeUI nav chevron icon - reactjs

in the office-ui react fabric how do i over ride the chevon icon
https://developer.microsoft.com/en-us/fabric#/components/nav
In the documentation there is this interface
INavStyles
but i am not able to override it with my own icons. i want to replace the existing chevron with FolderHorizontal and OpenFolderHorizontal icons instead
import { AppContainer } from 'react-hot-loader';
import * as React from "react";
import * as ReactDOM from "react-dom";
import { Nav, INavProps } from 'office-ui-fabric-react/lib/Nav';
import { initializeIcons } from 'office-ui-fabric-react/lib/Icons';
initializeIcons(/* optional base url */);
....
....
public _getNavLink(): any[] {
return [
{
name: 'Home',
url: '',
links: [{
name: 'Activity',
url: '',
key: 'key1'
},
{
name: 'News',
url: '',
key: 'key2'
}],
isExpanded: true
}
]}
public render() {
return (
<div>
<Nav
getStyles={() => {
return {
chevronIcon: {
color: 'transparent',
transform: 'rotate(0)',
selectors: {
'&:before': {
color: 'rgb(51, 51, 51)',
fontFamily: "FabricMDL2Icons-7",
content: '"\\F12B"',
},
'.is-expanded > * > &:before': {
fontFamily: "FabricMDL2Icons-5",
content: '"\\ED25"',
}
}
}
}
}}
groups={
[
{
links: this._getNavLink()
}
]
}
expandedStateText={ 'expanded' }
collapsedStateText={ 'collapsed' }
selectedKey={ 'key3' }
/>
</div>
);
}

You could set the getStyles property on the Nav component to apply CSS to the chevronIcon slot:
<Nav
getStyles={ () => { return {
chevronIcon: {
color: 'transparent',
transform: 'rotate(0)',
selectors: {
'&:before': {
color: 'rgb(51, 51, 51)',
fontFamily: "FabricMDL2Icons-7",
content: '"\\F12B"',
},
'.is-expanded > * > &:before': {
fontFamily: "FabricMDL2Icons-5",
content: '"\\ED25"',
}
}
}
}} }
groups={...}
expandedStateText={ 'expanded' }
collapsedStateText={ 'collapsed' }
selectedKey={ 'key3' }
/>
The solution is basically hiding away the original chevron, disables the rotation and shows desired icons in the background.
Note that the icons for FolderHorizontal and OpenFolderHorizontal are set using their Unicode representation which can be looked up in the Github repo (e.g. https://github.com/OfficeDev/office-ui-fabric-react/search?q=FolderHorizontal). The two icons live in seperate font families, hence the fontFamily directive.
UPDATE [20180417]
Make sure the fonts are initialized using initializeIcons(); or using a custom path. The font files should then be loaded and appear in your DevTools:
Note that - unlike your code - we are using
import { initializeIcons } from '#uifabric/icons';
to import the initializeIcons.

Related

fontSize in Treemap react apexchart not working

I'm using react apexcharts to render a treemap
I'm using fontSize inside dataLabels to set fontSize but it isn't working.
dataLabels: {
//enabled: true,
style: {
fontSize: "20px",
},
Here is the screenshot
Also I have used -
return `${textList[0]}
${textList[1]}
${textList[2]}`
-to return string in multiple lines but that also doesn't seem to be working.
Below is the full code
import React from 'react';
//import ReactApexChart from 'react-apexcharts';
import { ApexOptions } from "apexcharts";
import dynamic from 'next/dynamic';
import { getTenantDetails } from "utils/assetOverview";
const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false });
type datapointType={
value: number
seriesIndex: number
dataPointIndex: number
}
type tenantType={
x:string,
y:number
}
const TreeMap : React.FC<{areaChecked:boolean,assetCode:string}> = ({areaChecked,assetCode}) => {
let {tenantList} = getTenantDetails(assetCode);
let tenants = [] as tenantType[]
tenants = tenantList && tenantList.map((tenant)=>{
if(areaChecked){
return {
"x":`${tenant.name}\n${tenant.area}ft (${tenant.percentage}%)\n${tenant.years}`,
"y":tenant.area
}
}else{
return {
"x":`${tenant.name}\n$${tenant.revenue} (${tenant.percentage}%)\n${tenant.years}`,
"y":tenant.revenue
}
}
})
const series =[
{
data:tenants
}
]
const options:ApexOptions = {
legend: {
show: false
},
colors:['#002776'],
chart: {
height: 260,
toolbar:{
show:false
}
},
plotOptions: {
treemap: {
enableShades: false
}
},
dataLabels: {
//enabled: true,
style: {
fontSize: "20px",
},
formatter: function(text:string,o:datapointType){
let textList = text.split("\n");
return `${textList[0]}
${textList[1]}
${textList[2]}`
}
}
}
return (
<React.Fragment>
<ReactApexChart options={options} series={series} type="treemap" height={260} />
</React.Fragment>
);
}
export default TreeMap;
Also tried to set fontSize in global.scss file but the text in each rectangle overflows- Here is the screenshot
.apexcharts-data-labels > text {
font-size: 10px !important;
}
SO tried to add
.apexcharts-data-labels > text {
overflow-wrap: break-word !important;
}
but the above code doesn't seem to work

dynamic ionic icon with react typescript

I want to make my IonIcons dynamic so they are reusable. But i need to set it in {} I dont know how i do this with a .map() element.
import React from "react";
import { IonIcon, IonLabel } from "#ionic/react";
import styles from "./quickOptions.module.css";
import { alarmOutline, personOutline, cartOutline } from "ionicons/icons";
export default function quichOptions() {
const quickOptions = [
{ title: "Jouw consulent", icon: { personOutline } },
{ title: "Jouw afspraken", icon: { alarmOutline } },
{ title: "Jouw bestellingen", icon: { cartOutline } },
];
return (
<div className={styles.mainContainer}>
{quickOptions?.map((element: any) => {
return (
<div key={element.title} className={styles.btnContainer}>
<IonLabel>{element.title}</IonLabel>
<IonIcon icon={element.icon} size="large" /> //here
</div>
);
})}
</div>
);
}
Element.icon does not give the output of {personOutline} for example does anybody know how to fix this??
you can check console.log(typeof element.icon)
const quickOptions = [
{ title: "Jouw consulent", icon: 'personOutline' },
];
<IonIcon icon={element.icon} size="large" />
if the icon type here is {string}, that's why it doesn't work
try it in quickOptions , icon: personOutline or icon: 'personOutline'

How to update MapboxGL.ShapeSource dynamically?

Using react-native-mapbox-gl/maps, when a SymbolLayer is dynamically added to a ShapeSource, it seems it is not shown, or the ShapeSource is not updated.
Here is the example to reproduce : based on CustomIcon example, I replaced the code with the code below. To reproduce, just execute the examples, copy-paste the code in place of the existing code in CustomIcon.js example.
import React from 'react';
import { View, Text } from 'react-native';
import MapboxGL from '#react-native-mapbox-gl/maps';
import sheet from '../styles/sheet';
import BaseExamplePropTypes from './common/BaseExamplePropTypes';
import Page from './common/Page';
import Bubble from './common/Bubble';
const styles = {
icon: {
iconAllowOverlap: true,
},
view: {
width: 60,
height: 60,
borderColor: 'black',
borderWidth: 1,
alignItems: 'center',
justifyContent: 'center'
},
text: {
fontSize: 50
}
};
const customIcons = ['😀', '🤣', '😋', '😢', '😬']
class CustomIcon extends React.Component {
constructor(props) {
super(props);
this.state = {
featureCollection: {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
coordinates: [-73.970895, 40.723279],
type: 'Point'
},
id: 1,
properties: {
customIcon: customIcons[0]
}
}]
},
};
this.onPress = this.onPress.bind(this);
this.onSourceLayerPress = this.onSourceLayerPress.bind(this);
}
onPress(e) {
const feature = {
type: 'Feature',
geometry: e.geometry,
id: Date.now(),
properties: {
customIcon: customIcons[this.state.featureCollection.features.length]
}
};
this.setState(({ featureCollection }) => ({
featureCollection: {
type: 'FeatureCollection',
features: [
...featureCollection.features,
feature
]
}
}));
}
onSourceLayerPress(e) {
const feature = e.nativeEvent.payload;
console.log('You pressed a layer here is your feature', feature); // eslint-disable-line
}
render() {
return (
<Page {...this.props}>
<MapboxGL.MapView
ref={c => (this._map = c)}
onPress={this.onPress}
style={sheet.matchParent}
>
<MapboxGL.Camera
zoomLevel={9}
centerCoordinate={[-73.970895, 40.723279]}
/>
<MapboxGL.ShapeSource
id="symbolLocationSource"
hitbox={{width: 20, height: 20}}
onPress={this.onSourceLayerPress}
shape={this.state.featureCollection}
>
{this.state.featureCollection.features.map((feature, ind) => (
<MapboxGL.SymbolLayer
id={"symbolLocationSymbols" + feature.id}
key={feature.id}
filter={['==', 'customIcon', customIcons[ind]]}
minZoomLevel={1}
style={styles.icon}
>
<View style={styles.view}>
<Text style={styles.text}>
{feature.properties.customIcon}
</Text>
</View>
</MapboxGL.SymbolLayer>
))}
</MapboxGL.ShapeSource>
</MapboxGL.MapView>
<Bubble>
<Text>Tap to add an icon</Text>
</Bubble>
</Page>
);
}
}
export default CustomIcon;
We can see that clicking on the map changes the state, adds a feature, but does not show the feature on the map.
How can we make the ShapeSource update dynamically ?
The whole discussion about the subject is in here: https://github.com/react-native-mapbox-gl/maps/issues/248
To make it short : I wanted to use dynamics SVGs as SymbolLayer (so that I can change the colour for instance), but this is not possible : giving SymbolLayer any child component is not a proper way to do.
We need instead to use Images in parallel of ShapeSource and SymbolLayer, because Images can be updated dynamically.
Here is a code example :
import React from 'react';
import MapboxGL from '#react-native-mapbox-gl/maps';
const myImages = {
'image-1': 'path/to/image-1',
'image-2': 'path/to/image-2'
}
const createFeature = ({
showPin,
icon = 'image-1', // as long as any added feature has an icon belonging to the static myImages, it works.
coordinates,
id
}) => ({
// https://github.com/react-native-mapbox-gl/maps/blob/master/docs/ShapeSource.md -> shapeSource prop
// https://geojson.org
// this has a geoJSON shape
type: 'Feature',
id,
properties: {
showPin,
icon
},
geometry: {
type: 'Point',
coordinates,
}
})
class MyMarkers extends React.Component {
state = {
featureCollection: MapboxGL.geoUtils.makeFeatureCollection(),
}
componentDidMount() {
this.updateFeatures()
}
componentDidUpdate(prevProps) {
// update features based on any criteria
if (conditionOnProps(prevProps, this.props)) this.updateFeatures()
}
updateFeatures() {
const featureCollection = MapboxGL.geoUtils.makeFeatureCollection()
for (let feature of this.props.features) {
MapboxGL.geoUtils.addToFeatureCollection(
featureCollection,
createFeature(feature)
)
}
this.setState({ featureCollection });
}
onPress = (e) => {
const feature = e.nativeEvent.payload;
this.props.doAnythingWithPressedFeature(feature);
}
render() {
return (
<>
<MapboxGL.Images images={myImages} />
<MapboxGL.ShapeSource
id='markersShape'
shape={this.props.featureCollection}
onPress={this.onPress}
>
<MapboxGL.SymbolLayer
id='markersSymbol'
filter={['==', 'showPin', true]}
style={{
iconAllowOverlap: true,
iconImage: ['get', 'icon'],
}}
/>
</MapboxGL.ShapeSource>
</>
)
}
}
export default MyMarkers;

Theme nesting with Material UI

I have many datatables throughout my website and for the most part they are all styled the same. There are several different styles I need to apply to some of them. I want to create a global theme for handling everything across the site including the basic datatable styles and I also want to have a local theme to tweak the individual datatables a little.
Here is what I've got.
https://codesandbox.io/embed/jolly-antonelli-fg1y1
This is structure like this
<Test>
<PrimaryThemeHere> //All have Border 1px red
<TestChild>
<SecondaryThemeHere> //blue background
<Datatable />
</SecondaryThemeHere>
</TestChild>
<TestChild2>
<SecondaryThemeHere> //Red background
<Datatable />
</SecondaryThemeHere>
<TestChild2>
</PrimaryThemeHere>
</Test>
The primary theme looks like this:
const theme = createMuiTheme({
overrides: {
MuiTableBody: {
root: {
border: "1px solid red"
}
},
MuiTableCell: {
root: {
border: "1px solid red"
}
}
}
});
and the nested theme looks like this:
getMuiTheme = () =>
createMuiTheme({
overrides: {
MuiTableRow: {
root: {
backgroundColor: "blue"
}
}
}
});
I can never get the border red to show alongside the background color. It always chooses one or the other. How can I get a combination of the initial primary theming (border 1px red) and the background color or blue and red.
Please help
Here's the relevant portion of the documentation:
https://material-ui.com/customization/themes/#nesting-the-theme
The code that handles theme nesting can be found here:
https://github.com/mui/material-ui/blob/master/packages/mui-system/src/ThemeProvider/ThemeProvider.js
Here is the current code:
// To support composition of theme.
function mergeOuterLocalTheme(outerTheme, localTheme) {
if (typeof localTheme === 'function') {
const mergedTheme = localTheme(outerTheme);
warning(
mergedTheme,
[
'Material-UI: you should return an object from your theme function, i.e.',
'<ThemeProvider theme={() => ({})} />',
].join('\n'),
);
return mergedTheme;
}
return { ...outerTheme, ...localTheme };
}
Notice that the final line (return { ...outerTheme, ...localTheme };) is doing a shallow merge of the two themes. Since both of your themes have the overrides property specified, the localTheme overrides will completely replace the outerTheme overrides.
However, you can do a more sophisticated merge of the two themes, by providing a function to the ThemeProvider. For instance TestChild can look like this:
import React, { Component } from "react";
import { MuiThemeProvider } from "#material-ui/core/styles";
import MUIDataTable from "mui-datatables";
const localTheme = {
overrides: {
MuiTableRow: {
root: {
backgroundColor: "blue"
}
}
}
};
const themeMerge = outerTheme => {
// Shallow copy of outerTheme
const newTheme = { ...outerTheme };
if (!newTheme.overrides) {
newTheme.overrides = localTheme.overrides;
} else {
// Merge the overrides. If you have the same overrides key
// in both (e.g. MuiTableRow), then this would need to be
// more sophisticated and you would probably want to use
// a deepMerge function from some other package to handle this step.
newTheme.overrides = { ...newTheme.overrides, ...localTheme.overrides };
}
return newTheme;
};
class TestChild extends Component {
render() {
const columns = [
{
name: "Message"
},
{
name: "Date"
},
{
name: "Dismiss"
}
];
const data = [["test", "15/01/19", "", ""], ["test", "15/01/19", "", ""]];
let options = {
filterType: "dropdown",
responsive: "stacked",
print: false,
search: false,
download: false,
selectableRows: "none"
};
return (
<div>
<MuiThemeProvider theme={themeMerge}>
<MUIDataTable
title={"Test"}
data={data}
columns={columns}
options={options}
/>
</MuiThemeProvider>
</div>
);
}
}
export default TestChild;
In my version of your sandbox, I only fixed TestChild2.js.
For me the whole inner theme worked, except the mode. I could fix it by adding a <Paper /> component.
import { createTheme, Paper, ThemeProvider } from "#mui/material";
const outerThemeOptions = {
palette: { mode: "light" },
typography: { body1: { fontSize: 14 } },
};
const innerThemeOptions = {
palette: { mode: "dark" },
};
const outerTheme = createTheme(outerThemeOptions);
const innerTheme = createTheme({
...outerThemeOptions,
...innerThemeOptions,
});
<ThemeProvider theme={outerTheme}>
<Child1 />
<ThemeProvider theme={innerTheme}>
<Paper elevation={0}>
<Child2 />
</Paper>
</ThemeProvider>
</ThemeProvider>;

I have a card component that I need to update to add new items

I built a card component that shows a list of user data and images with antd on nextJs. I want to build a functionality that creates a modal to input new data and image and adds it to the user interface as a new card, but I am confused on how to get my hands around it. I need assistance. Here's a link to my code!
import React from 'react';
import { Avatar, Card, Icon, List } from 'antd';
import { ICON_LIST, LIST_TEXTS, STYLES, USER_UPLOAD } from './constants';
const { AVATAR, CARD_CONTAINER, ICON, USER_LIST } = STYLES;
const { INNER, MORE, UPLOAD, VERTICAL } = LIST_TEXTS
class Home extends React.Component {
state = {
clicks: 0,
};
IncrementIconText = () => {
this.setState({ clicks: this.state.clicks + 1 });
}
render() {
const actions = ( ICON_LIST.map(({ type }) => (
<span>
<Icon key={type} type={type} onClick={this.IncrementIconText} style={ICON} />
{this.state.clicks}
</span>
)));
return (
<List
itemLayout={VERTICAL}
dataSource={USER_UPLOAD}
renderItem={item => (
<List.Item style={USER_LIST}>
<Card
actions={actions}
cover={<img alt={UPLOAD} src={item.image} />}
extra={<Icon type={MORE} />}
hoverable
title={<a><Avatar src={item.image} style={AVATAR} />{item.user}</a>}
type={INNER}
style={CARD_CONTAINER}
>
{item.story}
</Card>
</List.Item>
)}
/>
);
}
}
export default Home;
constants.js
export const ICON_LIST = [
{
key: "heart",
type: "heart",
},
{
key: "dislike",
type: "dislike",
},
{
key: "meh",
type: "meh",
},
]
export const LIST_TEXTS = {
INNER: "inner",
MORE: "more",
UPLOAD: "upload",
VERTICAL: "vertical",
};
export const STYLES = {
AVATAR: {
marginRight: 8
},
CARD_CONTAINER: {
width: "650px",
marginBottom: 50
},
ICON: {
marginRight: 8
},
USER_LIST: {
width: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center"
},
};
export const USER_UPLOAD = [
{
image: "http://sugarweddings.com/files/styles/width-640/public/1.%20The%20Full%20Ankara%20Ball%20Wedding%20Gown%20#therealrhonkefella.PNG",
story: "Today's my birthday next week! What do you think?",
user: "Chioma",
},
{
image: "https://dailymedia.com.ng/wp-content/uploads/2018/10/7915550_img20181007141132_jpeg01c125e1588ffeee95a6f121c35cd378-1.jpg",
story: "Going for an event. Do you like my outfit",
user: "Simpcy",
},
{
image: "https://i0.wp.com/www.od9jastyles.com/wp-content/uploads/2018/01/ankara-styles-ankara-styles-gown-ankara-tops-ankara-gowns-ankara-styles-pictures-latest-ankara-style-2018-latest-ankara-styles-ankara-ankara-styles.png?fit=437%2C544&ssl=1",
story: "Saturdays are for weddings. Yay or nay!",
user: "Angela",
},
]
So this could get you started:
https://codesandbox.io/s/1r7j6lom34?fontsize=14
I moved your static USER_UPLOAD into the state of Home and wrote a method to add a new upload to that state.
You would now need to come up with a component that shows your modal and calls AddUpload with the right values.
Also your card-actions don't seem to function properly. To fix that i suggest creating a wrapper component for Card that has a state with the appropriate click counters. That way every card has its own clickcounters.

Resources