Use styled-components to supply a css class

Viewed 12703

I have a 3rd party lib which needs a calendarClassName to modify its style which expect a traditional class name of a CSS class. Can I use styled components to accomplish this?

I tried css function, but it won't work, the result is the array of style rather than a CSS class entity.

Just want to do something like this:

const myStyle = css`color: black`;

<DatePicker calendarClassName={myStyle}> // won't work

Tried attrs without any luck, the className has not been passed down to DatePicker.

const calendarClassName = "calendar";
export const MyDatePicker = styled(DatePicker).attrs({
  calendarClassName,
})`
  .${calendarClassName} {
    border-radius: 0px;
    box-shadow: 2px 0px 2.5px #D6D6D6;
    border: 1px solid ${color.pacific};
  }
`;

I know I can use CSS directly, but I just want to know how to use styled-components to do the job.

Thanks :)

5 Answers

styled-components does not provide a way to generate class names without them being attached to a component. However, we can use this feature to our advantage to achieve what you're looking for.

Simple className rename

If you need to use a class name generated by styled-components, given that we know that it will be attached to the className prop, you can create an intermediate component to manipulate it as needed.

const ClassNameToCalendarClassName = ({ className, ...rest }) => (
  <Calendar calendarClassName={className} {...rest} />
);

const SConvertClassNameToCalendarClassName = styled(ClassNameToCalendarClassName)`
  color: blue;
`;

Multiple className renames

For cases where you need multiple classNames at a given point in the code, you'll need as many intermediate components as classes you need:

const ClassNameToC3 = ({ c1, c2, className, ...rest }) => (
  // if you pass {...rest}, c1 and c2 are redundant, but included for clarity
  <Calendar c1={c1} c2={c2} c3={className} {...rest} />
);

const ClassNameToC2 = ({ className, ...rest }) => (
  <ClassNameToC3 c2={className} {...rest} />
);

const ClassNameToC1 = ({ className, ...rest }) => (
  <ClassNameToC2 c1={className} {...rest} />
);

and the matching styled components,

// Styled components
const SClassNameToC3 = styled(ClassNameToC3)`...`;
const SClassNameToC2 = styled(ClassNameToC2)`...`;
const SClassNameToC1 = styled(ClassNameToC1)`...`;

You can inject CSS classes using the following code snippet. In below snippet, in class-1 the colour property would be overridden. This would work if class-1 is already existing class being applied or else you will have to pass className='class-1' to DatePicker.

import styled, { css } from 'styled-components';
export const StyledDatePicker = styled(DatePicker)`
.class-1 {
 color: black;
}
`;

If the DatePicker receives additional className then appends it to the class list of itself, then it does work to wrapper it using styled to apply extra styles to it. I see you've tried all the possible methods but none of them work. It probably indicates that third party lib doesn't handle the additional className so that it's impossible for you to combine SC with the lib together.

I think this approach could resolve your problem if calendarClassName is applied for a nested element.

const StyledDatePicker = styled(DatePicker)`
  .calendarClassName {
    border-radius: 0px;
    box-shadow: 2px 0px 2.5px #D6D6D6;
    border: 1px solid ${color.pacific};
  }
`;

<StyledDatePicker calendarClassName="calendarClassName">

try this:

const Wrapper = styled.div`
  & .calendarClassName{
    // your style goes here
  }
`;

<Wrapper>
   <DatePicker />
</Wrapper>

or

const DtPicker = styled(DatePicker)`
  & .calendarClassName{
    // your style goes here
  }
`;

<DtPicker />

Must use 'space' between '&' and '.calendarClassName'

Related