feat: Add `framed` optional property for IconElement `ui-kit` component (#37726)

Co-authored-by: Douglas Gubert <1810309+d-gubert@users.noreply.github.com>
pull/37715/merge
gabriellsh 3 days ago committed by GitHub
parent 855fae239d
commit d3538e7045
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      .changeset/many-walls-cheat.md
  2. 40
      packages/fuselage-ui-kit/src/elements/IconElement.tsx
  3. 1
      packages/fuselage-ui-kit/src/stories/Message.stories.tsx
  4. 29
      packages/fuselage-ui-kit/src/stories/payloads/infoCard.ts
  5. 4
      packages/ui-kit/src/blocks/BlockElement.ts
  6. 8
      packages/ui-kit/src/blocks/elements/IconElement.ts
  7. 4
      packages/ui-kit/src/blocks/layout/InfoCardBlock.ts
  8. 2
      packages/ui-kit/src/index.ts

@ -0,0 +1,6 @@
---
"@rocket.chat/fuselage-ui-kit": minor
"@rocket.chat/ui-kit": minor
---
Introduces a new variation of the `Icon` element to `ui-kit` through the new `framed` optional property.

@ -1,24 +1,46 @@
import { Icon } from '@rocket.chat/fuselage'; import { Icon, FramedIcon } from '@rocket.chat/fuselage';
import type * as UiKit from '@rocket.chat/ui-kit'; import type * as UiKit from '@rocket.chat/ui-kit';
import type { ReactElement } from 'react'; import type { ComponentProps, ReactElement } from 'react';
import type { BlockProps } from '../utils/BlockProps'; import type { BlockProps } from '../utils/BlockProps';
type IconElementProps = BlockProps<UiKit.IconElement>; type IconElementProps = BlockProps<UiKit.FrameableIconElement>;
const getVariantColor = (variant: UiKit.IconElement['variant']): string => { const getVariantColor = (variant: UiKit.FrameableIconElement['variant']): string => {
switch (variant) { switch (variant) {
case 'default':
return 'default';
case 'danger': case 'danger':
return 'danger'; return 'danger';
case 'secondary': case 'secondary':
return 'secondary-info'; return 'secondary-info';
case 'warning':
return 'status-font-on-warning';
case 'default':
default:
return 'default';
} }
}; };
const IconElement = ({ block }: IconElementProps): ReactElement => ( const getFramedIconProps = (
<Icon size={20} name={block.icon} color={getVariantColor(block.variant)} /> variant: UiKit.FrameableIconElement['variant'],
); ): Pick<ComponentProps<typeof FramedIcon>, 'warning' | 'danger' | 'neutral'> => {
switch (variant) {
case 'danger':
return { danger: true };
case 'warning':
return { warning: true };
case 'default':
case 'secondary':
default:
return { neutral: true };
}
};
const IconElement = ({ block }: IconElementProps): ReactElement => {
const { icon, variant, framed } = block;
if (framed) {
return <FramedIcon size={20} icon={icon} {...getFramedIconProps(variant)} />;
}
return <Icon size={20} name={icon} color={getVariantColor(variant)} />;
};
export default IconElement; export default IconElement;

@ -117,3 +117,4 @@ export const PreviewWithExternalUrl = createStory(payloads.previewWithExternalUr
export const InfoCard = createStory(payloads.infoCard); export const InfoCard = createStory(payloads.infoCard);
export const InfoCardMultiple = createStory(payloads.infoCardMultiple); export const InfoCardMultiple = createStory(payloads.infoCardMultiple);
export const InfoCardMultipleIcons = createStory(payloads.infoCardMultipleIcons);

@ -32,7 +32,7 @@ export const infoCardMultiple: readonly UiKit.InfoCardBlock[] = [
{ {
background: 'default', background: 'default',
elements: [ elements: [
{ type: 'icon', icon: 'phone-off', variant: 'default' }, { type: 'icon', icon: 'phone-off', variant: 'warning' },
{ type: 'plain_text', text: 'Call ended' }, { type: 'plain_text', text: 'Call ended' },
], ],
action: getIconButtonPayload({ icon: 'info' }), action: getIconButtonPayload({ icon: 'info' }),
@ -44,3 +44,30 @@ export const infoCardMultiple: readonly UiKit.InfoCardBlock[] = [
], ],
}, },
]; ];
export const infoCardMultipleIcons: readonly UiKit.InfoCardBlock[] = [
{
type: 'info_card',
rows: [
{
background: 'default',
elements: [
{ type: 'plain_text', text: 'Framed icons' },
{ type: 'icon', icon: 'phone-off', variant: 'default', framed: true },
{ type: 'icon', icon: 'clock', variant: 'warning', framed: true },
{ type: 'icon', icon: 'phone-issue', variant: 'danger', framed: true },
],
},
{
background: 'default',
elements: [
{ type: 'plain_text', text: 'Icons' },
{ type: 'icon', icon: 'phone-off', variant: 'default' },
{ type: 'icon', icon: 'clock', variant: 'warning' },
{ type: 'icon', icon: 'phone-issue', variant: 'danger' },
{ type: 'icon', icon: 'info', variant: 'secondary' },
],
},
],
},
];

