Skip to content

Commit

Permalink
[Cases] add tooltip component to kbn-cases-components package (#148561)
Browse files Browse the repository at this point in the history
## Summary

This PR adds a tooltip component (High OrderComponent) to
@kbn/cases-components package. #146864

**Details of tooltip**


![image](https://user-images.githubusercontent.com/117571355/211531519-55c68e15-00ce-410d-9cd5-d23d4eb45287.png)

**status: Open, tooltip position : Top**


![image](https://user-images.githubusercontent.com/117571355/211530420-d0c96461-1ce5-4344-8fcf-17907a7efe61.png)

**status: In-progress, tooltip position: bottom, long title and
description**


![image](https://user-images.githubusercontent.com/117571355/211530905-2df9b768-3181-481b-8234-43875301cbb4.png)

### Checklist

Delete any items that are not applicable to this PR.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [x]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [x] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)


### How to Test:

- run `yarn storybook cases` and test on  http://localhost:9001/

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
js-jankisalvi and kibanamachine authored Jan 17, 2023
1 parent 066ee1c commit ed32d89
Show file tree
Hide file tree
Showing 17 changed files with 618 additions and 0 deletions.
1 change: 1 addition & 0 deletions .buildkite/scripts/steps/storybooks/build_and_upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import path from 'path';
const STORYBOOKS = [
'apm',
'canvas',
'cases',
'ci_composite',
'cloud_chat',
'coloring',
Expand Down
9 changes: 9 additions & 0 deletions packages/kbn-cases-components/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

module.exports = require('@kbn/storybook').defaultConfig;
31 changes: 31 additions & 0 deletions packages/kbn-cases-components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,34 @@ import { Status, CaseStatuses } from '@kbn/cases-components';
<Status status={CaseStatuses.open} />
```

### Tooltip

The component renders the tooltip with case details on hover of an Element. Usage:

```
import { Tooltip, CaseStatuses } from '@kbn/cases-components';
import type { CaseTooltipContentProps, CaseTooltipProps } from '@kbn/cases-components';
const tooltipContent: CaseTooltipContentProps = {
title: 'Case title',
description: 'Case description',
createdAt: '2020-02-19T23:06:33.798Z',
createdBy: {
fullName: 'Elastic User',
username: 'elastic',
},
totalComments: 1,
status: CaseStatuses.open,
}
const tooltipProps: CaseTooltipProps = {
loading: false,
content: tooltipContent,
className: 'customClass',
};
<Tooltip {...tooltipProps}>
<span>This is a demo span</span>
</Tooltip>
```
2 changes: 2 additions & 0 deletions packages/kbn-cases-components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@
export { Status } from './src/status/status';
export { CaseStatuses } from './src/status/types';
export { getStatusConfiguration } from './src/status/config';
export { Tooltip } from './src/tooltip/tooltip';
export type { CaseTooltipProps, CaseTooltipContentProps } from './src/tooltip/types';
103 changes: 103 additions & 0 deletions packages/kbn-cases-components/src/__stories__/tooltip.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import { I18nProvider } from '@kbn/i18n-react';
import { ComponentStory, ComponentMeta } from '@storybook/react';

import { CaseStatuses } from '../status/types';
import { Tooltip } from '../tooltip/tooltip';
import type { CaseTooltipProps, CaseTooltipContentProps } from '../tooltip/types';

const sampleText = 'This is a test span element!!';
const TestSpan = () => (
<a href="https://www.elastic.co/">
<span data-test-subj="sample-span">{sampleText}</span>
</a>
);

const tooltipContent: CaseTooltipContentProps = {
title: 'Unusual process identified',
description: 'There was an unusual process while adding alerts to existing case.',
createdAt: '2020-02-19T23:06:33.798Z',
createdBy: {
fullName: 'Elastic User',
username: 'elastic',
},
totalComments: 10,
status: CaseStatuses.open,
};

const tooltipProps: CaseTooltipProps = {
children: TestSpan,
loading: false,
content: tooltipContent,
};

const longTitle = `Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry standard dummy text ever since the 1500s!! Lorem!!!`;

const longDescription = `Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer
took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries,
but also the leap into electronic typesetting, remaining essentially unchanged.`;

const Template = (args: CaseTooltipProps) => (
<I18nProvider>
<Tooltip {...args}>
<TestSpan />
</Tooltip>
</I18nProvider>
);

export default {
title: 'CaseTooltip',
component: Template,
} as ComponentMeta<typeof Template>;

export const Default: ComponentStory<typeof Template> = Template.bind({});
Default.args = { ...tooltipProps };

export const LoadingState: ComponentStory<typeof Template> = Template.bind({});
LoadingState.args = { ...tooltipProps, loading: true };

export const LongTitle: ComponentStory<typeof Template> = Template.bind({});
LongTitle.args = { ...tooltipProps, content: { ...tooltipContent, title: longTitle } };

export const LongDescription: ComponentStory<typeof Template> = Template.bind({});
LongDescription.args = {
...tooltipProps,
content: { ...tooltipContent, description: longDescription },
};

export const InProgressStatus: ComponentStory<typeof Template> = Template.bind({});
InProgressStatus.args = {
...tooltipProps,
content: { ...tooltipContent, status: CaseStatuses['in-progress'] },
};

export const ClosedStatus: ComponentStory<typeof Template> = Template.bind({});
ClosedStatus.args = {
...tooltipProps,
content: { ...tooltipContent, status: CaseStatuses.closed },
};

export const NoUserInfo: ComponentStory<typeof Template> = Template.bind({});
NoUserInfo.args = { ...tooltipProps, content: { ...tooltipContent, createdBy: {} } };

export const FullName: ComponentStory<typeof Template> = Template.bind({});
FullName.args = {
...tooltipProps,
content: { ...tooltipContent, createdBy: { fullName: 'Elastic User' } },
};

export const LongUserName: ComponentStory<typeof Template> = Template.bind({});
LongUserName.args = {
...tooltipProps,
content: { ...tooltipContent, createdBy: { fullName: 'LoremIpsumElasticUser WithALongSurname' } },
};
26 changes: 26 additions & 0 deletions packages/kbn-cases-components/src/tooltip/icon_with_count.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import { render } from '@testing-library/react';

import { IconWithCount } from './icon_with_count';

describe('IconWithCount', () => {
it('renders component correctly', () => {
const res = render(<IconWithCount count={5} icon={'editorComment'} />);

expect(res.getByTestId('comment-count-icon')).toBeInTheDocument();
});

it('renders count correctly', () => {
const res = render(<IconWithCount count={100} icon={'editorComment'} />);

expect(res.getByText(100)).toBeInTheDocument();
});
});
31 changes: 31 additions & 0 deletions packages/kbn-cases-components/src/tooltip/icon_with_count.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText } from '@elastic/eui';
import React from 'react';

export const IconWithCount = React.memo<{
count: number;
icon: string;
}>(({ count, icon }) => (
<EuiFlexGroup alignItems="center" gutterSize="none" css={{ marginLeft: 'auto', flexGrow: 0 }}>
<EuiFlexItem grow={false}>
<EuiIcon
css={{ marginRight: '4px' }}
size="s"
type={icon}
data-test-subj="comment-count-icon"
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText size="xs">{count}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
));

IconWithCount.displayName = 'IconWithCount';
25 changes: 25 additions & 0 deletions packages/kbn-cases-components/src/tooltip/skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import { EuiFlexItem, EuiLoadingContent, EuiHorizontalRule, EuiSpacer } from '@elastic/eui';

const SkeletonComponent: React.FC = () => {
return (
<EuiFlexItem css={{ width: 240 }} data-test-subj="tooltip-loading-content">
<EuiLoadingContent lines={1} css={{ width: 70, marginBottom: '12px' }} />
<EuiLoadingContent lines={3} />
<EuiHorizontalRule margin="xs" />
<EuiSpacer size="s" />
</EuiFlexItem>
);
};

SkeletonComponent.displayName = 'Skeleton';

export const Skeleton = SkeletonComponent;
Loading

0 comments on commit ed32d89

Please sign in to comment.