Skip to content

Commit

Permalink
feat(fuselage): Introduce Callout actions (#1415)
Browse files Browse the repository at this point in the history
  • Loading branch information
dougfabris authored Aug 1, 2024
1 parent 6b45d98 commit 5fe8459
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 50 deletions.
5 changes: 5 additions & 0 deletions .changeset/sharp-paws-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/fuselage": minor
---

feat(fuselage): Introduce Callout actions
6 changes: 6 additions & 0 deletions packages/fuselage/.jest/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,9 @@ expect.extend({
});

expect.extend(toHaveNoViolations);

window.ResizeObserver = jest.fn().mockImplementation(() => ({
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
}));
16 changes: 15 additions & 1 deletion packages/fuselage/src/components/Callout/Callout.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import type { ComponentStory, ComponentMeta } from '@storybook/react';
import React from 'react';

import { Callout } from '../..';
import { Button, ButtonGroup, Callout } from '../..';
import { setStoryDescription } from '../../helpers/setStoryDescription';

export default {
Expand Down Expand Up @@ -87,3 +87,17 @@ CustomIcon.args = {
title: 'This is a message with custom icon',
icon: 'hash',
};

export const WithActions: ComponentStory<typeof Callout> = (args) => (
<Callout {...args} />
);
WithActions.args = {
title: 'This is a generic title',
children: 'This is a generic description.',
actions: (
<ButtonGroup>
<Button small>Button</Button>
<Button small>Button</Button>
</ButtonGroup>
),
};
29 changes: 25 additions & 4 deletions packages/fuselage/src/components/Callout/Callout.styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,36 @@ $callout-text-color: theme('callout-text-color', colors.font(default));
}

&__wrapper {
display: flex;

overflow: hidden;
flex-flow: column nowrap;

justify-content: space-between;

flex: 1 1 0;

margin-inline-start: lengths.margin(12);

@include typography.use-font-scale(c1);
> :nth-child(2) {
margin-block-start: lengths.margin(12);
}

&--large {
display: flex;

overflow: hidden;
flex-direction: row;
align-items: center;

> :nth-child(2) {
margin-block-start: lengths.margin(0);
}
}
}

&__wrapper-content {
display: flex;

overflow: hidden;
flex-flow: column nowrap;

> :nth-child(2) {
margin-block-start: lengths.margin(4);
Expand Down
21 changes: 17 additions & 4 deletions packages/fuselage/src/components/Callout/Callout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ComponentProps, ReactNode } from 'react';
import { useResizeObserver } from '@rocket.chat/fuselage-hooks';
import type { ComponentProps, ReactElement, ReactNode } from 'react';
import React from 'react';

import Box from '../Box';
Expand All @@ -9,16 +10,24 @@ type CalloutProps = Omit<ComponentProps<typeof Box>, 'type' | 'name'> & {
title?: ReactNode;
children?: ReactNode;
icon?: ComponentProps<typeof Icon>['name'];
actions?: ReactElement;
};

const WRAPPER_LIMIT_SIZE = 420;

export const Callout = ({
type,
title,
children,
icon,
className,
actions,
...props
}: CalloutProps) => {
const { ref, borderBoxSize } = useResizeObserver();
const isLarge =
borderBoxSize.inlineSize && borderBoxSize.inlineSize >= WRAPPER_LIMIT_SIZE;

const defaultIcon =
(type === 'info' && 'info-circled') ||
(type === 'success' && 'checkmark-circled') ||
Expand All @@ -28,6 +37,7 @@ export const Callout = ({

return (
<Box
ref={ref}
is='section'
className={['rcx-callout', type && `rcx-callout--${type}`, className]
.filter(Boolean)
Expand All @@ -39,9 +49,12 @@ export const Callout = ({
name={icon || defaultIcon}
size='x20'
/>
<Box rcx-callout__wrapper>
{title && <Box rcx-callout__title>{title}</Box>}
{children && <Box rcx-callout__content>{children}</Box>}
<Box rcx-callout__wrapper rcx-callout__wrapper--large={isLarge}>
<Box rcx-callout__wrapper-content>
{title && <Box rcx-callout__title>{title}</Box>}
{children && <Box rcx-callout__content>{children}</Box>}
</Box>
{actions && <Box rcx-callout__actions>{actions}</Box>}
</Box>
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ exports[`[CheckBox Rendering] renders CustomIcon without crashing 1`] = `
class="rcx-box rcx-box--full rcx-callout__wrapper"
>
<div
class="rcx-box rcx-box--full rcx-callout__title"
class="rcx-box rcx-box--full rcx-callout__wrapper-content"
>
This is a message with custom icon
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
This is a generic description.
<div
class="rcx-box rcx-box--full rcx-callout__title"
>
This is a message with custom icon
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
This is a generic description.
</div>
</div>
</div>
</section>
Expand All @@ -47,14 +51,18 @@ exports[`[CheckBox Rendering] renders Danger without crashing 1`] = `
class="rcx-box rcx-box--full rcx-callout__wrapper"
>
<div
class="rcx-box rcx-box--full rcx-callout__title"
>
This is a danger message
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
class="rcx-box rcx-box--full rcx-callout__wrapper-content"
>
This is a generic description.
<div
class="rcx-box rcx-box--full rcx-callout__title"
>
This is a danger message
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
This is a generic description.
</div>
</div>
</div>
</section>
Expand All @@ -78,14 +86,18 @@ exports[`[CheckBox Rendering] renders Default without crashing 1`] = `
class="rcx-box rcx-box--full rcx-callout__wrapper"
>
<div
class="rcx-box rcx-box--full rcx-callout__title"
class="rcx-box rcx-box--full rcx-callout__wrapper-content"
>
This is a generic title
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
This is a generic description.
<div
class="rcx-box rcx-box--full rcx-callout__title"
>
This is a generic title
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
This is a generic description.
</div>
</div>
</div>
</section>
Expand All @@ -109,14 +121,18 @@ exports[`[CheckBox Rendering] renders Info without crashing 1`] = `
class="rcx-box rcx-box--full rcx-callout__wrapper"
>
<div
class="rcx-box rcx-box--full rcx-callout__title"
class="rcx-box rcx-box--full rcx-callout__wrapper-content"
>
This is a info message
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
This is a generic description.
<div
class="rcx-box rcx-box--full rcx-callout__title"
>
This is a info message
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
This is a generic description.
</div>
</div>
</div>
</section>
Expand All @@ -140,14 +156,18 @@ exports[`[CheckBox Rendering] renders Success without crashing 1`] = `
class="rcx-box rcx-box--full rcx-callout__wrapper"
>
<div
class="rcx-box rcx-box--full rcx-callout__title"
>
This is a success message
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
class="rcx-box rcx-box--full rcx-callout__wrapper-content"
>
This is a generic description.
<div
class="rcx-box rcx-box--full rcx-callout__title"
>
This is a success message
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
This is a generic description.
</div>
</div>
</div>
</section>
Expand All @@ -171,14 +191,82 @@ exports[`[CheckBox Rendering] renders Warning without crashing 1`] = `
class="rcx-box rcx-box--full rcx-callout__wrapper"
>
<div
class="rcx-box rcx-box--full rcx-callout__title"
class="rcx-box rcx-box--full rcx-callout__wrapper-content"
>
<div
class="rcx-box rcx-box--full rcx-callout__title"
>
This is a warning message
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
This is a generic description.
</div>
</div>
</div>
</section>
</div>
</body>
`;

exports[`[CheckBox Rendering] renders WithActions without crashing 1`] = `
<body>
<div>
<section
class="rcx-box rcx-box--full rcx-callout"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-info-circled rcx-icon rcx-callout__icon rcx-css-4pvxx3"
>
</i>
<div
class="rcx-box rcx-box--full rcx-callout__wrapper"
>
<div
class="rcx-box rcx-box--full rcx-callout__wrapper-content"
>
This is a warning message
<div
class="rcx-box rcx-box--full rcx-callout__title"
>
This is a generic title
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
This is a generic description.
</div>
</div>
<div
class="rcx-box rcx-box--full rcx-callout__content"
class="rcx-box rcx-box--full rcx-callout__actions"
>
This is a generic description.
<div
class="rcx-button-group rcx-button-group--align-start"
role="group"
>
<button
class="rcx-box rcx-box--full rcx-button--small rcx-button rcx-button-group__item"
type="button"
>
<span
class="rcx-button--content"
>
Button
</span>
</button>
<button
class="rcx-box rcx-box--full rcx-button--small rcx-button rcx-button-group__item"
type="button"
>
<span
class="rcx-button--content"
>
Button
</span>
</button>
</div>
</div>
</div>
</section>
Expand All @@ -202,9 +290,13 @@ exports[`[CheckBox Rendering] renders WithDescriptionOnly without crashing 1`] =
class="rcx-box rcx-box--full rcx-callout__wrapper"
>
<div
class="rcx-box rcx-box--full rcx-callout__content"
class="rcx-box rcx-box--full rcx-callout__wrapper-content"
>
This is a generic description.
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
This is a generic description.
</div>
</div>
</div>
</section>
Expand Down

0 comments on commit 5fe8459

Please sign in to comment.