I'm building a React app using Dart SASS. Things are generally going well and I particularly appreciate how the styles for each component are isolated to that component - ie. ComponentName.module.scss
But I've just built a new Modal component that is merely a wrapper for the popular react-modal component installable via npm.
What I'd ideally like to be able to do is pass in a className string that is merely a reference to an SCSS class in my parent component and have it override the default styles in Modal.jsx.
Example: I have a component called SignIn.jsx. It has a Forgot Password link that, when clicked, displays a modal to allow the user to enter their email address. What would be ideal is to be able to define an SCSS class in SignIn.module.scss and then pass into Modal.jsx this class when I call <Modal className={...myCustomClass} ... />
I actually have been able to accomplish this with a global SCSS class definition but haven't been able to figure out how to do so as I described above.
Is what I'm seeking to do possible? Are there any articles on how to do this?
While I appreciate #iamhuynq trying to help, there's much more that can be said, which will hopefully help others in the future.
To summarize the issue, imagine you're using TypeScript with React and have a parent component with a companion SCSS file:
ParentComponent.tsx
ParentComponent.module.scss
In this parent component you want to utilize a child component consisting of these files:
ChildComponent.tsx
ChildComponent.module.scss
You want the ability to inject a custom style into the ChildComponent. More precisely, you have an SCSS class defined in ParentComponent.module.scss that you want to be utilized by ChildComponent.tsx. To accomplish this, do the following in the child component:
import * as React from 'react';
import cx from 'classnames';
import styles from './ChildComponent.module.scss';
interface IChildComponent {
className?: any; // Note: I tried more specific types but none of them worked
children: React.ReactNode;
}
const ChildComponent = ({ className, children }: IChildComponent) => {
return (
// Your version of this content will necessarily be different
<div className={cx(styles.childComponentMain, className)}>
// More content here
</div>
);
};
export default ChildComponent;
With this approach I am able to inject a style defined in ParentComponent.module.scss into ChildComponent.tsx and have it amend to those styles already defined in ChildComponent.module.scss.
Related
I have React app (functional components) and I use Material-UI. I have custom theme also and I use theme provider. I have created custom component (e.g. MySuperContainer) and I need to connect it with particular styles (object) in my theme
export const myTheme = { …, components: { MySuperContainer: { padding: “10px“, … } … }
I don’t want to import it to component to sx via useTheme hook. I don’t want to use styled components nor anything similar. Finally I want to write <MySuperContainer /> and it should already find its own custom styles in myTheme.
How can I achieve this? Is there any example or tutorial how to do this? I cannot find anything.
I'm currently working on a personal project to build a design system in React using Typescript. I'd like to take advantage of some of the types pre-defined within the React project for HTML elements, especially form controls such as ComponentPropsWithoutRef<'input'>. I'm currently working on a Checkbox component which hides the standard HTML input checkbox but uses its checked state to style some custom HTML within its label.
I'm using Styled Components to provide styles but have been struggling with how to structure my interface/interfaces to typecheck this component.
I have created a Code Sandbox to show the component code, but Checkbox.tsx looks like so:
import { ComponentPropsWithoutRef } from 'react';
import * as S from './checkbox.styles';
export interface CheckboxInputProps extends ComponentPropsWithoutRef<'input'> {
disabled?: boolean;
}
export interface CheckboxProps extends CheckboxInputProps {
label: string;
}
export const Checkbox = ({ label, disabled, ...props }: CheckboxProps) => {
return (
<S.Checkbox>
<S.CheckboxInput disabled={disabled} {...props} />
<S.CheckboxLabel>
<S.CheckboxBackground>
<S.CheckboxIndicator>
<S.CheckboxIcon />
</S.CheckboxIndicator>
</S.CheckboxBackground>
<S.CheckboxText>{label}</S.CheckboxText>
</S.CheckboxLabel>
</S.Checkbox>
);
};
I'd like some advice on how/if I can create a single interface for this component which also uses ComponentPropsWithoutRef or whether I need to create separate interfaces for each and every sub-component. Appreciate the question is a bit vague but I'd just like some guidance on how to structure this.
Could you please help with the following?
We use Ionic with React in a team having 2 distinct projects.
We need to style these Ionic components a little differently.
I need to share these a-little-differently-styled Ionic components with another team for code re-use.
I would like to showcase these styled Ionic components using Storybook to the UX team and say "this is how a button looks like"
To begin with I just added the styling in a css file and imported that file in the root React page.
But it would be nice to just encapsulate component + styling in a re-usable isolated component that other people can re-use without having to import custom css files.
I am thinking of :
import { IonButton } from "#ionic/react";
import styled from "styled-components";
const StyledIonButton = styled(IonButton)`
// some custom css styling here
`;
const MyIonButton = () => <StyledIonButton {...props} />;
export default MyIonButton;
Now, I can track/export above component using e.g Bit.dev and have the other team consume it via npm-install.
However, I dislike :
a) changing the name from "IonButton" to "MyIonButton"
b) having to wrap each and every Ionic component as shown above
I would like myself and the other team to just use Ionic components in the standard way e.g
import { IonButton } from "#ionic/react";
...
<IonButton>Close</IonButton>
BUT having these base building-blocks/components styled in a certain way.
Could you please describe to me the right approach please? Many thanks for your time
I am trying to use the library 'react-images' in my reactjs project. I am receiving the error "Unexpected token" in the react-images\src\components\Footer.js file. Also, on the same line i have the error "'import ... =' can only be used in a .ts file.".
import type { PropsWithStyles, ViewType } from '../types';
Also, I am receiving the error "'type aliases' can only be used in a .ts file." in many of the component files in 'react-images' library. Why is this? Thanks.
import React, { Component, Fragment } from 'react';
import Carousel, { Modal, ModalGateway, FooterCaption } from 'react-images';
You misunderstand how this library is designed. If you look at the documentation, FooterCaption is listed under Component API. That means FooterCaption is part of the API for the Carousel component meaning that this is designed with the Slots Pattern.
If you look at the example code above it, it shows you how this works.
<Carousel components={{ Header: CustomHeader }} />
The Carousel component has a prop called components which takes an object. This object is expected to have keys that are one of the various replaceable components listed under Component API. The value is expected to be a something that React can render; typically a component. This example is replacing the Header with a custom header component called CustomHeader.
If you don't override the component, then Carousel will render something by default as described in the documentation for each component under Component API.
If you would like to override the default FooterCaption, then you will do something like this:
<Carousel components={{ FooterCaption: MyCustomFooterCaption }} />
Where MyCustomFooterCaption is a component you've defined elsewhere. The props it will receive from the Carousel component can be found in the source code.
To summarize:
You don't need to import FooterCaption.
If you plan on overriding the default FooterCaption, then create your own component and pass it in as shown in example.
The same goes for everything listed under Component API.
New to material-ui here and trying to work out the best way of using the css in js. I can see from the demo code that inserting styles as classes is pretty easy using 'withStyles' but if I do the following I'd need to re-create the 'grow' and 'defaultPadding' styles in every component.
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
import Paper from '#material-ui/core/Paper';
function Dashboard(props) {
const { classes } = props;
return (
<Paper className={classes.defaultPadding}>
Hello
</Paper>
);
}
const styles = theme => ({
grow: {
flexGrow: 1
},
defaultPadding: {
padding: theme.spacing.unit * 3 + 'px'
}
});
export default withStyles(styles)(Dashboard);
I could easily create a factory method in an external file that returns a massive object containing all my default styles but I'd need to be able to pass the existing theme to it if I want to use things like 'theme.spacing.unit'.
So, is there a way to create a bunch of re-usable styles of my own, using theme values, then import them into any component?
Bonus question: Is it possible to create nested objects so I can do things like this? ...
className={classes.layout.header}
I think creating an external factory method would work or you could also create a ThemeProvider to pass your theme to every component that needs the same styles.
In the Codesandbox I created two Dashboard components. One with styled-components just to show how a ThemeProvider works and the other component is using withStyles.
For withStyles factory I called it sharedStyles in the demo and with this you can create a new style object inside your components by calling it and spreading it to a new style (just if you need to add more styles).
Nesting inside styles seems not supported. You could create keys like layout.heading or flatten the object before using it (see code in the demo). Both not perfect and I wouldn't use it.
I'm personally prefering styled-components but you don't need to switch to it. You can look at the source code how they implemented it and use it in your code to pass the theme to your component.
The ThemeProvider is using React Context-Api.