Unable to create custom tailwind component library - reactjs

I try to create my own react component library based on tailwind CSS.
I start with a simple button component
import * as React from 'react'
interface Props {
text: string
onClick?(): any
}
export const Button = ({ text, onClick }: Props) => {
return (
<button onClick={onClick} className='bg-primary-500 rounded-md'>
{text}
</button>
)
}
I push it on npm : https://www.npmjs.com/package/tailwind-lib-quentin
Then I create a simple React app that use this package
import "tailwind-lib-quentin/dist/index.css";
import { Button } from "tailwind-lib-quentin";
function App() {
return (
<div className="App">
<Button text="Test" onClick={() => console.log("ok")} />
<div className="w-full h-40 bg-primary-500">Bonjour</div>
</div>
);
}
export default App;
as you can see I import the css of my package that extend tailwind but my components are not styled at all.
The button work but I can't see any style on it and I don't get any errors.
Here is reproductible example on Codesandbox : https://codesandbox.io/s/frosty-sea-1y879
here is the package repository : https://github.com/quentin-bardenet/tailwind-lib-quentin

Related

semantic-ui-react : modify component itself without overload with new method at onClick event

I've set an example here : https://codesandbox.io/s/lucid-morning-bd8nn0
I've trying using "this." but I can't found method to do this.
I don't want to extend Label component and implement a homemaid method to do this.
I'm expecting to found a solution using native REACT / semantic-ui method to do this.
Below my code and I'd like to update Label component itself at onClick event.
import "./styles.css";
import { Label } from "semantic-ui-react";
export default function App() {
return (
<div className="App">
<Label
as="a"
color="green"
tag
onClick={(e) => {
// I'd like to update the text of this LABEL
// any idea to do this ?
}}
>
Click here to change text
</Label>
</div>
);
}
Any idea ?
Thanks for your help.
You can use local state to accomplish that:
import "./styles.css";
import { Label } from "semantic-ui-react";
import { useState } from "react";
export default function App() {
const [labelText, setLabelText] = useState("Click here to change text");
return (
<div className="App">
<Label
value="XXXXX"
as="a"
color="green"
tag
onClick={(e) => {
setLabelText("updated text");
}}
>
{labelText}
</Label>
</div>
);
}

Correct use of ReactToPrint?

The problem is that the button that is supposed to give the option to print is not working anymore.
the error in the console says:
To print a functional component ensure it is wrapped with `React.forwardRef`, and ensure the forwarded ref is used. See the README for an example: https://github.com/gregnb/react-to-print#examples
I Have already seen some solutions specifically talking about the same problem but I have not been able to make it work.
any suggestion?
this is the library i'm using: ReactToPrint npm
React To print
import { useRef } from "react";
import { useReactToPrint } from "react-to-print";
import Resume from "./Pdf/Pdf";
const Example = () => {
const componentRef = useRef();
const handlePrint = useReactToPrint({
content: () => componentRef.current
});
return (
<div >
<button onClick={handlePrint}> ------> NOT WORKING!
Descargar Pdf
</button>
<Resume ref={componentRef} /> ------> COMPONENT TO PRINT
</div>
);
};
export default Example;
Component to be printed
import React from "react";
import styled from 'styled-components';
import PdfSection from './PdfSection';
import AlienLevel from './AlienLevel';
import {connect } from 'react-redux';
class Resume extends React.Component {
renderList = () => {
return this.props.posts.diagnose.map((post) => {
return (
<PdfSection
key={post.id}
id={post.id}
divider={"/images/pdf/divider.png"}
img={"/images/alienRandom.png"}
title={post.title}
// data={post.data}
text={post.text0}
subtext={post.subtext0}
/>
);
});
};
render(){
return (
<div>
<Container>
<Page>
<Portada>
<img id="portada" src="/images/pdf/PortadaPdf.png" />
</Portada>
</Page>
<Page>
<AlienLevel
result= "{props.diagn}{"
character={"/images/pdf/alienMedio.png"}
fileName={"responseBody[4].data"}
level={"/images/pdf/level6.png"}
correct={"/images/pdf/correct.png"}
medium={"/images/pdf/medium.png"}
incorrect={"/images/pdf/incorrect.png"}
text='"Necesitas mejorar tus prácticas intergalácticas de CV, pero ya eres nivel medio!"'
/>
<div>{this.renderList()}</div>
</Page>
</Container>
</div>
);
};
}
const mapStateToProps = (state) => {
return { posts: state.posts };
};
export default connect(mapStateToProps)( Resume);
thanks in advance!
The problem is with connect() function of react-redux.
You wrapped your component in connect and connect by default does not forward ref. Which means, the ref you are passing here <Resume ref={componentRef} /> does not reach to your component.
You need to pass options { forwardRef: true } in fourth parameter of connect function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?).
Just change this code export default connect(mapStateToProps)(Resume); in Resume component to this
export default connect(mapStateToProps, null, null, { forwardRef: true })(Resume);
For anyone that is struggling with the same error, it seems that they found the proper way to resolve this, I actually resolved it by following the Codesandbox I found in the Github issues here si the link. hope is useful! -->
LINK TO GITHUB SPECIFIC ISSUE (SOLVED!!)
I had the same issue and I am happy to share my findings as soon as now.
The component has to be rendered somewhere using ref.
I added it to my page as hidden using React Material UI's Backdrop. Or u can hide it using hooks like examples below.
Using backdrop and only calling it when I need to preview the print. 👇👇
<Backdrop sx={{ color: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1 }}
open={openBD}>
<ComponentToPrint ref={componentRef} />
</Backdrop>
Using Hooks plus display styling to only display it when needed. 👇👇
const [isReady, setIsReady] = useState("none");
<Paper style={{ display: isReady }} >
<ComponentToPrint ref={componentRef} />
</Paper>
<Button
variant="contained"
endIcon={<BackupTableRoundedIcon />}
onClick={() => setIsReady("")}
>
Start Printing
</Button>
Note: I used MUI components, if u decide to copy paste, then change Button to html <button and paper to <div. Hope this helps.

