feat(twenty-front/Button): add loading state on Button (#10536)

This commit is contained in:
Antoine Moreaux
2025-03-03 11:04:32 +01:00
committed by GitHub
parent 2e4c596644
commit 51c34b77d9
19 changed files with 374 additions and 99 deletions

View File

@ -17,12 +17,12 @@ import {
useFloating,
} from '@floating-ui/react';
import { MouseEvent, ReactNode } from 'react';
import { flushSync } from 'react-dom';
import { Keys } from 'react-hotkeys-hook';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared';
import { sleep } from '~/utils/sleep';
import { useDropdown } from '../hooks/useDropdown';
import { flushSync } from 'react-dom';
const StyledDropdownFallbackAnchor = styled.div`
left: 0;

View File

@ -82,9 +82,7 @@ export const Empty: Story = {
play: async () => {
const canvas = within(document.body);
const buttons = await canvas.findAllByRole('button', {
name: 'Open Dropdown',
});
const buttons = await canvas.findAllByRole('button');
userEvent.click(buttons[0]);
await waitFor(async () => {
@ -225,16 +223,16 @@ export const WithHeaders: Story = {
<StyledDropdownMenuSubheader>Subheader 1</StyledDropdownMenuSubheader>
<DropdownMenuItemsContainer hasMaxHeight>
<>
{optionsMock.slice(0, 3).map(({ name }) => (
<MenuItem text={name} />
{optionsMock.slice(0, 3).map((item) => (
<MenuItem key={item.id} text={item.name} />
))}
</>
</DropdownMenuItemsContainer>
<DropdownMenuSeparator />
<StyledDropdownMenuSubheader>Subheader 2</StyledDropdownMenuSubheader>
<DropdownMenuItemsContainer>
{optionsMock.slice(3).map(({ name }) => (
<MenuItem text={name} />
{optionsMock.slice(3).map((item) => (
<MenuItem key={item.id} text={item.name} />
))}
</DropdownMenuItemsContainer>
</>
@ -282,7 +280,7 @@ export const WithInput: Story = {
<DropdownMenuSeparator />
<DropdownMenuItemsContainer hasMaxHeight>
{optionsMock.map(({ name }) => (
<MenuItem text={name} />
<MenuItem key={name} text={name} />
))}
</DropdownMenuItemsContainer>
</>

View File

@ -1,3 +1,4 @@
import { expect } from '@storybook/jest';
import { Meta, StoryObj } from '@storybook/react';
import { within } from '@storybook/test';
@ -31,6 +32,12 @@ export const Default: Story = {
const canvas = within(canvasElement);
sleep(1000);
await canvas.findByRole('button', { name: 'View billing details' });
const buttons = await canvas.findAllByRole('button');
expect(
buttons.findIndex((button) =>
button.outerHTML.includes('View billing details'),
),
).toBeGreaterThan(-1);
},
};

View File

@ -1,3 +1,4 @@
import { expect } from '@storybook/jest';
import { Meta, StoryObj } from '@storybook/react';
import { within } from '@storybook/test';
@ -30,6 +31,10 @@ export const Default: Story = {
await sleep(1000);
await canvas.getByRole('button', { name: 'Copy link' });
const buttons = await canvas.getAllByRole('button');
expect(
buttons.findIndex((button) => button.outerHTML.includes('Copy link')),
).toBeGreaterThan(-1);
},
};

View File

@ -28,7 +28,7 @@ describe('formatDateString', () => {
it('should format date as relative when displayAsRelativeDate is true', () => {
const mockDate = DateTime.now().minus({ months: 2 }).toISO();
const mockRelativeDate = '2 months ago';
const mockRelativeDate = 'about 2 months ago';
jest.mock('@/localization/utils/formatDateISOStringToRelativeDate', () => ({
formatDateISOStringToRelativeDate: jest

View File

@ -30,7 +30,7 @@ describe('formatDateTimeString', () => {
it('should format date as relative when displayAsRelativeDate is true', () => {
const mockDate = DateTime.now().minus({ months: 2 }).toISO();
const mockRelativeDate = '2 months ago';
const mockRelativeDate = 'about 2 months ago';
jest.mock('@/localization/utils/formatDateISOStringToRelativeDate', () => ({
formatDateISOStringToRelativeDate: jest