Render an SVG icon inside a button? - javascript

I have an SVG in a folder icon.svg, I'm trying to render it in a button along with text. Specifically, it's the Google icon and i'm trying to render it next to some text that says "SIGN IN WITH GOOGLE"
I'm importing the SVG as is and trying to pass it next to the button but, the file path is rendering instead:
function App() {
return (
<div className="App">
<button>{SVG}SIGN IN WITH GOOGLE</button>
</div>
);
}
That renders a button that says /static/media/Icon.a1611096.svgSIGN IN WITH GOOGLE
How is one supposed to render the icon inside the button properly?
EDIT: I've been messing with the icon and the button and got close:
https://codesandbox.io/s/10k7rr3rp4

First you have to save the icon in assets folder. Then import it into the component which you want to use in
import {ReactComponent as Logo} from '../../assets/google.svg';
Now you can use it like a component
<button>
<Logo className='logo' /> Sign in with Google
</button>

You can use the require function as follows:
<button><img src={require(SVG)} alt="test" />SIGN IN WITH GOOGLE</button>

another solution could be to use styled-components with ::before pseudo element.
i just moved the images folder to the public folder.
live example

Related

ReactJS: How to properly link to a download file?

I have a manual.pdf file that I need to attach to my document.
The conventional wisdom would be to link the file source in the href attribute of an <a> tag:
<a href="../assets/img/manual.pdf" download>Manual</a>
React seems to not like it, I assume. Failed-No file error is given upon click on the <a> tag.
When it is an <img> tag with a local file, I would import the source import logo from '../assets/img/logo.svg';, then pass it to the src attribute like so <img src={logo} alt="brand logo" />.
I tried it - no use.
giving the absolute path - no use.
giving a relative path - no use.
It seems that it does not work the same way with <a> tags.
How do I properly link local files in a React Project?
P.S. I have heard of React routes, but I am not linking to any page, it is for downloading a file.
Try this
<Link to="/files/manual.pdf" target="_blank" download>Download</Link>
Where /files/manual.pdf is inside your public folder
Try this one https://www.npmjs.com/package/file-saver (FileSaver.js)
//function for saving file
const saveManual = () => {
fileSaver.saveAs(
process.env.REACT_APP_CLIENT_URL + "../assets/img/manual.pdf",
"manual.pdf"
);
};
//button for calling
<button onClick={saveManual}>
Manual
</button>

Font Awesome icons not showing up using Bulma in Gatsby

I am building a website using Gatsby and Bulma. In my Nav.js file, where I create a general format for the buttons at the top of the website, I have a few buttons using Bulma to which I would like to add icons inside. I went off the documentation for adding Bulma buttons with Font Awesome Icons: https://bulma.io/documentation/elements/button/. My code is exactly the same, other that the fact that I have my buttons wrapped in an <a> tag to link to other pages in my website. I have the included <script> file listed in documentation to have Font Awesome Icons available, and my code looks as such:
const Nav = () => {
return (
<div style={{ margin: `3rem auto`, maxWidth: 650, padding: `0 1rem` }}>
<nav>
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
<p class="buttons is-outlined is-centered">
<a href="/"><button class="button is-outlined"> <span class="icon">
<i class="fas fa-home"></i>
</span>
<span>Home</span>
</button></a>
<button class="button is-outlined">Projects</button>
<button class="button is-outlined">Experience</button>
</p>
</nav>
</div>
)
}
I'm not sure if I have the script located in the correct part of the file, and I've only tried to put an icon for my Home button which looks like this:
The gap to the left of the "Home" is where I'm guessing the icon should be. I would appreciate any help as to why the icon is not showing up or is showing up blank. Thank you!
I ran into this issue myself so posting here for anyone that is looking for the answer. There are a few ways to make it work, including using the icons as components with a library such as react-fontawesome. However if you're using Bulma then chances are that you specifically don't want to do that, instead you want to use the class names.
So first install the package:
npm i #fortawesome/fontawesome-free
Then in your index.js / app.js / any styling wrapper component you have:
import '#fortawesome/fontawesome-free/css/all.min.css'
Here is a Typescript example I have in front of me. This is a wrapper component that imports all my global styles for nested child components to use:
import React from 'react';
import 'bulma/css/bulma.css';
import '#fortawesome/fontawesome-free/css/all.min.css';
import NavMenu from '../nav-menu';
import Footer from '../footer';
import './layout.css';
const Layout: React.FC<{ light: boolean }> = ({ light, children }) => {
return (
<div className="layout-wrapper">
<NavMenu light={light} />
{children}
<Footer light={light} />
</div>
);
};
export default Layout;
With the help of a friend, what solved the issue was putting the <script> tag in the public/index.html file of the project, and then making an exact copy and naming it index.html and putting it in the static folder in the project. This way, each time a Gatsby server is ran, it will create a copy of the index.html file in the public repository with the Font Awesome Icon script included.

