Icon is not visible in PivotItem in fluent ui - reactjs

I am creating a view using fluent in react. I used to pivot to display the top navigation but the icon in the tab is not visible even on using the itemIcon property in the PivotItem.
This is the code snippet I used
return <div>
<Pivot>{
headerItems.map( (item: IHeaderItem) => (
<PivotItem itemKey = {item.id} headerText = {item.name} itemIcon="Globe">
</PivotItem>
))
}
</Pivot>
</div>

By default, the font-based Fluent UI icons are not added to your bundle or loaded on the page, in order to save bytes for scenarios where you don't care about icons, or you only care about a subset.
To make the icons available, you may initialize them as follows. Note that initializeIcons() should only be called once per app and must be called before rendering any components. This is typically done in the app's top-level file just before the main ReactDOM.render() call.
import { initializeIcons } from '#fluentui/react/lib/Icons';
initializeIcons();

Related

Fluent UI and ReactDOM.createPortal bug

I'm currently working with Fluent UI to create a web app, and in this app I'm attempting to create a Fluent UI Dialog with a custom component that contains a Fluent UI ComboBox inside of it. I'm calling ReactDOM.createPortal on return from the render method inside of my custom React object. Upon first use of the Dialog my ComboBox functions as expected, i.e. the dropdown shows properly and it allows me to select and interact with my page as intended. However, when closing the Dialog after having already interacted with the ComboBox, upon re-opening the Dialog the ComboBox no longer displays the dropdown (although I can see the options are still there, just somewhere in the background). I've tried adjusting the zIndex of the ComboBox, it's container, etc. with no luck. I'm starting to think that it's an issue with ReactDOM.createPortal whenever the component is re-rendered after having been interacted with in a previous render, and figured I'd see if anyone has ever tried to do something similar. Thanks so much in advance!
render() {
const {options, changeOptions} = this.store;
return (
<>
{!!this.item && buttonTexts.length && ReactDOM.createPortal(
<ComboBox
label='Title'
selectedKey={changeOptions}
onChange={this.changeOptionDisplaying}
options={options.map(text => ({ key: text, text }))}
/>,
this.item
)}
<div ref={this.setRef} dangerouslySetInnerHTML={{ __html: this.props.htmlString}} />
</>
)
}
// this.item is an HTMLDivElement

System to manage reactjs applications

I get how to specify where to render the reactjs application by using the render method and specifying the html tag where it should be rendered.
What I do not understand is how you can have a list of react.js applications that is dynamically loaded into that same HTML tag.
For example there is a sidebar which is dynamically created to give a user a list of N number of react.js applications. When the user clicks on one of the links it loads that application into the HTML tag (div or whatever) container on the right.
I am sure this may be something easy but have been struggling with this concept for awhile.
Would appreciate any inputs anyone has on this.
If you truly had multiple full apps you wanted to swap out, you'd have to manually mount and unmount them. Something like a function like this, that unmounts the previous app, then mounts a new one. Example
function swapApp(App) {
const appNode = document.getElementById('app')
ReactDOM.unmountComponentAtNode(appNode)
ReactDOM.render(<App />, document.getElementById('app'))
}
But that would be a pain. So, typically, that menu and the content being changed are all part of the same react app. This app would render the menu, keep state about what item you clicked, and then render some components conditionally, depending on what was clicked.
Something like this example
function App() {
const [showingItem, setShowingItem] = React.useState(null)
return (
<>
<p><a href="#" onClick={() => setShowingItem('A')}>Show Item A</a></p>
<p><a href="#" onClick={() => setShowingItem('B')}>Show Item B</a></p>
{showingItem === 'A' ? <AppA /> : null}
{showingItem === 'B' ? <AppB /> : null}
</>
)
}

How to pass padding/margin as props in React-Bootstrap components

I am trying to apply margins and paddings with React-Bootstrap as props.
I passed the docs through but haven't found any mention adding padding or margin in there as it is in official bootstrap docs (3th and 4th). I know it doesn't support well Bootstrap 4, so tried with both.
I tried to pass params as p={1}, paddingxs={5} or mt='1' but it doesn't recognize any of them. More over tried to find any Spacing element in React-Bootstrap folder, but failed.
Paddings and margins work as classnames. But I feel there must be a way to it without Bootstrap classes. There must be a kind of property.
First include bootstrap CSS in your src/index.js or App.js
import 'bootstrap/dist/css/bootstrap.min.css';
Then you can style your component by passing desired bootstrap CSS class name as className prop in React, for example:
import React from "react"
import Container from "react-bootstrap/Container";
function MyComponent() {
return (
<Container fluid className="p-0">
<SomeOtherComponent />
</Container>
);
}
export default MyComponent
Above code will add p-0 CSS class to Container.
Reference
React - How do I add CSS classes to components?
React-Bootstrap - Stylesheets
You can add margin and padding by using default React's style:
const divStyle = {
marginLeft: '10px',
};
function HelloWorldComponent() {
return <div style={divStyle}>Hello World!</div>;
}
Refrenced from here
The answer is: there is no props from React Bootstrap to use margins/paddings.
You can use props for col class, but no for margins.
Example:
<Col className="col-6 col-md-3 mb-3 pt-2">
// there you have a Col component from React-Bootstrap 4
// it has some grid system classes, that you can use as props like this:
https://react-bootstrap.github.io/layout/grid/
<Col xs={6} md={3} className="mb-3 pt-2">
// but as you can see, the native classes of Bootstrap 4 like
// mt, mb, pt, pb etc, they have not a props use with
// React-Bootstrap, you have to use them like regular classes
// inside "className"
You'll want to add className="p-5" to the element. This isn't documented in react-bootstrap but it's in the original Bootstrap 4 documentation here: https://getbootstrap.com/docs/4.4/utilities/spacing/#examples
Usually, I'm able to add custom styles to React Bootstrap components by just adding them to the style param. I've put together a short example below, hope this helps.
import React from 'react';
import { Button } from 'react-bootstrap';
const styles = {
myCoolButton: {
paddingTop: "10vh",
paddingBottom: "10vh",
paddingRight: "10vw",
paddingLeft: "10vw"
}
}
const ReactButton = (props) => {
return (
<Button style={styles.myCoolButton} onClick={()=> {
console.log("Do something here!")
}}>Click Me!</Button>
);
}
export default ReactButton
You can also pass custom components (including those from react-bootstrap) into the styled-components constructor if you prefer to do it that way.
None of the jQuery-free implementations of Bootstrap (React Bootstrap, BootstrapVue or ngBootstrap) have implemented utility directives for spacing (margin/padding), simply because Bootstrap have made it unnecessary in the vast majority of cases, by providing a very intuitive set of Spacing utility classes.
All you need to do is apply the desired class.
To apply utility classes selectively, based on responsiveness interval (media queries), you could use a useMedia hook, as demoed here.
In a nutshell:
const interval = useMedia([
"(min-width: 1200px)",
"(min-width: 992px)",
"(min-width: 768px)",
"(min-width: 576px)"
],
["xl", "lg", "md", "sm"],
"xs"
);
(Based on useMedia from useHooks/useMedia).
You can now reuse this hook throughout your app to add media interval based logic.
Example usages:
// interval === 'sm' ? a : b
// ['xs', 'sm'].includes(interval) ? a : b
// negations of the above, etc...
Important: this particular implementation returns the first matching media query in the list.
If you need to map various media queries, to an object/map with true/false values, you'll need to modify getValue fn to return the entire list, along these lines:
const getValue = () => {
const matches = mediaQueryLists.map(mql => mql.matches);
return values.reduce((o, k, i) => ({...o, [k]: matches[i]}), {})
};
Working example here.
Obviously, you could expand on it and add/remove queries. However, be warned each query adds a separate listener so it could impact performance.
In most cases, the return of the first matching query (first example) is enough.
Note: if the above useMedia hook is not enough for your use case, a more robust and heavily tested solution for media-query listeners in JS is enquire.js. It's easy to use, incredibly light and thoroughly tested cross-browser/cross-device. I have no affiliation with it, but I have used it in various projects over the course of more than a decade. In short, I couldn't recommend it more.
Back to Bootstrap 4: in order to customize the $spacer sizes, follow the guide provided under Bootstrap's theming as it's actually about more than what we typically call theming (changing colors), it's about overriding default values of Bootstrap's SASS defaults, including responsivenss breakpoints, spacers, number of columns and many, many others. The one you're interested in is $spacer.
Simply write the overrides into an .scss file and import it in your root component. Example.
Note: a (simpler and more intuitive) option to customize Bootstrap is to do it visually, using bootstrap.build but it's typically a few minor versions behind (i.e. Bootstrap is now at v4.4.1 and the build tool is at v4.3.0).
The build customizer provides intuitive controls and real time visualization.
It allows export as .css or .scss.
Just try this out once according to your input and still if face any issue you can reach out.In below we have increased the .col padding with .px-md-5 and then countered then with .mx-md-n5 on the parent .row.
JSX:
import React from 'react'
import { MDBContainer, MDBRow, MDBCol } from 'mdbreact';
const SpacingPage = () => {
return (
<MDBContainer>
<MDBRow className="mx-md-n5">
<MDBCol size="6" className="py-3 px-md-5">Custom column padding</MDBCol>
<MDBCol size="6" className="py-3 px-md-5">Custom column padding</MDBCol>
</MDBRow>
</MDBContainer>
)
}
export default SpacingPage;
If you still have any kind of doubt on this then feel free to ask .

How to create popup with YouTube video that not affect main page?

I'm trying to have popup window with YouTube video that not affect the main page.
I can still interact with the main page, similar on this web site when you click track you have small popup video on right bottom corner.
I have App.js with YouTube API
{
getYouTubeApi = (searchTerms1, searchTerms2) => {
fetch(`https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=10&q=${searchTerms1} ${searchTerms2}&type=video&key=YOUR_KEY`)
.then(res=>res.json())
.then(data=>{
this.setState({videoId: data.items[0].id.videoId})
})
.catch(error=>console.log(error))
}
render(){
return (<YouTube opts={opts} videoId={this.state.videoId} />)
}
}
getYouTubeApi function I call on click on track that just bring to the top of my page where YouTube video loads.
Here is my school project.
Since this describes DOM behavior more than business logic, you could put in whatever you want in a specific component that behaves like a modal (whether by swapping out css classes or setting inline styles based on certain conditions).
To make this modal reusable, I'll suggest you make it a higher order component to wrap around <Youtube /> component or any other component you want to display with modals.
For example, you could have
const Modal = (ComponentToDisplayAsModal, props) => (
<div class="modal">
<ComponentToDisplayAsModal {...props} />
</div>
)
You could then style the modal class to behave like a modal.
On the view you wish to show your modal, you could render
Modal(Youtube, props)

is there a way to have templates in react

I have built an element which is kind of template. (e.g, thumbnail container with image at the top and something in the footer with dynamic content between them)
the dynamic content can be different types of DOM elements, based on the state.
I did it with adding logic in the render method which "injects" the dynamic part.
Does this make sense (having logic in the render method which returns different react components)?
Is there a better way for templating? (i'm not looking for projects that add this capability, wanted to know if there's a "react way" to do so.
Thanks!
edit: here's the code I was referring to (coffeescript):
internalContent: ->
switch #props.title
when "title1" then SomeReactFactory(props)
when "title2" then SomeOtherReactFactory(props)
render ->
...
DOM.div
className: 'panel'
#internalContent()
the internalContent() method is dynamically adding some React Component based on the prop
This is the React way.. And you should make use of it to target your specific domain.
For example a Button in React could be written like this:
const MyButton = ({ text, type = "normal", color = "blue", onClick }) => {
return (
<button
onClick={onClick}
style={{backgroundColor: color }}
className={"my-button my-button--type" + type}>
{text}
</button>);
};
Or a layout component:
const MyLayout = ({side, nav, main}) => {
return (
<div className="container">
<nav>{nave}</nav>
<aside>{side}</aside>
<div className="main">{main}</div>
</div>
)
}
Now you can composite it for example like this:
class App extends Component {
...
render() {
<MyLayout
nav={<MyNav/>}
side={<MySideBar items={...} />}
main={<MyButton onClick={this.onClick} text="Main Button"}
/>
}
}
Dont try to pack everything in a big Component which will do everything, the trick in React is to make small reusable Components and composite them.
You could also create a bunch of components which you can use across many projects.

Resources