Skip to content

Commit 8fe5964

Browse files
committed
feat(tasty): mod values support
1 parent 7574a2c commit 8fe5964

File tree

24 files changed

+950
-529
lines changed

24 files changed

+950
-529
lines changed

.changeset/value-mods.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@cube-dev/ui-kit': major
3+
---
4+
5+
**BREAKING:** Boolean mods now generate `data-*` instead of `data-is-*` attributes (`mods={{ hovered: true }}``data-hovered=""` instead of `data-is-hovered=""`).
6+
7+
**NEW:** Value mods support - `mods` now accepts string values (`mods={{ theme: 'danger' }}``data-theme="danger"`). Includes shorthand syntax in styles (`theme=danger`, `theme="danger"`). See Tasty documentation for details.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ coverage
1717
size-limit-report/stats.json
1818
docs-static
1919
*.plan.md
20+
*.spec.md

src/components/actions/Button/button.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@ describe('<Button />', () => {
1111
expect(screen.getByTestId('test')).toBeInTheDocument();
1212
});
1313

14-
it('should have data-is-loading', () => {
14+
it('should have data-loading', () => {
1515
render(
1616
<Button isLoading data-qa="ApplyDbConnection">
1717
Apply
1818
</Button>,
1919
);
2020

2121
expect(screen.getByTestId('ApplyDbConnection')).toHaveAttribute(
22-
'data-is-loading',
22+
'data-loading',
2323
'',
2424
);
2525
});
2626

27-
it('should have data-is-loading after rerender', () => {
27+
it('should have data-loading after rerender', () => {
2828
const { rerender } = render(
2929
<Button isLoading={false} data-qa="ApplyDbConnection">
3030
Apply
@@ -38,7 +38,7 @@ describe('<Button />', () => {
3838
);
3939

4040
expect(screen.getByTestId('ApplyDbConnection')).toHaveAttribute(
41-
'data-is-loading',
41+
'data-loading',
4242
'',
4343
);
4444
});

src/components/actions/CommandMenu/CommandMenu.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,7 @@ describe('CommandMenu', () => {
859859
);
860860

861861
const commandMenu = screen.getByTestId('test-command-menu');
862-
expect(commandMenu).toHaveAttribute('data-is-popover');
862+
expect(commandMenu).toHaveAttribute('data-popover');
863863
});
864864

865865
it('should apply tray mod when used with MenuTrigger', () => {
@@ -875,7 +875,7 @@ describe('CommandMenu', () => {
875875
);
876876

877877
const commandMenu = screen.getByTestId('test-command-menu');
878-
expect(commandMenu).toHaveAttribute('data-is-tray');
878+
expect(commandMenu).toHaveAttribute('data-tray');
879879
});
880880

881881
it('should not apply any special mods when used standalone', () => {
@@ -887,8 +887,8 @@ describe('CommandMenu', () => {
887887
);
888888

889889
const commandMenu = screen.getByTestId('test-command-menu');
890-
expect(commandMenu).not.toHaveAttribute('data-is-popover');
891-
expect(commandMenu).not.toHaveAttribute('data-is-tray');
890+
expect(commandMenu).not.toHaveAttribute('data-popover');
891+
expect(commandMenu).not.toHaveAttribute('data-tray');
892892
});
893893
});
894894
});

src/components/actions/Menu/Menu.test.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ describe('<Menu />', () => {
556556
);
557557

558558
// With first strategy, first menu item gets focus
559-
const focusedItem = container.querySelector('[data-is-focused]');
559+
const focusedItem = container.querySelector('[data-focused]');
560560
expect(focusedItem).toBeInTheDocument();
561561
});
562562

@@ -568,7 +568,7 @@ describe('<Menu />', () => {
568568
);
569569

570570
// With last strategy, last menu item gets focus
571-
const focusedItem = container.querySelector('[data-is-focused]');
571+
const focusedItem = container.querySelector('[data-focused]');
572572
expect(focusedItem).toBeInTheDocument();
573573
});
574574

@@ -646,12 +646,12 @@ describe('<Menu />', () => {
646646

647647
// Check wrapper mods (header, footer are on wrapper)
648648
const menuWrapper = container.querySelector('[data-qa="Menu"]');
649-
expect(menuWrapper).toHaveAttribute('data-is-header', '');
650-
expect(menuWrapper).toHaveAttribute('data-is-footer', '');
649+
expect(menuWrapper).toHaveAttribute('data-header', '');
650+
expect(menuWrapper).toHaveAttribute('data-footer', '');
651651

652652
// Check menu list mods (sections mod is on the menu list)
653653
const menu = getByRole('menu');
654-
expect(menu).toHaveAttribute('data-is-sections', '');
654+
expect(menu).toHaveAttribute('data-sections', '');
655655
});
656656

657657
// Ref tests
@@ -1048,7 +1048,7 @@ describe('Menu popover mod', () => {
10481048
);
10491049

10501050
const menuWrapper = container.querySelector('[data-qa="Menu"]');
1051-
expect(menuWrapper).toHaveAttribute('data-is-popover');
1051+
expect(menuWrapper).toHaveAttribute('data-popover');
10521052
});
10531053

