Skip to content

Commit

Permalink
feat: actionButton on Banner
Browse files Browse the repository at this point in the history
  • Loading branch information
TateB committed Aug 9, 2024
1 parent 89dbbb3 commit 16ee2ec
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 27 deletions.
94 changes: 67 additions & 27 deletions components/src/components/atoms/Banner/Banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type BaseProps = {
actionIcon?: React.ReactNode
icon?: React.ReactNode
iconType?: IconTypes
actionButton?: React.ReactNode
} & NativeDivProps

type WithIcon = {
Expand All @@ -40,6 +41,7 @@ type WithAnchor = {
rel?: string
onDismiss?: never
actionIcon?: React.ReactNode
actionButton?: never
}

type WithoutAnchor = {
Expand All @@ -48,35 +50,38 @@ type WithoutAnchor = {
target?: never
rel?: never
onDismiss?: () => void
actionButton?: React.ReactNode
}

type NonNullableAlert = NonNullable<Props['alert']>

const Container = styled.div<{
$alert: NonNullableAlert
$hasAction: boolean
$hasBannerWideAction: boolean
}>(
({ theme, $alert, $hasAction }) => css`
({ theme, $alert, $hasBannerWideAction }) => css`
position: relative;
background: ${theme.colors.backgroundPrimary};
border: 1px solid ${theme.colors.border};
border-radius: ${theme.radii['2xLarge']};
padding: ${theme.space[4]};
display: flex;
align-items: stretch;
flex-direction: column;
gap: ${theme.space[4]};
width: ${theme.space.full};
transition: all 150ms ease-in-out;
${mq.sm.min(
css`
padding: ${theme.space['6']};
gap: ${theme.space[6]};
align-items: center;
flex-direction: row;
gap: ${theme.space[6]};
`,
)}
${$hasAction &&
${$hasBannerWideAction &&
css`
padding-right: ${theme.space[8]};
&:hover {
Expand Down Expand Up @@ -108,6 +113,16 @@ const Container = styled.div<{
)

const Content = styled.div(
({ theme }) => css`
flex: 1;
display: flex;
align-items: stretch;
gap: ${theme.space[4]};
width: ${theme.space.full};
`,
)

const TextContent = styled.div(
({ theme }) => css`
flex: 1;
display: flex;
Expand Down Expand Up @@ -165,7 +180,23 @@ const IconContainer = styled.div<{
`,
)

const ActionButtonContainer = styled.button(
const CustomActionButtonContainer = styled.div(
({ theme }) => css`
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
& > * {
width: ${theme.space.full};
${mq.sm.min(css`
width: ${theme.space.fit};
`)}
}
`,
)

const ActionIconButtonContainer = styled.button(
({ theme }) => css`
position: absolute;
top: 0;
Expand All @@ -174,7 +205,7 @@ const ActionButtonContainer = styled.button(
`,
)

const ActionButtonIconWrapper = styled.div<{
const ActionIconButtonIconWrapper = styled.div<{
$alert: NonNullableAlert
$hasAction?: boolean
}>(
Expand Down Expand Up @@ -230,27 +261,28 @@ const ActionButtonIconWrapper = styled.div<{
`,
)

const ActionButton = ({
alert = 'info',
const ActionIconButton = ({
alert,
icon,
hasHref,
onDismiss,
}: Pick<Props, 'alert' | 'onDismiss'> & { hasHref: boolean } & WithIcon) => {
}: Required<WithAlert> &
Pick<Props, 'onDismiss'> & { hasHref: boolean } & WithIcon) => {
if (onDismiss)
return (
<ActionButtonContainer onClick={() => onDismiss()}>
<ActionButtonIconWrapper $alert={alert} $hasAction>
<ActionIconButtonContainer onClick={() => onDismiss()}>
<ActionIconButtonIconWrapper $alert={alert} $hasAction>
{icon || <CrossSVG />}
</ActionButtonIconWrapper>
</ActionButtonContainer>
</ActionIconButtonIconWrapper>
</ActionIconButtonContainer>
)
if (hasHref || icon)
return (
<ActionButtonContainer as="div">
<ActionButtonIconWrapper $alert={alert}>
<ActionIconButtonContainer as="div">
<ActionIconButtonIconWrapper $alert={alert}>
{icon || <UpRightArrowSVG />}
</ActionButtonIconWrapper>
</ActionButtonContainer>
</ActionIconButtonIconWrapper>
</ActionIconButtonContainer>
)
return null
}
Expand Down Expand Up @@ -282,6 +314,7 @@ export const Banner = React.forwardRef<
as: asProp,
children,
onDismiss,
actionButton,
...props
},
ref,
Expand All @@ -295,27 +328,34 @@ export const Banner = React.forwardRef<
))

const hasHref = !!props.href
const hasAction = hasHref || !!props.onClick
const hasBannerWideAction = hasHref || !!props.onClick
const _iconType = iconType || defaultIconType(alert, icon)

return (
<Container
{...props}
$alert={alert}
$hasAction={hasAction}
$hasBannerWideAction={hasBannerWideAction}
as={asProp as any}
ref={ref}
>
{_iconType !== 'none' && (
<IconContainer $alert={alert} $type={_iconType}>
{Icon}
</IconContainer>
)}
<Content>
{title && <Typography fontVariant="largeBold">{title}</Typography>}
<Typography>{children}</Typography>
{_iconType !== 'none' && (
<IconContainer $alert={alert} $type={_iconType}>
{Icon}
</IconContainer>
)}
<TextContent>
{title && <Typography fontVariant="largeBold">{title}</Typography>}
<Typography>{children}</Typography>
</TextContent>
</Content>
<ActionButton
{actionButton && (
<CustomActionButtonContainer>
<div>{actionButton}</div>
</CustomActionButtonContainer>
)}
<ActionIconButton
alert={alert}
hasHref={hasHref}
icon={props.actionIcon}
Expand Down
16 changes: 16 additions & 0 deletions docs/src/reference/mdx/atoms/Banner.docs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,22 @@ import { Banner } from '@ensdomains/thorin'
</DeleteMe>
```

## Action Button

```tsx live=true
<DeleteMe>
<Banner alert="info" title="Heading" actionButton={<Button colorStyle="accentSecondary">Action</Button>}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</Banner>
<Banner alert="warning" title="Heading" actionButton={<Button colorStyle="yellowPrimary">Action</Button>}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</Banner>
<Banner alert="error" title="Heading" actionButton={<Button colorStyle="redPrimary">Action</Button>}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</Banner>
</DeleteMe>
```

## Icon Type

```tsx live=true
Expand Down

0 comments on commit 16ee2ec

Please sign in to comment.