How to create a conditional rendering of Gatsby's Link component and <a> tag for links?

From Gatsby's official docs regarding Gatsby's Link component, it states that the Link component is used only for internal links, whereas for external links, one has to use the tag.
I'm building a Button component that has inbuilt props for links. The problem is right now I have to create 2 separate Button components for internal and external links due to the limitation.
My goal is to use one freeLink component that can be used as both internal and external links
I've tried creating a subcomponent (Button) for the button, but I'm unsure of the parent component (freeLink) which requires conditional rendering. The subcomponent is as of follows:
const Button = props => (
<button className={props.btnType}>
<span>{props.text}</span>
</button>
)
This is the visual logic to what I want to achieve:
For Internal links
<freeLink intLink="/about" btnType="btn-cta" text="Read about us">
</freeLink>
...which will render...
<Link to="/about">
<button className="btn-cta">
<span>Read about us</span>
</button>
</Link>
It is relatively similar for external links
<freeLink extLink="https://google.com" btnType="btn-cta" text="Visit Our Partner">
</freeLink>
...which will render...
<a href="https://google.com">
<button className="btn-cta">
<span>Visit Our Partner</span>
</button>
</a>
I'm quite new to Javascript, Gatsby and React so I'm unsure to how to apply a conditional rendering based on props applied.
Any advice, suggestion, or direction to how to code up the freeLink component is greatly appreciated.
P.S: I've seen Conditionally Use Gatsby Link in React Compoment but the chosen answer is too complicated for me to understand, and I don't have enough points to comment to ask for further elaboration.
You could try something simple like this:
const MyLink = (href, text, ...props) => {
if (href.startsWith("http") {
return <a href={href} {...props}>{text}</a>
} else {
return <Link href={href} {...props}>{text}</Link>
}
}
Your component could return different stuff based on weather you pass it a to or a href prop:
import { Link } from "gatsby"
const freeLink = props => {
if (props.to) return <Link {...props} />
return <a {...props} />
}`

Render one component several times in different html pages with different text

I'm new to react and I'm trying to render one component in different html files (because I'm working in an existing project), each of them with different text.
I'm thinking of something like this:
class ctaSection extends React.Component{
render(){
return(
<div className="cta-section">
<div className="md:w-9c">
<h5 className="uppercase">{this.props.h5}</h5>
<h3>{this.props.h3}</h3>
</div>
<div className="cta-button">
<a href="#">
<button className="w-full">{this.props.button}</button>
</a>
</div>
</div>
);
}
}
export default ctaSection;
Then, in my index.js, I'm rendering like this, passing the props:
let ctaPage1 = document.getElementById('cta-section-page-1');
let ctaPage2 = document.getElementById('cta-section-page-2');
ReactDOM.render(<CtaSection h3='my text for page 1' h5='my h5 for page 1' button='hello'/>, ctaPage1);
ReactDOM.render(<CtaSection h3='text for page 2' h5='something' button='click me'/>, ctaPage2);
I'm not sure if this is the best and simpler way to do this, because I'm calling ReactDOM.render twice for same component, and I got this error:
Uncaught Invariant Violation: Target container is not a DOM element.
This works fine if I render the component once, but not for multiple instances.
What is the best way to do it?
I've thought about this more, and I'm not experienced with adding React to existing websites, but here's what I'd suggest:
I would have 1 JS file per HTML page that imports CtaSection, each of those files would look like such:
// page1.js
import CtaSection from '../CtaSection'; // or wherever it is
let ctaPage = document.getElementById('cta-section-page');
ReactDOM.render(<CtaSection h3='my text for page 1' h5='my h5 for page 1' button='hello'/>, ctaPage);
You would just need to make sure each html page uses the corresponding JS file.
// page1.html
<body>
<div id="cta-section-page"></div>
<script src="page1.js"></script>
</body>
Repeat for each page.

Can you have more than one SVG on a page? (using svg-react-loader)

I'm trying to import and display multiple SVGs in the same component, but it's actually just showing the first one duplicated every time, instead of two individual SVGs. Here is my code:
import React, { Component } from 'react';
import Account from '-!svg-react-loader!./svg/Account.svg';
import Alert from '-!svg-react-loader!./svg/Alert.svg';
<div className="col-lg-1">
<Account className="icon" />
</div>
<div className="col-lg-1">
<Alert className="icon" />
</div>
Can we only have one instance of an SVG per page?
For anyone reading this. It appears Sketch was saving the SVGs out with the same id - "#path-1", which was breaking when there were multiple on the page. So, the answer is they need a unique ID.

Categories

Resources