Skip to content

Instantly share code, notes, and snippets.

@dipiash
Created March 13, 2023 21:56
Show Gist options
  • Save dipiash/a2798b48c621439e023e6f9986aca1d4 to your computer and use it in GitHub Desktop.
Save dipiash/a2798b48c621439e023e6f9986aca1d4 to your computer and use it in GitHub Desktop.
Stats component
import { createStyles } from '@mantine/core'
export const useStatsStyles = createStyles((theme) => ({
root: {
backgroundColor: theme.other.colors.white[0],
padding: 16,
border: '1px solid',
borderColor: theme.other.colors.greyIron[4],
borderRadius: theme.other.borderRadius[8],
boxSizing: 'border-box',
},
wrapper: {
justifyContent: 'space-between',
height: '100%',
},
header: {},
headerTitleWrapper: {},
headerTitle: {
font: theme.other.fonts.desktop.s.xs.extraImportant,
color: theme.other.colors.greyIron[12],
textTransform: 'uppercase',
},
headerTooltip: {
maxWidth: 200,
},
headerTooltipButton: {},
headerRightTopIcon: {
width: 20,
height: 20,
color: theme.other.colors.greyIron[7],
svg: {
width: 20,
height: 20,
},
},
descriptionWrapper: {},
description: {
font: theme.other.fonts.desktop.s.l.extraImportant,
color: theme.other.colors.greyIron[20],
},
descriptionSub: {
font: theme.other.fonts.desktop.s.xs.default,
color: theme.other.colors.greyIron[12],
},
}))
import React, { FC, memo, MouseEventHandler, useCallback, useState } from 'react'
import { Group, Paper, Stack, useComponentDefaultProps } from '@mantine/core'
import { HelpCircle12 } from '@PROJECT_NAME/icons'
import { ButtonSizeEnum, ButtonVariantEnum } from '../Button/Button.types'
import { StatsPropertiesInterface } from './Stats.types'
import { Button } from '../Button'
import { Skeleton } from '../Skeleton'
import { Text } from '../Text'
import { Title } from '../Title'
import { Tooltip } from '../Tooltip'
import { useStatsStyles } from './Stats.styled'
const defaultProps: Partial<StatsPropertiesInterface> = {
isLoading: false,
}
export const Stats: FC<StatsPropertiesInterface> = memo<StatsPropertiesInterface>((properties) => {
const {
headerTitle,
headerTooltipText,
HeaderRightTopIconComponent,
description,
descriptionSub,
isLoading,
classNames,
styles,
unstyled,
className,
...rest
} = useComponentDefaultProps('Stats', defaultProps, properties)
const { classes, cx } = useStatsStyles(undefined, { classNames, styles, unstyled, name: 'Stats' })
const [openedTooltip, setOpenedTooltip] = useState(false)
const handleOpenedTooltip: MouseEventHandler = useCallback((event) => {
event.preventDefault()
event.stopPropagation()
setOpenedTooltip((o) => !o)
}, [])
return (
<Paper className={cx(classes.root, className)} {...rest}>
<Stack className={classes.wrapper} spacing={16}>
<Group className={classes.header} position="apart" noWrap>
<Group className={classes.headerTitleWrapper} spacing={4} noWrap>
<Title className={classes.headerTitle} order={3} elementSize="xs">
{headerTitle}
</Title>
{headerTooltipText && (
<Tooltip className={classes.headerTooltip} opened={openedTooltip} onClick={handleOpenedTooltip} label={headerTooltipText} multiline>
<Button
isIconOnly
elementVariant={ButtonVariantEnum.SecondaryMainLine}
elementSize={ButtonSizeEnum.XS}
rightIcon={<HelpCircle12 />}
data-testid="Stats-tooltip-button"
className={classes.headerTooltipButton}
/>
</Tooltip>
)}
</Group>
{HeaderRightTopIconComponent && (
<div className={classes.headerRightTopIcon}>{<HeaderRightTopIconComponent data-testid="Stats-header-right-top-icon" />}</div>
)}
</Group>
{(description || descriptionSub) && (
<Stack className={classes.descriptionWrapper} spacing={2}>
{description && (
<Text className={classes.description} elementSize="l" elementVariant="extraImportant">
{isLoading ? <Skeleton uniqueKey="sk-stats-description-loader" width={61} height={12} /> : description}
</Text>
)}
{descriptionSub && (
<Text className={classes.descriptionSub} elementSize="xs" elementVariant="default">
{descriptionSub}
</Text>
)}
</Stack>
)}
</Stack>
</Paper>
)
})
Stats.displayName = 'Stats'
import { FC, ReactNode } from 'react'
import { CSSObject, DefaultProps, Selectors } from '@mantine/styles'
import { useStatsStyles } from './Stats.styled'
export type StatsStylesNamesType = Selectors<typeof useStatsStyles>
export interface StatsPropertiesInterface extends DefaultProps<StatsStylesNamesType, Record<string, CSSObject>> {
/** Title */
headerTitle: ReactNode
/** Tooltip text */
headerTooltipText?: ReactNode
/** Top right icon */
HeaderRightTopIconComponent?: FC
/** Description */
description?: ReactNode
/** Sub description */
descriptionSub?: ReactNode
/** Is stats loading */
isLoading?: boolean
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment