Skip to content

Commit

Permalink
Merge pull request #31 from kubit-ui/feature/new-components-and-impro…
Browse files Browse the repository at this point in the history
…vements

Feature/new components and improvements
  • Loading branch information
kubit-ui authored Oct 12, 2024
2 parents 72ad973 + 80ddd4a commit 5e8e0f1
Show file tree
Hide file tree
Showing 203 changed files with 3,280 additions and 805 deletions.
65 changes: 32 additions & 33 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@kubit-ui-web/react-components",
"version": "1.13.2",
"version": "1.14.0",
"description": "Kubit React Components is a customizable, accessible library of React web components, designed to enhance your application's user experience",
"author": {
"name": "Kubit",
Expand Down Expand Up @@ -86,60 +86,60 @@
"sideEffects": false,
"license": "Apache-2.0",
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.4",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@eslint/compat": "^1.1.1",
"@babel/core": "^7.25.8",
"@babel/preset-env": "^7.25.8",
"@babel/preset-react": "^7.25.7",
"@babel/preset-typescript": "^7.25.7",
"@eslint/compat": "^1.2.0",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.11.1",
"@storybook/addon-a11y": "^8.3.2",
"@storybook/addon-controls": "^8.3.2",
"@eslint/js": "^9.12.0",
"@storybook/addon-a11y": "^8.3.5",
"@storybook/addon-controls": "^8.3.5",
"@storybook/addon-coverage": "^1.0.4",
"@storybook/addon-essentials": "^8.3.2",
"@storybook/addon-interactions": "^8.3.2",
"@storybook/addon-links": "^8.3.2",
"@storybook/addon-themes": "^8.3.2",
"@storybook/blocks": "^8.3.2",
"@storybook/react": "^8.3.2",
"@storybook/react-vite": "^8.3.2",
"@storybook/addon-essentials": "^8.3.5",
"@storybook/addon-interactions": "^8.3.5",
"@storybook/addon-links": "^8.3.5",
"@storybook/addon-themes": "^8.3.5",
"@storybook/blocks": "^8.3.5",
"@storybook/react": "^8.3.5",
"@storybook/react-vite": "^8.3.5",
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.1",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.5.2",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/jest": "^29.5.13",
"@types/jest-axe": "^3.5.9",
"@types/mocha": "^10.0.8",
"@types/react": "^18.3.8",
"@types/mocha": "^10.0.9",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.0",
"@types/styled-components": "^5.1.34",
"@types/ungap__structured-clone": "^1.2.0",
"@typescript-eslint/eslint-plugin": "^8.7.0",
"@typescript-eslint/parser": "^8.7.0",
"@typescript-eslint/eslint-plugin": "^8.8.1",
"@typescript-eslint/parser": "^8.8.1",
"@ungap/structured-clone": "^1.2.0",
"@vitejs/plugin-react": "^4.3.1",
"@vitejs/plugin-react": "^4.3.2",
"babel-jest": "^29.7.0",
"cpy-cli": "^5.0.0",
"eslint": "^9.11.1",
"eslint": "^9.12.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard-with-typescript": "^43.0.1",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.30.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jest": "^28.8.3",
"eslint-plugin-jsx-a11y": "^6.10.0",
"eslint-plugin-n": "^17.10.3",
"eslint-plugin-n": "^17.11.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "5.2.1",
"eslint-plugin-promise": "^7.1.0",
"eslint-plugin-react": "^7.36.1",
"eslint-plugin-react": "^7.37.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.12",
"eslint-plugin-storybook": "^0.8.0",
"eslint-plugin-storybook": "^0.9.0",
"eslint-plugin-unused-imports": "^4.1.4",
"globals": "^15.9.0",
"globals": "^15.11.0",
"gts": "^5.3.1",
"html-validate": "^8.23.0",
"html-validate": "^8.24.1",
"jest": "^29.7.0",
"jest-axe": "^9.0.0",
"jest-canvas-mock": "^2.5.2",
Expand All @@ -151,13 +151,12 @@
"prettier": "^3.3.3",
"react-transition-group": "^4.4.5",
"sort-imports": "^1.1.0",
"storybook": "^8.3.2",
"storybook": "^8.3.5",
"ts-jest": "^29.2.5",
"tsc-alias": "1.8.10",
"typedoc": "^0.26.7",
"typedoc-plugin-markdown": "^4.2.8",
"typescript": "^5.6.2",
"vite": "^5.4.7",
"typedoc": "^0.26.8",
"typescript": "^5.6.3",
"vite": "^5.4.8",
"vite-tsconfig-paths": "^4.3.2",
"yarn-deduplicate": "^6.0.2"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@ import * as React from 'react';
import { axe } from 'jest-axe';

import { renderProvider } from '@/tests/renderProvider/renderProvider.utility';
import { windowMatchMedia } from '@/tests/windowMatchMedia';

import { ActionBottomSheetUnControlled as ActionBottomSheet } from '../actionBottomSheetUnControlled';

window.matchMedia = windowMatchMedia();

describe('ActionBottomSheet component', () => {
it('Should render ActionBottomSheet component', async () => {
const { container } = renderProvider(
Expand Down Expand Up @@ -38,6 +35,30 @@ describe('ActionBottomSheet component', () => {
expect(results).toHaveNoViolations();
});

it('When no title is used, an aria-dialog-name should be provided', async () => {
const { container } = renderProvider(
<ActionBottomSheet
closeIcon={{ icon: 'UNICORN', ['aria-label']: 'ariaLabelButton' }}
open={true}
popover={{ ['aria-label']: 'ariaLabel' }}
variant={'DEFAULT'}
>
Hello
</ActionBottomSheet>
);

const popover = screen.getByText('Hello');
expect(popover).toBeInTheDocument();

const results = await axe(container);
expect(container).toHTMLValidate({
rules: {
'no-inline-style': 'off',
},
});
expect(results).toHaveNoViolations();
});

it('Should simulate icon onClick', async () => {
const { container } = renderProvider(
<ActionBottomSheet
Expand Down Expand Up @@ -68,12 +89,15 @@ describe('ActionBottomSheet component', () => {
title={{ content: 'title' }}
variant={'DEFAULT'}
>
Hello
Internal content
</ActionBottomSheet>
);
const triggerIcon = screen.getByLabelText('ariaLabelButton');

const internalContent = screen.getByText('Internal content');
await act(async () => {
fireEvent.keyDown(window, {
// Internal popover element fire the escape keydown
fireEvent.keyDown(internalContent, {
key: 'Escape',
code: 'Escape',
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import * as React from 'react';

import { PopoverControlled as Popover } from '@/components/popover';
import { PopoverControlled as Popover, PopoverComponentType } from '@/components/popover';
import { STYLES_NAME } from '@/constants';
import { useDeviceHeight, useId, useMediaDevice, useScrollEffect } from '@/hooks';
import { useStyles } from '@/hooks/useStyles/useStyles';
import { ErrorBoundary, FallbackComponent } from '@/provider/errorBoundary';
import { DeviceBreakpointsType } from '@/types';
import { DeviceBreakpointsType, ROLES } from '@/types';

import { ActionBottomSheetStandAlone } from './actionBottomSheetStandAlone';
import {
Expand Down Expand Up @@ -85,7 +85,7 @@ const ActionBottomSheetControlledComponent = React.forwardRef(
ref: React.ForwardedRef<HTMLDivElement> | undefined | null
): JSX.Element => {
const uniqueTitleId = useId('actionSheet-title');
const titleId = title?.id ?? uniqueTitleId;
const titleId = (title?.id ?? title?.content) ? uniqueTitleId : undefined;
const styles = useStyles<ActionBottomSheetVariantStylesType>(
STYLES_NAME.ACTION_BOTTOM_SHEET,
props.variant,
Expand All @@ -95,10 +95,13 @@ const ActionBottomSheetControlledComponent = React.forwardRef(
return (
<Popover
aria-labelledby={titleId}
aria-modal={true}
clickOverlayClose={!blocked}
component={PopoverComponentType.DIV}
dataTestId={`${props.dataTestId}Popover`}
hasBackDrop={true}
open={open}
role={ROLES.DIALOG}
trapFocusInsideModal={true}
variant={styles.popoverVariant}
{...popover}
Expand Down
6 changes: 2 additions & 4 deletions src/components/badge/__tests__/badge.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@ import * as React from 'react';
import { axe } from 'jest-axe';

import { renderProvider } from '@/tests/renderProvider/renderProvider.utility';
import { windowMatchMedia } from '@/tests/windowMatchMedia';

import { BadgeUnControlled as Badge } from '../badgeUnControlled';
import { IBadgeUnControlled } from '../types';

window.matchMedia = windowMatchMedia();

// Mocks
const mockProps: IBadgeUnControlled = {
dataTestId: 'badge-component',
Expand Down Expand Up @@ -129,7 +126,8 @@ describe('Badge component', () => {
expect(contentExpand).toBeInTheDocument();

await act(async () => {
fireEvent.keyDown(window, {
// Internal popover element fire the escape keydown
fireEvent.keyDown(contentExpand, {
key: 'Escape',
code: 'Escape',
});
Expand Down
2 changes: 2 additions & 0 deletions src/components/badge/badgeControlled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ const BagdeBoundary = <
);

/**
* @deprecated Try the new BadgeV2 component
*
* @description
* Badge component is a component that shows a badge with a number or a dot.
* @param {React.PropsWithChildren<IBadgeControlled<V>>} props
Expand Down
2 changes: 2 additions & 0 deletions src/components/badge/badgeUnControlled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ const BadgeUnControlledComponent = <
};

/**
* @deprecated Try the new BadgeV2 component
*
* @description
* Badge component is a component that shows a badge with a number or a dot.
* @param {React.PropsWithChildren<IBadgeUnControlled<V>>} props
Expand Down
106 changes: 106 additions & 0 deletions src/components/badgeV2/__tests__/badge.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { fireEvent, screen } from '@testing-library/react';
import * as React from 'react';

import { axe } from 'jest-axe';

import { renderProvider } from '@/tests/renderProvider/renderProvider.utility';

import { Badge } from '../badge';
import { IBadge } from '../types';

// Mocks
const mockProps: IBadge = {
dataTestId: 'badge-component',
variant: 'PRIMARY',
size: 'DEFAULT',
dot: {
variant: 'WITH_BORDER',
size: 'MEDIUM',
number: 23,
maxNumber: 99,
},
icon: { icon: 'CONTACTS' },
label: { content: 'Notifications' },
labelIcon: { icon: 'CHEVRON_DOWN' },
ariaLiveText: 'New notification',
['aria-label']: 'Open menu',
};

describe('Badge component', () => {
it('Should be displayed correctly', async () => {
const ref = jest.fn();
const { container } = renderProvider(<Badge ref={ref} {...mockProps} />);

const badge = screen.getByTestId(mockProps.dataTestId + 'Badge');
expect(badge).toBeInTheDocument();

const results = await axe(container);
expect(container).toHTMLValidate();
expect(results).toHaveNoViolations();
});

it('When it has a dot, the dot position is custompizable using customDotTranslate', () => {
const ref = jest.fn();
renderProvider(<Badge ref={ref} {...mockProps} customDotTranslate="translate(2px, 2px)" />);

const badge = screen.getByTestId(mockProps.dataTestId + 'Badge');
expect(badge).toBeInTheDocument();
});

it('CustomDotTranslate can also be defined via styles', () => {
const ref = jest.fn();
renderProvider(
<Badge ref={ref} {...mockProps} cts={{ customDotNumberTranslate: '"translate(2px, 2px)' }} />
);

const badge = screen.getByTestId(mockProps.dataTestId + 'Badge');
expect(badge).toBeInTheDocument();
});

it('Should be displayed correctly without label', async () => {
const { container } = renderProvider(<Badge {...mockProps} label={undefined} />);

const badge = screen.getByTestId(mockProps.dataTestId + 'Badge');
expect(badge).toBeInTheDocument();

const results = await axe(container);
expect(container).toHTMLValidate();
expect(results).toHaveNoViolations();
});

it('Should be displayed correctly with simulate onClick', () => {
renderProvider(<Badge {...mockProps} label={undefined} />);

const triggerButton = screen.getByLabelText('Open menu');
fireEvent.click(triggerButton);

const badge = screen.getByTestId(mockProps.dataTestId + 'Badge');
expect(badge).toBeInTheDocument();
});

it('Should call onClick if defined when open', async () => {
const onClick = jest.fn();
const { container, getByLabelText } = renderProvider(
<Badge {...mockProps} onClick={onClick} />
);

const triggerButton = getByLabelText('Open menu');
fireEvent.click(triggerButton);

expect(onClick).toHaveBeenCalled();

const results = await axe(container);
expect(container).toHTMLValidate();
expect(results).toHaveNoViolations();
});

it('Should be displayed correctly when simulate onBlur', () => {
renderProvider(<Badge {...mockProps} />);

const triggerButton = screen.getByLabelText('Open menu');
fireEvent.blur(triggerButton);

const badge = screen.getByTestId(mockProps.dataTestId + 'Badge');
expect(badge).toBeInTheDocument();
});
});
Loading

0 comments on commit 5e8e0f1

Please sign in to comment.