Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ src/platform/packages/private/kbn-transpose-utils @elastic/kibana-visualizations
src/platform/packages/private/kbn-ui-shared-deps-npm @elastic/kibana-operations
src/platform/packages/private/kbn-ui-shared-deps-src @elastic/kibana-operations
src/platform/packages/private/kbn-unsaved-changes-badge @elastic/kibana-data-discovery
src/platform/packages/private/kbn-split-button @elastic/kibana-data-discovery
src/platform/packages/private/kbn-validate-oas @elastic/kibana-core
src/platform/packages/private/opentelemetry/kbn-metrics @elastic/kibana-core @elastic/stack-monitoring
src/platform/packages/private/opentelemetry/kbn-metrics-config @elastic/kibana-core
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,7 @@
"@kbn/spaces-plugin": "link:x-pack/platform/plugins/shared/spaces",
"@kbn/spaces-test-plugin": "link:x-pack/platform/test/spaces_api_integration/common/plugins/spaces_test_plugin",
"@kbn/spaces-utils": "link:src/platform/packages/shared/kbn-spaces-utils",
"@kbn/split-button": "link:src/platform/packages/private/kbn-split-button",
"@kbn/sse-example-plugin": "link:examples/sse_example",
"@kbn/sse-utils": "link:src/platform/packages/shared/kbn-sse-utils",
"@kbn/sse-utils-client": "link:src/platform/packages/shared/kbn-sse-utils-client",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

module.exports = require('@kbn/storybook').defaultConfig;
3 changes: 3 additions & 0 deletions src/platform/packages/private/kbn-split-button/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @kbn/split-button

Empty package generated by @kbn/generate
10 changes: 10 additions & 0 deletions src/platform/packages/private/kbn-split-button/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export { SplitButton } from './src/split_button';
14 changes: 14 additions & 0 deletions src/platform/packages/private/kbn-split-button/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

module.exports = {
preset: '@kbn/test',
rootDir: '../../../../..',
roots: ['<rootDir>/src/platform/packages/private/kbn-split-button'],
};
7 changes: 7 additions & 0 deletions src/platform/packages/private/kbn-split-button/kibana.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "shared-common",
"id": "@kbn/split-button",
"owner": "@elastic/kibana-data-discovery",
"group": "platform",
"visibility": "private"
}
6 changes: 6 additions & 0 deletions src/platform/packages/private/kbn-split-button/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "@kbn/split-button",
"private": true,
"version": "1.0.0",
"license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import React from 'react';
import { SplitButton } from './split_button';

const DEFAULT_SECONDARY_ICON = 'clock';

export default {
title: 'Split Button',
};

export const Default = {
name: 'Default',
args: {
secondaryButtonIcon: DEFAULT_SECONDARY_ICON,
},
render: (args: { secondaryButtonIcon: string }) => <SplitButton {...args}>Default</SplitButton>,
};

export const BothIcons = {
name: 'Both icons',
args: {
secondaryButtonIcon: DEFAULT_SECONDARY_ICON,
iconType: 'search',
},
render: (args: { secondaryButtonIcon: string; iconType: string }) => (
<SplitButton {...args}>Both icons</SplitButton>
),
};

export const TextColor = {
name: 'Text color',
args: {
color: 'text',
},
render: (args: { color: React.ComponentProps<typeof SplitButton>['color'] }) => (
<SplitButton secondaryButtonIcon={DEFAULT_SECONDARY_ICON} {...args}>
Default
</SplitButton>
),
};

export const AccentColor = {
name: 'Accent color',
args: {
color: 'accent',
},
render: (args: { color: React.ComponentProps<typeof SplitButton>['color'] }) => (
<SplitButton secondaryButtonIcon={DEFAULT_SECONDARY_ICON} {...args}>
Default
</SplitButton>
),
};

export const DangerColor = {
name: 'Danger color',
args: {
color: 'danger',
},
render: (args: { color: React.ComponentProps<typeof SplitButton>['color'] }) => (
<SplitButton secondaryButtonIcon={DEFAULT_SECONDARY_ICON} {...args}>
Default
</SplitButton>
),
};

export const SuccessColor = {
name: 'Success color',
args: {
color: 'success',
},
render: (args: { color: React.ComponentProps<typeof SplitButton>['color'] }) => (
<SplitButton secondaryButtonIcon={DEFAULT_SECONDARY_ICON} {...args}>
Default
</SplitButton>
),
};

export const WarningColor = {
name: 'Warning color',
args: {
color: 'warning',
},
render: (args: { color: React.ComponentProps<typeof SplitButton>['color'] }) => (
<SplitButton secondaryButtonIcon={DEFAULT_SECONDARY_ICON} {...args}>
Default
</SplitButton>
),
};

export const MediumSize = {
name: 'Medium size',
args: {
size: 'm',
},
render: (args: { size: React.ComponentProps<typeof SplitButton>['size'] }) => (
<SplitButton secondaryButtonIcon={DEFAULT_SECONDARY_ICON} {...args}>
Medium size
</SplitButton>
),
};

export const SmallSize = {
name: 'Small size',
args: {
size: 's',
},
render: (args: { size: React.ComponentProps<typeof SplitButton>['size'] }) => (
<SplitButton secondaryButtonIcon={DEFAULT_SECONDARY_ICON} {...args}>
Small size
</SplitButton>
),
};

export const Disabled = {
name: 'Disabled',
args: {
isDisabled: true,
disabled: true,
},
render: (args: { isDisabled: boolean; disabled: boolean }) => (
<SplitButton secondaryButtonIcon={DEFAULT_SECONDARY_ICON} {...args}>
Small size
</SplitButton>
),
};

export const AllLoading = {
name: 'All loading',
args: {
isLoading: true,
isMainButtonLoading: true,
isSecondaryButtonLoading: true,
},
render: (args: {
isLoading: boolean;
isMainButtonLoading: boolean;
isSecondaryButtonLoading: boolean;
}) => (
<SplitButton secondaryButtonIcon={DEFAULT_SECONDARY_ICON} {...args}>
Small size
</SplitButton>
),
};

export const MainButtonLoading = {
name: 'Main button loading',
args: {
isLoading: false,
isMainButtonLoading: true,
isSecondaryButtonLoading: false,
},
render: (args: {
isLoading: boolean;
isMainButtonLoading: boolean;
isSecondaryButtonLoading: boolean;
}) => (
<SplitButton secondaryButtonIcon={DEFAULT_SECONDARY_ICON} {...args}>
Small size
</SplitButton>
),
};

export const SecondaryButtonLoading = {
name: 'Secondary button loading',
args: {
isLoading: false,
isMainButtonLoading: false,
isSecondaryButtonLoading: true,
},
render: (args: {
isLoading: boolean;
isMainButtonLoading: boolean;
isSecondaryButtonLoading: boolean;
}) => (
<SplitButton secondaryButtonIcon={DEFAULT_SECONDARY_ICON} {...args}>
Small size
</SplitButton>
),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { render, screen } from '@testing-library/react';
import { SplitButton } from './split_button';
import React from 'react';
import userEvent from '@testing-library/user-event';

const setup = (props: Partial<React.ComponentProps<typeof SplitButton>> = {}) => {
const secondaryButtonIcon = 'clock';
const onMainButtonClick = jest.fn();
const onSecondaryButtonClick = jest.fn();

const user = userEvent.setup();

render(
<SplitButton
data-test-subj="split-button"
onClick={onMainButtonClick}
onSecondaryButtonClick={onSecondaryButtonClick}
secondaryButtonIcon={secondaryButtonIcon}
{...props}
/>
);

return {
secondaryButtonIcon,
onMainButtonClick,
onSecondaryButtonClick,
user,
};
};

describe('<SplitButton />', () => {
describe('given a primary icon', () => {
it('should render the primary button icon', () => {
// Given
const primaryButtonIcon = 'plus';
setup({ iconType: primaryButtonIcon });

// When
const primaryButton = screen.getByTestId('split-button-primary-button');

// Then
expect(primaryButton).toBeVisible();
expect(primaryButton).toHaveAttribute('data-icon', primaryButtonIcon);
});
});

describe('given a secondary icon', () => {
it('should render the secondary button icon', () => {
// Given
const secondaryButtonIcon = 'clock';

// When
setup({ secondaryButtonIcon });

// Then
const secondaryButton = screen.getByTestId('split-button-secondary-button');
expect(secondaryButton).toBeVisible();
expect(secondaryButton).toHaveAttribute('data-icon', secondaryButtonIcon);
});
});

describe('when the primary button is clicked', () => {
it('should call the onClick handler', async () => {
// Given
const { user, onMainButtonClick } = setup();

// When
const primaryButton = screen.getByTestId('split-button-primary-button');
await user.click(primaryButton);

// Then
expect(onMainButtonClick).toHaveBeenCalled();
});
});

describe('when the secondary button is clicked', () => {
it('should call the onSecondaryButtonClick handler', async () => {
// Given
const { user, onSecondaryButtonClick } = setup();

// When
const secondaryButton = screen.getByTestId('split-button-secondary-button');
await user.click(secondaryButton);

// Then
expect(onSecondaryButtonClick).toHaveBeenCalled();
});
});
});
Loading