I want to wrap up my ant-design components with styled-components, I know that this is possible (https://gist.github.com/samuelcastro/0ff7db4fd54ce2b80cd1c34a85b40c08) however I
I have found this ancient question and try to solve in an easy way:
import React from 'react';
import styled from 'styled-components';
import { Card } from 'antd';
import { CardProps } from 'antd/lib/card';
export const NewCard: React.FunctionComponent<CardProps> = styled(Card)`
margin-bottom: 24px;
`;
without render props :D
if you just need wrap a component as function component, that's all right. But you will lose the properties of class component such as Card.Meta.
There is a workaround:
import React from 'react';
import styled from 'styled-components';
import { Card } from 'antd';
import { CardProps } from 'antd/lib/card';
export const NewCard: typeof Card = styled(Card)<CardProps>`
margin-bottom: 24px;
` as any;
Everything (maybe... XD) works as original Antd Component ;)
my code is here. and it is work.
import React from 'react';
import { Button as AntButton } from 'antd';
import { ButtonProps } from 'antd/lib/button/button';
import styled from 'styled-components';
const Container = styled.div`
font-size: 20px;
`;
const Button: React.FunctionComponent<ButtonProps> = styled(AntButton)`
margin-top: 24px;
margin-left: 30px;
`;
export default function Home() {
return (
<Container>
Hello World
<Button type="primary">test</Button>
</Container>
);
}
The above solutions didn't work for me, this solved it though.
const Button = styled((props: NativeButtonProps) => <AntButton {...props} />)``;
index.tsx (Button Component)
import { Button as AntButton } from 'antd'
import { NativeButtonProps } from 'antd/lib/button/button'
import 'antd/lib/button/style/css'
import * as React from 'react'
import styledComponents from 'styled-components'
import * as colours from '../colours'
const getColour = (props: any) =>
props.status === 'green'
? colours.STATUS_GREEN
: props.status === 'red'
? colours.STATUS_RED
: props.type === 'primary'
? colours.PRIMARY
: colours.WHITE
export interface ButtonProps extends NativeButtonProps {
status?: string
}
export default styledComponents((props: ButtonProps) => <AntButton {...props} />)`
&:focus,
&:hover
& {
background-color: ${getColour};
border-color: ${getColour};
}
`
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.5.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.5.2/umd/react-dom.production.min.js"></script>
import React from 'react'
import Button, { ButtonProps } from './index'
interface ButtonAsyncSingleSuccessProps extends ButtonProps {
clickFunc: any, // (...args: any[]) => Promise<any>
labelLoading: string,
labelReady: string,
labelSuccess: string,
}
interface ButtonAsyncSingleSuccessState {
label: string,
loading: boolean,
status: string
}
export default class ButtonAsyncSingleSuccess extends React.Component<
ButtonAsyncSingleSuccessProps,
ButtonAsyncSingleSuccessState
> {
constructor (props: any) {
super(props)
this.state = {
label: props.labelReady,
loading: false,
status: ''
}
}
public clickHandler (event: any) {
const { labelLoading, labelReady, labelSuccess, clickFunc } = this.props
this.setState({
label: labelLoading,
loading: true,
status: ''
})
clickFunc(event)
.then(() => {
this.setState({
label: labelSuccess,
loading: false,
status: 'green'
})
})
.catch(() => {
this.setState({
label: labelReady,
loading: false,
status: 'red'
})
})
}
public render () {
const {
labelLoading,
labelReady,
labelSuccess,
clickFunc,
...props
} = this.props
const { label, loading, status } = this.state
if (status === 'red') {
setTimeout(() => this.setState({ status: '' }), 1000) // flash red
}
return (
<Button
{...props}
loading={loading}
status={status}
onClick={(e) => this.clickHandler(e)}
>
{label}
</Button>
)
}
}
The root of the problem seems to be that styled-components expects the inner component (AntButton) to accept all the props in the specified interface (IButtonProps), but AntButton does not accept customProp. To fix this, follow the last example in this section of the documentation and use a stateless function component to remove customProp before calling AntButton.
export const Button = styledComponents<IButtonProps>(
({ customProp, ...rest }) => <AntButton {...rest} />)`
// any custom style here
`;