-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Converts Card to typescript #1160
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,98 @@ | ||||||||||||
import React, { | ||||||||||||
createElement, | ||||||||||||
type DetailedHTMLProps, | ||||||||||||
type HTMLAttributes, | ||||||||||||
type ReactNode, | ||||||||||||
} from 'react'; | ||||||||||||
import classNames from 'classnames'; | ||||||||||||
|
||||||||||||
import { LoadingSkeleton } from 'src/LoadingSkeleton'; | ||||||||||||
|
||||||||||||
import './Card.scss'; | ||||||||||||
|
||||||||||||
export const CardSizes = { | ||||||||||||
EXTRA_SMALL: 'xs', | ||||||||||||
SMALL: 'sm', | ||||||||||||
MEDIUM: 'md', | ||||||||||||
LARGE: 'lg', | ||||||||||||
} as const; | ||||||||||||
|
||||||||||||
type ElementProps = DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>; | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is happening here with this syntax? like, what does it mean or how is it defining this type? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea so this is using what are called generics, which we won't be getting to for a few weeks in the course. In essence, this type evaluates to the set of all possible props that can be passed to an HTML element (as far as React is concerned). So really, it's the firehose of HTML props, including all even listeners, all aria attributes, etc, etc, etc. The only reason that I'm using it here is because the card component is spreading all its props into the element that it renders. This is an anti-pattern IMHO, but I didn't want to change the API of this component in this work, just convert it to TS: ui-design-system/src/Card/Card.tsx Line 50 in c11d2f0
ui-design-system/src/Card/Card.tsx Lines 65 to 68 in c11d2f0
|
||||||||||||
|
||||||||||||
type CardProps = { | ||||||||||||
children?: ReactNode; | ||||||||||||
className?: string; | ||||||||||||
divided?: boolean; | ||||||||||||
elementType?: string; | ||||||||||||
helperText?: ReactNode; | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||
isLoading?: boolean; | ||||||||||||
loadingSkeleton?: ReactNode; | ||||||||||||
loadingSkeletonParagraphCount?: number; | ||||||||||||
noPadding?: boolean; | ||||||||||||
size: 'xs' | 'sm' | 'md' | 'lg'; | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead, we can explicitly state that |
||||||||||||
subTitle?: ReactNode; | ||||||||||||
title?: ReactNode; | ||||||||||||
} & ElementProps; | ||||||||||||
|
||||||||||||
const Card = ({ | ||||||||||||
children, | ||||||||||||
className, | ||||||||||||
divided = false, | ||||||||||||
elementType = 'section', | ||||||||||||
helperText, | ||||||||||||
isLoading = false, | ||||||||||||
loadingSkeleton, | ||||||||||||
loadingSkeletonParagraphCount = 1, | ||||||||||||
noPadding = false, | ||||||||||||
size, | ||||||||||||
subTitle, | ||||||||||||
title, | ||||||||||||
...props | ||||||||||||
}: CardProps) => { | ||||||||||||
const defaultLoadingSkeleton = ( | ||||||||||||
<> | ||||||||||||
<LoadingSkeleton height={24} width="33%" /> | ||||||||||||
<br /> | ||||||||||||
{Array(loadingSkeletonParagraphCount).fill(0).map((_, i) => ( | ||||||||||||
// eslint-disable-next-line react/no-array-index-key | ||||||||||||
<div className="Card__loading-skeleton-paragraphs" key={`skeleton-paragraph-${i}`}> | ||||||||||||
<LoadingSkeleton count={3} /> | ||||||||||||
</div> | ||||||||||||
))} | ||||||||||||
</> | ||||||||||||
); | ||||||||||||
|
||||||||||||
return createElement( | ||||||||||||
elementType, | ||||||||||||
{ | ||||||||||||
...props, | ||||||||||||
className: classNames( | ||||||||||||
'Card', | ||||||||||||
{ [`Card--${size}`]: size }, | ||||||||||||
className, | ||||||||||||
{ | ||||||||||||
'Card--divided': divided, | ||||||||||||
'Card--no-padding': noPadding, | ||||||||||||
}, | ||||||||||||
), | ||||||||||||
}, | ||||||||||||
<> | ||||||||||||
{isLoading ? (loadingSkeleton || defaultLoadingSkeleton) : ( | ||||||||||||
<> | ||||||||||||
{title && ( | ||||||||||||
<div className="Card__header"> | ||||||||||||
<h2 className="Card__title">{title}</h2> | ||||||||||||
{helperText && <span className="Card__helper-text">{helperText}</span>} | ||||||||||||
</div> | ||||||||||||
)} | ||||||||||||
|
||||||||||||
{divided && <hr className="Card__divider" /> } | ||||||||||||
{subTitle && <h3 className="Card__subtitle">{subTitle}</h3> } | ||||||||||||
{children} | ||||||||||||
</> | ||||||||||||
)} | ||||||||||||
</>, | ||||||||||||
); | ||||||||||||
}; | ||||||||||||
|
||||||||||||
export default Card; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've kept this here for backward compatibility's sake, but it's not really necessary in Typescript. As we get further along with adoption, we can explore just removing these types of objects altogether.