10541054
it('should not apply popover mod when used standalone', () => {
@@ -1060,7 +1060,7 @@ describe('Menu popover mod', () => {
10601060
);
10611061

10621062
const menuWrapper = container.querySelector('[data-qa="Menu"]');
1063-
expect(menuWrapper).not.toHaveAttribute('data-is-popover');
1063+
expect(menuWrapper).not.toHaveAttribute('data-popover');
10641064
});
10651065

10661066
it('should not apply popover mod when context provides false', () => {
@@ -1076,7 +1076,7 @@ describe('Menu popover mod', () => {
10761076
);
10771077

10781078
const menuWrapper = container.querySelector('[data-qa="Menu"]');
1079-
expect(menuWrapper).not.toHaveAttribute('data-is-popover');
1079+
expect(menuWrapper).not.toHaveAttribute('data-popover');
10801080
});
10811081
});
10821082

src/components/actions/Menu/SubMenuTrigger.test.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ describe('<SubMenuTrigger />', () => {
166166
// Verify Share item is focused before trying to open submenu
167167
await waitFor(() => {
168168
const shareItem = getByText('Share').closest('li');
169-
expect(shareItem).toHaveAttribute('data-is-focused');
169+
expect(shareItem).toHaveAttribute('data-focused');
170170
});
171171

172172
await act(async () => {
@@ -221,7 +221,7 @@ describe('<SubMenuTrigger />', () => {
221221
// Verify Share item is focused before trying to open submenu
222222
await waitFor(() => {
223223
const shareItem = getByText('Share').closest('li');
224-
expect(shareItem).toHaveAttribute('data-is-focused');
224+
expect(shareItem).toHaveAttribute('data-focused');
225225
});
226226

227227
await act(async () => {
@@ -279,7 +279,7 @@ describe('<SubMenuTrigger />', () => {
279279
// Verify Share item is focused before trying to open submenu
280280
await waitFor(() => {
281281
const shareItem = getByText('Share').closest('li');
282-
expect(shareItem).toHaveAttribute('data-is-focused');
282+
expect(shareItem).toHaveAttribute('data-focused');
283283
});
284284

285285
await act(async () => {
@@ -337,7 +337,7 @@ describe('<SubMenuTrigger />', () => {
337337
// Verify Share item is focused before trying to open submenu
338338
await waitFor(() => {
339339
const shareItem = getByText('Share').closest('li');
340-
expect(shareItem).toHaveAttribute('data-is-focused');
340+
expect(shareItem).toHaveAttribute('data-focused');
341341
});
342342

343343
await act(async () => {
@@ -401,7 +401,7 @@ describe('<SubMenuTrigger />', () => {
401401
// Verify Share item is focused before trying to open submenu
402402
await waitFor(() => {
403403
const shareItem = getByText('Share').closest('li');
404-
expect(shareItem).toHaveAttribute('data-is-focused');
404+
expect(shareItem).toHaveAttribute('data-focused');
405405
});
406406

407407
await act(async () => {
@@ -713,7 +713,7 @@ describe('<SubMenuTrigger />', () => {
713713
// Verify Share item is focused before trying to open submenu
714714
await waitFor(() => {
715715
const shareItem = getByText('Share').closest('li');
716-
expect(shareItem).toHaveAttribute('data-is-focused');
716+
expect(shareItem).toHaveAttribute('data-focused');
717717
});
718718

719719
await act(async () => {
@@ -731,9 +731,9 @@ describe('<SubMenuTrigger />', () => {
731731
// The actual DOM focus might be on the menu itself with aria-activedescendant
732732
const firstSubmenuItem = getByText('Copy link').closest('li');
733733

734-
// Check for focus indication - tasty sets data-is-focused based on mods.focused
734+
// Check for focus indication - tasty sets data-focused based on mods.focused
735735
await waitFor(() => {
736-
expect(firstSubmenuItem).toHaveAttribute('data-is-focused');
736+
expect(firstSubmenuItem).toHaveAttribute('data-focused');
737737
});
738738
});
739739
});

src/components/content/ActiveZone/ActiveZone.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ function ActiveZone(
5353

5454
return (
5555
<Element
56-
data-is-hovered={isHovered && !isDisabled ? '' : null}
57-
data-is-focused={isFocused && !isDisabled ? '' : null}
58-
data-is-disabled={isDisabled || null}
56+
data-hovered={isHovered && !isDisabled ? '' : null}
57+
data-focused={isFocused && !isDisabled ? '' : null}
58+
data-disabled={isDisabled || null}
5959
aria-label={label}
6060
{...mergeProps(
6161
hoverProps,

src/components/fields/ComboBox/ComboBox.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ describe('<ComboBox />', () => {
839839
);
840840

841841
await waitFor(() => {
842-
const wrapper = combobox.closest('[data-is-invalid]');
842+
const wrapper = combobox.closest('[data-invalid]');
843843
expect(wrapper).toBeInTheDocument();
844844
});
845845

@@ -852,7 +852,7 @@ describe('<ComboBox />', () => {
852852
);
853853

854854
await waitFor(() => {
855-
const wrapper = combobox.closest('[data-is-valid]');
855+
const wrapper = combobox.closest('[data-valid]');
856856
expect(wrapper).toBeInTheDocument();
857857
});
858858

src/components/fields/FilterListBox/FilterListBox.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -800,15 +800,15 @@ describe('<FilterListBox />', () => {
800800
</FilterListBox>,
801801
);
802802

803-
expect(container.firstChild).toHaveAttribute('data-is-valid');
803+
expect(container.firstChild).toHaveAttribute('data-valid');
804804

805805
rerender(
806806
<FilterListBox label="Select a fruit" validationState="invalid">
807807
{basicItems}
808808
</FilterListBox>,
809809
);
810810

811-
expect(container.firstChild).toHaveAttribute('data-is-invalid');
811+
expect(container.firstChild).toHaveAttribute('data-invalid');
812812
});
813813
});
814814

src/components/fields/FilterListBox/FilterListBox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ export const FilterListBox = forwardRef(function FilterListBox<
815815
ref={searchInputRef}
816816
qa={qa || 'FilterListBox'}
817817
id={id}
818-
data-is-prefix={isLoading ? '' : undefined}
818+
data-prefix={isLoading ? '' : undefined}
819819
type="search"
820820
placeholder={searchPlaceholder}
821821
value={searchValue}

0 commit comments

Comments
 (0)