@ -5,7 +5,7 @@ import type { ConversationsSelectElement } from './elements/ConversationsSelectE
import type { DatePickerElement } from './elements/DatePickerElement'; import type { DatePickerElement } from './elements/DatePickerElement';
import type { ExperimentalTabElement } from './elements/ExperimentalTabElement'; import type { ExperimentalTabElement } from './elements/ExperimentalTabElement';
import type { IconButtonElement } from './elements/IconButtonElement'; import type { IconButtonElement } from './elements/IconButtonElement';
import type { IconElement } from './elements/IconElement'; import type { FrameableIconElement } from './elements/IconElement';
import type { ImageElement } from './elements/ImageElement'; import type { ImageElement } from './elements/ImageElement';
import type { LinearScaleElement } from './elements/LinearScaleElement'; import type { LinearScaleElement } from './elements/LinearScaleElement';
import type { MultiChannelsSelectElement } from './elements/MultiChannelsSelectElement'; import type { MultiChannelsSelectElement } from './elements/MultiChannelsSelectElement';
@ -40,5 +40,5 @@ export type BlockElement =
| CheckboxElement | CheckboxElement
| TimePickerElement | TimePickerElement
| ExperimentalTabElement | ExperimentalTabElement
| IconElement | FrameableIconElement
| IconButtonElement; | IconButtonElement;

@ -1,7 +1,11 @@
type AvailableIcons = 'phone-off' | 'phone-issue' | 'clock' | 'arrow-forward' | 'info'; type AvailableIcons = 'phone-off' | 'phone-issue' | 'clock' | 'arrow-forward' | 'info' /* | 'phone-question-mark' */; // TODO add new icon when available in fuselage
export type IconElement = { export type IconElement = {
type: 'icon'; type: 'icon';
icon: AvailableIcons; icon: AvailableIcons;
variant: 'default' | 'danger' | 'secondary'; variant: 'default' | 'danger' | 'secondary' | 'warning';
};
export type FrameableIconElement = IconElement & {
framed?: boolean;
}; };

@ -1,13 +1,13 @@
import type { LayoutBlockType } from '../LayoutBlockType'; import type { LayoutBlockType } from '../LayoutBlockType';
import type { LayoutBlockish } from '../LayoutBlockish'; import type { LayoutBlockish } from '../LayoutBlockish';
import type { IconButtonElement } from '../elements/IconButtonElement'; import type { IconButtonElement } from '../elements/IconButtonElement';
import type { IconElement } from '../elements/IconElement'; import type { FrameableIconElement } from '../elements/IconElement';
import type { Markdown } from '../text/Markdown'; import type { Markdown } from '../text/Markdown';
import type { PlainText } from '../text/PlainText'; import type { PlainText } from '../text/PlainText';
type InfoCardRow = { type InfoCardRow = {
background: 'default' | 'secondary'; background: 'default' | 'secondary';
elements: readonly (IconElement | PlainText | Markdown)[]; elements: readonly (FrameableIconElement | PlainText | Markdown)[];
action?: IconButtonElement; action?: IconButtonElement;
}; };

@ -28,7 +28,7 @@ export { RadioButtonElement } from './blocks/elements/RadioButtonElement';
export { TimePickerElement } from './blocks/elements/TimePickerElement'; export { TimePickerElement } from './blocks/elements/TimePickerElement';
export { BlockElement } from './blocks/BlockElement'; export { BlockElement } from './blocks/BlockElement';
export { ExperimentalTabElement } from './blocks/elements/ExperimentalTabElement'; export { ExperimentalTabElement } from './blocks/elements/ExperimentalTabElement';
export { IconElement } from './blocks/elements/IconElement'; export { IconElement, FrameableIconElement } from './blocks/elements/IconElement';
export { IconButtonElement } from './blocks/elements/IconButtonElement'; export { IconButtonElement } from './blocks/elements/IconButtonElement';
export { ActionsBlock } from './blocks/layout/ActionsBlock'; export { ActionsBlock } from './blocks/layout/ActionsBlock';

Loading…
Cancel
Save