Why inline styling doesnt work in react on components?

Why inline styling doesnt work in react on components?I dont understand why this is not working.I know is possible to make it different ways.(with css files for example).Im just corius.The intellisense does not help by inline styling either.Its strange..
import "./App.css";
import Button from "./components/Button";
function App() {
return (
<div className="App" >
<Button style={{fontSize:"50px"}} />
</div>
);
}
export default App;
//this is from Button components
import React from "react";
const Button = () => {
return (
<div>
<button>
Change
</button>
</div>
);
};
export default Button;
You need to pass the style property to the Button component:
const Button = ({style}) => {
return (
<div>
<button style={style}>
Change
</button>
</div>
);
};

Im building a React App that requires a pdf to download, in the event the (materialUI) download button is clicked, how can I add that functionality?

the profile component contains the following code:
<div className="button_container" style={{display:'flex'}}>
<DownloadButton text={'PDF'} icon={<GetAppIcon />} />
</div>
the button component contains the following code:
import React from 'react'
import { Button } from "#material-ui/core";
import './Button.css'
const DownloadButton = ({text, icon}) => {
return (
<Button onClick={() => { }} className="custom_btn" endIcon={icon ?
(<div className="btn_icon_container" >{icon}</div>) : null}>
<span className="btn_textw">{text}</span>
</Button>
)
}
export default CustomButton
**I've added an onClick event but am having difficulty figuring the simplest way to trigger the file to download, once the button is clicked **
Any comments are appreciated
Turn your button into a link and provide the path to your pdf file
import React from 'react'
import { Button } from "#material-ui/core";
import './Button.css'
const DownloadButton = ({text, icon}) => {
return (
<Button component="a" href="PATH_TO_YOUR_PDF_FILE" className="custom_btn" endIcon={icon ?
(<div className="btn_icon_container" >{icon}</div>) : null}>
<span className="btn_textw">{text}</span>
</Button>
)
}
export default CustomButton
The simplest way to achieve this is to use an HTML anchor and style it like a button.
Download PDF
With material core buttons you need to add the href prop and it will use an anchor tag instead of a button tag.
<Button href="/path/to/file.pdf">Download PDF</Button>
Your download button would look like
const DownloadButton = ({text, icon}) => {
const endIcon = icon ? (<div className="btn_icon_container" >{icon}</div>) : null;
return (
<Button href="file.pdf" className="custom_btn" endIcon={endIcon}>
<span className="btn_textw">{text}</span>
</Button>
)
}

How to reuse a Custom Material-ui button inside a react-app?

I'm developing my first React app. I've imported a Material-ui button and I've customized it.
Now I want to reuse this custom button in several components of my app. I want a different text for each time I use this custom button.
Where do I need to write this specific text for each button?
My button is visible when I import it in other components, but I can't see the text I wrote inside the button component. The button stays empty.
My custom button component : MyButton:
import React from "react";
import Button from "#material-ui/core/Button";
import { withStyles } from "#material-ui/core/styles";
const styles = () => ({
button: {
margin: 50,
padding: 10,
width: 180,
fontSize: 20
}
});
function MyButton(props) {
const { classes } = props;
return (
<Button variant="contained" color="primary" className={classes.button}>
<b> </b>
</Button>
);
}
export default withStyles(styles)(MyButton);
The other component where I import MyButton component : Home :
import React from "react";
import "../App.css";
import MyButton from "./Button";
function Header() {
return (
<header className="Header">
{/* background image in css file */}
<h1>Welcome </h1>
<h3> description...</h3>
<MyButton>Play now</MyButton>
</header>
);
}
export default Header;
I expect the button to show "Play now" (expected output) but for now it stays empty (actual output).
Also, I've found another solution that offers the possibility to write directly the text inside each button (children of MyButton), and customize it if needed.
Pass "children" keyword as "props" to MyButton component :
function MyButton(props) {
const { classes, children } = props;
return (
<Button variant="contained" color="primary" className={classes.button}>
<b>{children}</b>
</Button>
);
}
Then write the text of your button inside the button as you will do in html :
<MyButton> Play now </MyButton>
You will get the most flexibility from your custom Button if you pass all of the props along to the wrapped Button. This will automatically take care of children and classes so long as you use class keys in your styles object that match the CSS classes supported for the wrapped component.
import React from "react";
import Button from "#material-ui/core/Button";
import { withStyles } from "#material-ui/core/styles";
const styles = () => ({
root: {
margin: 50,
padding: 10,
width: 180,
fontSize: 20,
fontWeight: "bold"
}
});
function CustomButton(props) {
return <Button variant="contained" color="primary" {...props} />;
}
export default withStyles(styles)(CustomButton);
Notice in the sandbox example, that this allows you to still leverage other Button features like disabled, specify additional styles, or override some properties specified in CustomButton.
If you have a scenario where you need to handle children explicitly (in my example above I used fontWeight CSS instead of the <b> tag), you can use the following syntax to still pass all the props through to the wrapped component:
function CustomButton({children, ...other}) {
return <Button variant="contained" color="primary" {...other}><b>{children}</b></Button>;
}
Pass text of button as props to your button component
<MyButton text="Play now"></MyButton>
Then inside MyButton component you can get it like
function MyButton(props) {
const { classes,text } = props;
return (
<Button variant="contained" color="primary" className={classes.button}>
<b> {text} </b>
</Button>
);
}

Resources