Reputation: 998
I've recently started to use Styled Components together with React, and I am unsure if I am handling a particular case right which keeps reoccuring.
Let's say I have a very simple component like a Label
which needs only a very styles and some given content. I would now handle this is follows:
import React from "react";
import styled from "styled-components";
export type Props = {...};
export const Impl = styled.span`
display: inline-block;
padding: 0 4px;
...
`;
export const Label: React.FC<Props> = ({ text }) => <Impl>{ text }</Impl>;
I find it circumstantial to define base components like Impl
first, only for the styles, and then then another component which takes the props and uses that styled component.
Is there a shorter way to do both in only one component? I was hoping for something like ...
export const Label = styled.span<Props>=`
...styles...
`({ label }) = { label };
... but that doesn't seem to work.
Upvotes: 1
Views: 264
Reputation: 13652
One way you could do this is to use the styled
factory and just inline your component - though this kind of inverses the relation in the sense that you're not using a styled.span
, but rather just styling your own component via the className
generated by styled-components
. This also means that you need to include className?
in your props' type, or use an utility type to add it in.
type Props = {
text: string;
className?: string;
};
const Label = styled(({ text, className }: Props) => (
<span className={className}>{text}</span>
))`
display: inline-block;
padding: 0 4px;
color: red;
`;
export default function App() {
return (
<>
<Label text="foo" />
</>
);
}
You might also prefer this:
const Label = styled(({ text, ...props }: Props) => (
<span {...props}>{text}</span>
))`
display: inline-block;
padding: 0 4px;
color: red;
`;
or with a utility type:
type SCP<T> = T & { className?: string };
type Props = {
text: string;
};
const Label = styled(({ text, ...props }: SCP<Props>) => (
<span {...props}>{text}</span>
))`
display: inline-block;
padding: 0 4px;
color: red;
`;
Upvotes: 3