Unverified Commit d0d0d82a authored by Douglas Fabris's avatar Douglas Fabris Committed by GitHub

perf: Remove Box from Option (#347)

Co-authored-by: default avatarGuilherme Gazzo <guilherme@gazzo.xyz>
parent bb534df6
import React from 'react';
import { Box } from '../src';
import { Box, Icon } from '../src';
export function PropsVariationSection({
component: Component,
......@@ -107,3 +107,24 @@ v/L21v8BT/ZVoe1UItsAAAAASUVORK5CYII=`;
export const blankAvatar = `data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BA
AAAAAALAAAAAABAAEAAAICRAEAOw==`;
export const menuOptions = {
makeAdmin: {
label: (
<Box display='flex' alignItems='center'>
<Icon mie='x4' name='key' size='x16' />
Make Admin
</Box>
),
action: () => console.log('[...] is now admin'),
},
delete: {
label: (
<Box display='flex' alignItems='center' color='danger'>
<Icon mie='x4' name='trash' size='x16' />
Delete
</Box>
),
action: () => console.log('[...] no longer exists'),
},
};
import { Meta, Canvas, ArgsTable, Story } from '@storybook/addon-docs/blocks';
import { Box, Icon, Menu } from '..';
export const options = {
makeAdmin: {
label: <Box display='flex' alignItems='center'><Icon mie='x4' name='key' size='x16'/>Make Admin</Box>,
action: () => console.log('[...] is now admin'),
},
delete: {
label: <Box display='flex' alignItems='center' color='danger'><Icon mie='x4' name='trash' size='x16'/>Delete</Box>,
action: () => console.log('[...] no longer exists'),
},
}
import { Box, Menu } from '..';
import { menuOptions } from '../../../.storybook/helpers.js';
<Meta title='Misc/Menu' parameters={{ jest: ['Menu/spec'] }} />
......@@ -22,7 +12,7 @@ Kebab Menu
<Canvas>
<Story name='Default'>
<Box style={{ position: 'relative', maxWidth: 250 }} >
<Menu options={options} />
<Menu options={menuOptions} />
</Box>
</Story>
</Canvas>
......
import { Meta, Canvas, ArgsTable, Story } from '@storybook/addon-docs/blocks';
import LinkTo from '@storybook/addon-links/react';
import { Option } from '.';
import { Box, Avatar, Menu, StatusBullet } from '../..';
import { exampleAvatar, menuOptions } from '../../../../.storybook/helpers.js';
<Meta title='Misc/Options/Option' parameters={{ jest: ['Option/spec'] }} />
# Option
The generic <LinkTo kind='Misc/Options/Option' story='Default'>`Option`</LinkTo> item of options. Can be freely used or inside the <LinkTo kind='Misc/Options/Options' story='Default'>`Options`</LinkTo> as well.
<Canvas>
<Story name='Default'>
<Box position='relative' maxWidth={250}>
<Option>
<Option.Content>Lorem Ipsum Lorem</Option.Content>
</Option>
<Option>
<Option.Content>Lorem Ipsum Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem</Option.Content>
</Option>
<Option>
<Option.Content>Lorem Ipsum Lorem <Option.Description>Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem</Option.Description></Option.Content>
</Option>
</Box>
</Story>
</Canvas>
## With avatar
<Canvas>
<Story name='withAvatar'>
<Box position='relative' maxWidth={250}>
<Option>
<Option.Avatar>
<Avatar url={exampleAvatar} size='x28' />
</Option.Avatar>
<Option.Content>Lorem Ipsum Lorem</Option.Content>
</Option>
<Option>
<Option.Avatar>
<Avatar url={exampleAvatar} size='x28' />
</Option.Avatar>
<Option.Content>Lorem Ipsum Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem</Option.Content>
</Option>
<Option>
<Option.Avatar>
<Avatar url={exampleAvatar} size='x28' />
</Option.Avatar>
<Option.Content>Lorem Ipsum Lorem <Option.Description>Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem</Option.Description></Option.Content>
</Option>
</Box>
</Story>
</Canvas>
## With presence
<Canvas>
<Story name='withPresence'>
<Box position='relative' maxWidth={250}>
<Option>
<Option.Column><StatusBullet /></Option.Column>
<Option.Content>Lorem Ipsum Lorem</Option.Content>
</Option>
<Option>
<Option.Avatar>
<Avatar url={exampleAvatar} size='x28' />
</Option.Avatar>
<Option.Column><StatusBullet /></Option.Column>
<Option.Content>Lorem Ipsum Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem</Option.Content>
</Option>
</Box>
</Story>
</Canvas>
## With menu
<Canvas>
<Story name='withMenu'>
<Box position='relative' maxWidth={250}>
<Option>
<Option.Content>Lorem Ipsum Lorem</Option.Content>
<Option.Menu><Menu options={menuOptions} /></Option.Menu>
</Option>
<Option>
<Option.Avatar>
<Avatar url={exampleAvatar} size='x28' />
</Option.Avatar>
<Option.Column><StatusBullet /></Option.Column>
<Option.Content>Lorem Ipsum Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem</Option.Content>
<Option.Menu><Menu options={menuOptions} /></Option.Menu>
</Option>
</Box>
</Story>
</Canvas>
## With Icon
<Canvas>
<Story name='withIcon'>
<Box position='relative' maxWidth={250}>
<Option>
<Option.Icon name='bell'/>
<Option.Content>Lorem Ipsum Lorem</Option.Content>
<Option.Menu><Menu options={menuOptions} /></Option.Menu>
</Option>
<Option>
<Option.Avatar>
<Avatar url={exampleAvatar} size='x28' />
</Option.Avatar>
<Option.Icon name='bell'/>
<Option.Column><StatusBullet /></Option.Column>
<Option.Content>Lorem Ipsum Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem Lorem Ipsum Lorem</Option.Content>
<Option.Menu><Menu options={menuOptions} /></Option.Menu>
</Option>
</Box>
</Story>
</Canvas>
## As UserItem
<Canvas>
<Story name='asUserItem'>
<Box maxWidth={330}>
<Option>
<Option.Avatar>
<Avatar url={exampleAvatar} size='x28' />
</Option.Avatar>
<Option.Column><StatusBullet status='online' /></Option.Column>
<Option.Content>
<Box withTruncatedText fontScale='p1'>carla.culhane <Box is='span' color='neutral-500'>(carla hune)</Box></Box>
</Option.Content>
<Option.Menu><Menu options={menuOptions} /></Option.Menu>
</Option>
</Box>
</Story>
</Canvas>
## As Skeleton
<Canvas>
<Story name='Skeleton'>
<Box position='relative' maxWidth={330}>
<Option.Skeleton />
</Box>
</Story>
</Canvas>
<ArgsTable of={Option} />
import React from 'react';
import { Icon } from '../../Icon';
import { Skeleton } from '../../Skeleton';
const OptionColumn = (props) => (
<div className='rcx-option__column' {...props} />
);
const OptionContent = (props) => (
<div className='rcx-option__content' {...props} />
);
const OptionAvatar = (props) => (
<div className='rcx-option__avatar' {...props} />
);
const OptionDescription = (props) => (
<div className='rcx-option__description' {...props} />
);
const OptionIcon = ({ name }) => (
<OptionColumn>
<Icon size='x16' name={name} />
</OptionColumn>
);
const OptionSkeleton = (props) => {
return (
<Option {...props}>
<Option.Avatar>
<Skeleton variant='rect' width={28} height={28} />
</Option.Avatar>
<Option.Content>
<Skeleton width='100%' />
</Option.Content>
</Option>
);
};
export const OptionMenu = (props) => (
<div className='rcx-box--animated rcx-option__menu-wraper' {...props} />
);
export const Option = React.memo(
({
is: Tag = 'li',
id,
presence,
children,
label,
focus,
selected,
className,
ref,
icon,
avatar,
...options
}) => (
<Tag
key={id}
id={id}
ref={ref}
aria-selected={selected}
{...options}
className={[
'rcx-option',
className,
focus && 'rcx-option--focus',
selected && 'rcx-option--selected',
]
.filter(Boolean)
.join(' ')}
>
<div className='rcx-option__wrapper'>
{avatar && <Option.Avatar>{avatar}</Option.Avatar>}
{icon && <Option.Icon name={icon} />}
{label && <Option.Content>{label}</Option.Content>}
{label !== children && children}
</div>
</Tag>
)
);
Option.Description = OptionDescription;
Option.Skeleton = OptionSkeleton;
Option.Avatar = OptionAvatar;
Option.Menu = OptionMenu;
Option.Icon = OptionIcon;
Option.Column = OptionColumn;
Option.Content = OptionContent;
import React from 'react';
import ReactDOM from 'react-dom';
import { Option } from '.';
it('Option renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<Option />, div);
ReactDOM.unmountComponentAtNode(div);
});
import { Meta, Canvas, ArgsTable, Story } from '@storybook/addon-docs/blocks';
import { Options, CheckOption, Option } from '.';
import { Options, CheckOption } from '.';
import { Box } from '..'
import { Option } from './Option';
export const options = [
[1, 'a teste 1'],
......@@ -10,7 +11,7 @@ export const options = [
[4, 'd testeadsasdasdasdasdjhasjfhasdkjfhaskdfjhkasjdfhkasjdhfkasjdhfkasjdhfkasjdhfkasdjhfkasdjhfaksjdfhkasjdh 4'],
];
<Meta title='Misc/Options' parameters={{ jest: ['Options/spec'] }} />
<Meta title='Misc/Options/Options' parameters={{ jest: ['Options/spec'] }} />
# Options
......
......@@ -2,13 +2,12 @@ import {
useMutableCallback,
useDebouncedState,
} from '@rocket.chat/fuselage-hooks';
import React, { useLayoutEffect, useState, forwardRef, useMemo } from 'react';
import React, { useLayoutEffect, useState, useMemo } from 'react';
import { AnimatedVisibility, Box, Scrollable } from '../Box';
import { CheckBox } from '../CheckBox';
import { Icon } from '../Icon';
import Margins from '../Margins';
import { Tile } from '../Tile';
import { Option } from './Option';
export const ACTIONS = {
ESC: 27,
......@@ -25,53 +24,6 @@ const prevent = (e) => {
e.stopPropagation();
};
const Li = forwardRef(function Li({ children, ...props }, ref) {
return (
<Box rcx-option withTruncatedText is='li' ref={ref} {...props}>
<Box withTruncatedText display='flex' alignItems='center' mi='neg-x4'>
<Margins inline='x4'>{children}</Margins>
</Box>
</Box>
);
});
export const Option = React.memo(
({
id,
avatar,
children,
label = children,
focus,
selected,
icon,
className,
...options
}) => (
<Li
key={id}
rcx-option--focus={focus}
id={id}
rcx-option--selected={selected}
aria-selected={selected}
{...options}
>
{avatar}
{icon && <Icon size='x16' name={icon} />}{' '}
<Box
is='span'
className={className}
withTruncatedText
flexGrow={1}
fontScale='p1'
color='default'
>
{label}
</Box>
{label !== children && children}
</Li>
)
);
export const Empty = React.memo(() => <Option color='hint' label='Empty' />);
export const CheckOption = React.memo(
......
......@@ -4,23 +4,79 @@
.rcx-option {
@include clickable;
@include typography.use-font-scale(p2);
@include typography.use-text-ellipsis;
@include typography.use-font-scale(p1);
padding: lengths.padding(4) lengths.padding(16);
list-style: none;
white-space: nowrap;
&__wrapper {
display: flex;
align-items: center;
margin-inline: lengths.margin(-4);
}
&:hover,
&--focus {
background: colors.neutral(400);
background: colors.neutral(100);
}
&--selected {
background: colors.neutral(500);
}
&:hover &__menu-wraper,
&.focus-within &__menu-wraper,
&:focus-within &__menu-wraper {
display: flex;
align-items: center;
width: lengths.size(28);
opacity: 1;
}
&__menu-wraper {
flex-shrink: 0;
width: 0;
height: 100%;
opacity: 0;
}
}
%column {
flex: 0 0 auto;
margin-inline: lengths.margin(4);
}
.rcx-option__avatar {
@extend %column;
}
.rcx-option__content {
@include typography.use-text-ellipsis;
@extend %column;
flex: 1 1 100%;
white-space: nowrap;
}
.rcx-option__column {
@extend %column;
display: flex;
}
.rcx-option__description {
@include typography.use-font-scale(p1);
@extend %column;
display: inline;
color: colors.foreground(hint);
}
.rcx-options:hover {
......
......@@ -23,6 +23,7 @@ export * from './Menu';
export * from './Modal';
export * from './NumberInput';
export * from './Options';
export * from './Options/Option';
export * from './Pagination';
export * from './PasswordInput';
export * from './StatusBullet';
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment