Repository: melt-ui/melt-ui
Pull request #767 (2023-11-24 20:37:11)

Slider: add `data-value` attribute to `tick` and `thumb`
This PR adds the `data-value` attributes to the `tick`. This improves customizability, like only showing certain ticks, for example. I also added `data-value` to the `thumb` for consistency (I'm aware `aria-valuenow` exists, just thought it'd be nice to be consistent).

changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: 70c24cdae337b1b88ae7baec6595950ef3d59948

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/abdel-17/melt-ui/new/feat/enhance-slider?filename=.changeset/thirty-poets-boil.md&value=---%0A%22%40melt-ui%2Fsvelte%22%3A%20patch%0A---%0A%0ASlider%3A%20add%20%60data-value%60%20attribute%20to%20%60tick%60%20and%20%60thumb%60%0A)



Patch:
diff --git a/.changeset/clever-bananas-cheer.md b/.changeset/clever-bananas-cheer.md
new file mode 100644
index 00000000..db602e72
--- /dev/null
+++ b/.changeset/clever-bananas-cheer.md
@@ -0,0 +1,5 @@
+---
+"@melt-ui/svelte": patch
+---
+
+Popover: Fix trigger not toggling the `open` state (closes #763)
diff --git a/.changeset/serious-fireants-tickle.md b/.changeset/serious-fireants-tickle.md
new file mode 100644
index 00000000..1b03eb41
--- /dev/null
+++ b/.changeset/serious-fireants-tickle.md
@@ -0,0 +1,5 @@
+---
+"@melt-ui/svelte": patch
+---
+
+Fix: `aria-disabled` attr types (closes #764)
diff --git a/src/docs/content/builders/dialog.md b/src/docs/content/builders/dialog.md
index a05f4fd7..bbb28684 100644
--- a/src/docs/content/builders/dialog.md
+++ b/src/docs/content/builders/dialog.md
@@ -27,7 +27,7 @@ At a high level, the anatomy of a dialog looks like this:
 
 <button use:melt={$trigger}> Open Dialog </button>
 
-<div use:portal>
+<div use:melt={$portalled}>
 	{#if $open}
 		<div use:melt={$overlay} />
 		<div use:melt={$content}>
diff --git a/src/docs/data/builders/menu.ts b/src/docs/data/builders/menu.ts
index 0ca3c463..70bd252e 100644
--- a/src/docs/data/builders/menu.ts
+++ b/src/docs/data/builders/menu.ts
@@ -91,6 +91,18 @@ function getMenuBuilderEls(name = 'menu') {
 			name: 'arrow',
 			description: `The builder store used to create the ${name} arrow.`,
 		},
+		{
+			name: 'item',
+			description: `The builder store used to create the ${name} item`,
+		},
+		{
+			name: 'group',
+			description: `The builder store used to group menu items together. It takes in a unique key to group menu items together.`,
+		},
+		{
+			name: 'groupLabel',
+			description: `The builder store used to create the group label for the ${name}.`,
+		},
 	];
 }
 
diff --git a/src/docs/data/builders/slider.ts b/src/docs/data/builders/slider.ts
index ef4a57b9..dec04872 100644
--- a/src/docs/data/builders/slider.ts
+++ b/src/docs/data/builders/slider.ts
@@ -130,6 +130,10 @@ const thumb = elementSchema('thumb', {
 			name: 'data-melt-slider-thumb',
 			value: ATTRS.MELT('slider thumb'),
 		},
+		{
+			name: 'data-value',
+			value: 'The current value of the thumb.',
+		},
 	],
 	events: sliderEvents['thumb'],
 });
@@ -141,9 +145,13 @@ const tick = elementSchema('tick', {
 			name: 'data-melt-slider-tick',
 			value: ATTRS.MELT('slider tick'),
 		},
+		{
+			name: 'data-value',
+			value: "The value at the tick's position.",
+		},
 		{
 			name: 'data-bounded',
-			value: "Present when a tick is inside the `value`'s bounds.",
+			value: 'Present when the tick is inside the active range.',
 		},
 	],
 });
diff --git a/src/lib/builders/popover/create.ts b/src/lib/builders/popover/create.ts
index 01833f03..29cd6ceb 100644
--- a/src/lib/builders/popover/create.ts
+++ b/src/lib/builders/popover/create.ts
@@ -8,6 +8,7 @@ import {
 	getPortalDestination,
 	handleFocus,
 	isBrowser,
+	isElement,
 	isHTMLElement,
 	kbd,
 	noop,
@@ -139,7 +140,9 @@ export function createPopover(args?: CreatePopoverProps) {
 								  },
 							clickOutside: $closeOnOutsideClick
 								? {
-										handler: () => {
+										handler: (e) => {
+											const target = e.target;
+											if (isElement(target) && target.id === get(ids.trigger)) return;
 											handleClose();
 										},
 								  }
diff --git a/src/lib/builders/slider/create.ts b/src/lib/builders/slider/create.ts
index 54aacf4e..7bc01e49 100644
--- a/src/lib/builders/slider/create.ts
+++ b/src/lib/builders/slider/create.ts
@@ -172,13 +172,15 @@ export const createSlider = (props?: CreateSliderProps) => {
 					currentThumbIndex.update((prev) => prev + 1);
 				}
 
-				const thumbPosition = `${$position($value[index])}%`;
+				const thumbValue = $value[index];
+				const thumbPosition = `${$position(thumbValue)}%`;
 				return {
 					role: 'slider',
 					'aria-valuemin': $min,
 					'aria-valuemax': $max,
-					'aria-valuenow': $value[index],
+					'aria-valuenow': thumbValue,
 					'data-melt-part': 'thumb',
+					'data-value': thumbValue,
 					style: styleToString({
 						position: 'absolute',
 						...($orientation === 'horizontal'
@@ -327,6 +329,7 @@ export const createSlider = (props?: CreateSliderProps) => {
 
 				return {
 					'data-bounded': bounded ? true : undefined,
+					'data-value': tickValue,
 					style: styleToString(style),
 				};
 			};
@@ -460,7 +463,7 @@ export const createSlider = (props?: CreateSliderProps) => {
 
 		if ($value.some((v) => !isValidValue(v))) {
 			value.update((prev) => {
-				return [...prev].map(gcv);
+				return prev.map(gcv);
 			});
 		}
 	});
diff --git a/src/lib/internal/helpers/attr.ts b/src/lib/internal/helpers/attr.ts
index c070e0a6..0f551426 100644
--- a/src/lib/internal/helpers/attr.ts
+++ b/src/lib/internal/helpers/attr.ts
@@ -5,7 +5,7 @@ export function disabledAttr(disabled: boolean | undefined) {
 }
 
 export function ariaDisabledAttr(disabled: boolean | undefined) {
-	return disabled ? 'true' : undefined;
+	return disabled ? ('true' as const) : undefined;
 }
 
 export const hiddenInputAttrs = {


Test patch:
diff --git a/src/tests/popover/Popover.spec.ts b/src/tests/popover/Popover.spec.ts
index b4f83388..ed5cf928 100644
--- a/src/tests/popover/Popover.spec.ts
+++ b/src/tests/popover/Popover.spec.ts
@@ -57,6 +57,16 @@ describe('Popover (Default)', () => {
 		await waitFor(() => expect(content).not.toBeVisible());
 	});
 
+	test('Toggles open state on trigger click', async () => {
+		const { content, trigger, user } = setup();
+
+		expect(content).not.toBeVisible();
+		await user.click(trigger);
+		await waitFor(() => expect(content).toBeVisible());
+		await user.click(trigger);
+		await waitFor(() => expect(content).not.toBeVisible());
+	});
+
 	test('Respects `openFocus` prop', async () => {
 		const { content, trigger, user, getByTestId } = setup({
 			openFocus: () => {