From 4dbaab76b694f1f90893c593f3aaf94163bdcfd4 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 17:50:21 -0800 Subject: [PATCH 01/49] Fix escape key and restoring focus --- packages/dev/s2-docs/src/ComponentCardView.tsx | 1 + packages/dev/s2-docs/src/SearchMenuTrigger.tsx | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/dev/s2-docs/src/ComponentCardView.tsx b/packages/dev/s2-docs/src/ComponentCardView.tsx index d8b106d5500..07eec383ff6 100644 --- a/packages/dev/s2-docs/src/ComponentCardView.tsx +++ b/packages/dev/s2-docs/src/ComponentCardView.tsx @@ -34,6 +34,7 @@ export function ComponentCardView({items, ariaLabel = 'Items', size = 'S', curre linkBehavior="override" autoFocus={!!currentUrl} selectedKeys={currentUrl ? [currentUrl] : []} + disallowEmptySelection onAction={onAction} className={style({ display: { diff --git a/packages/dev/s2-docs/src/SearchMenuTrigger.tsx b/packages/dev/s2-docs/src/SearchMenuTrigger.tsx index 5dc81b81e30..ac53eabd62d 100644 --- a/packages/dev/s2-docs/src/SearchMenuTrigger.tsx +++ b/packages/dev/s2-docs/src/SearchMenuTrigger.tsx @@ -3,7 +3,7 @@ import {Button, ButtonProps, Modal, ModalOverlay} from 'react-aria-components'; import {fontRelative, style} from '@react-spectrum/s2/style' with { type: 'macro' }; import {getLibraryFromPage, getLibraryLabel} from './library'; -import React, {CSSProperties, lazy, useCallback, useEffect, useState} from 'react'; +import React, {CSSProperties, lazy, useCallback, useEffect, useRef, useState} from 'react'; import Search from '@react-spectrum/s2/icons/Search'; import {useRouter} from './Router'; @@ -113,6 +113,17 @@ export default function SearchMenuTrigger({onOpen, onClose, isSearchOpen, overla if (isSearchOpen && !wasOpen) { setWasOpen(true); } + + // Manually restore focus to the trigger when search menu closes, since we don't actually unmount. + let buttonRef = useRef(null); + let isOpenRef = useRef(isSearchOpen); + useEffect(() => { + if (!isSearchOpen && isOpenRef.current && buttonRef.current) { + buttonRef.current.focus({preventScroll: true}); + } + + isOpenRef.current = isSearchOpen; + }, [isSearchOpen]); return (
- +
{/*- begin highlight -*/} Science - +
); } From 9b7444036a8a9cdaa7be00d3a81bbcaa58dfa20e Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 20:14:30 -0800 Subject: [PATCH 06/49] Show two columns of items in GridList on mobile --- starters/docs/src/GridList.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/starters/docs/src/GridList.css b/starters/docs/src/GridList.css index 2799d11cfba..ad7596390a2 100644 --- a/starters/docs/src/GridList.css +++ b/starters/docs/src/GridList.css @@ -26,6 +26,13 @@ --grid-item-size: 150px; } + @media (width < 500px) { + &[data-layout=grid] { + --grid-item-size: 150px; + grid-template-columns: 1fr 1fr; + } + } + &[data-layout=stack] { grid-template-columns: auto; align-items: center; From fbd755519661ed17f57eb866f10fe05e3c40abf3 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 20:17:16 -0800 Subject: [PATCH 07/49] Fix Vanilla Checkbox disabled checkmark color --- starters/docs/src/Checkbox.css | 1 + 1 file changed, 1 insertion(+) diff --git a/starters/docs/src/Checkbox.css b/starters/docs/src/Checkbox.css index b11495a1244..23b84a8d950 100644 --- a/starters/docs/src/Checkbox.css +++ b/starters/docs/src/Checkbox.css @@ -55,5 +55,6 @@ &[data-disabled] { color: var(--text-color-disabled); + --checkmark-color: var(--text-color-disabled); } } From f46521ae8ce6128fcfd1bda34a296350573e5deb Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 21:20:38 -0800 Subject: [PATCH 08/49] RAC ColorPicker fixes --- starters/docs/src/ColorArea.css | 5 +++-- starters/docs/src/ColorPicker.css | 1 + starters/docs/src/ColorSlider.css | 11 ++++++----- starters/docs/src/ColorThumb.css | 4 ++-- starters/tailwind/src/ColorArea.tsx | 2 +- starters/tailwind/src/ColorSlider.tsx | 4 ++-- starters/tailwind/src/ColorThumb.tsx | 2 +- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/starters/docs/src/ColorArea.css b/starters/docs/src/ColorArea.css index 4be762f0c7d..ece9bed342f 100644 --- a/starters/docs/src/ColorArea.css +++ b/starters/docs/src/ColorArea.css @@ -1,7 +1,8 @@ .react-aria-ColorArea { - width: 192px; - height: 192px; + width: 100%; + max-width: calc(var(--spacing) * 56); + aspect-ratio: 1/1; border-radius: var(--radius); flex-shrink: 0; } diff --git a/starters/docs/src/ColorPicker.css b/starters/docs/src/ColorPicker.css index ea05e05b90f..e53991bf322 100644 --- a/starters/docs/src/ColorPicker.css +++ b/starters/docs/src/ColorPicker.css @@ -27,4 +27,5 @@ gap: var(--spacing-2); min-width: 192px; max-height: inherit; + overflow: auto; } diff --git a/starters/docs/src/ColorSlider.css b/starters/docs/src/ColorSlider.css index 64afc887dbb..8e1efb596b6 100644 --- a/starters/docs/src/ColorSlider.css +++ b/starters/docs/src/ColorSlider.css @@ -4,8 +4,6 @@ "track track"; grid-template-columns: 1fr auto; gap: var(--spacing-1); - width: 100%; - max-width: 300px; .react-aria-Label { grid-area: label; @@ -24,8 +22,11 @@ } &[data-orientation=horizontal] { + width: 100%; + max-width: 300px; + .react-aria-SliderTrack { - height: var(--spacing-7); + height: var(--spacing-6); } .react-aria-ColorThumb { @@ -34,7 +35,7 @@ } &[data-orientation=vertical] { - height: 150px; + height: 200px; display: block; .react-aria-Label, @@ -43,7 +44,7 @@ } .react-aria-SliderTrack { - width: var(--spacing-7); + width: var(--spacing-6); height: 100%; } diff --git a/starters/docs/src/ColorThumb.css b/starters/docs/src/ColorThumb.css index f13045448a4..19dfdc605f2 100644 --- a/starters/docs/src/ColorThumb.css +++ b/starters/docs/src/ColorThumb.css @@ -3,8 +3,8 @@ .react-aria-ColorThumb { border: 2px solid white; box-shadow: 0 0 0 1px black, inset 0 0 0 1px black; - width: var(--spacing-5); - height: var(--spacing-5); + width: calc(var(--spacing) * 4.5); + height: calc(var(--spacing) * 4.5); border-radius: 50%; box-sizing: border-box; diff --git a/starters/tailwind/src/ColorArea.tsx b/starters/tailwind/src/ColorArea.tsx index e8084a92c13..20c4943d36c 100644 --- a/starters/tailwind/src/ColorArea.tsx +++ b/starters/tailwind/src/ColorArea.tsx @@ -13,7 +13,7 @@ export function ColorArea(props: ColorAreaProps) { return ( ({ ...defaultStyle, background: isDisabled ? undefined : defaultStyle.background diff --git a/starters/tailwind/src/ColorSlider.tsx b/starters/tailwind/src/ColorSlider.tsx index aa8a3779c88..4361ebcce25 100644 --- a/starters/tailwind/src/ColorSlider.tsx +++ b/starters/tailwind/src/ColorSlider.tsx @@ -12,11 +12,11 @@ import { composeTailwindRenderProps } from './utils'; import { ColorThumb } from './ColorThumb'; const trackStyles = tv({ - base: 'group col-span-2 orientation-horizontal:h-6 rounded-md', + base: 'group col-span-2 rounded-md', variants: { orientation: { horizontal: 'w-full h-6', - vertical: 'w-6 h-56 ml-[50%] -translate-x-[50%]' + vertical: 'w-6 h-50' }, isDisabled: { true: 'bg-neutral-300 dark:bg-neutral-800 forced-colors:bg-[GrayText]' diff --git a/starters/tailwind/src/ColorThumb.tsx b/starters/tailwind/src/ColorThumb.tsx index cdb10770a46..143af7f66f6 100644 --- a/starters/tailwind/src/ColorThumb.tsx +++ b/starters/tailwind/src/ColorThumb.tsx @@ -4,7 +4,7 @@ import {ColorThumb as AriaColorThumb, ColorThumbProps} from 'react-aria-componen import { tv } from 'tailwind-variants'; const thumbStyles = tv({ - base: 'w-6 h-6 top-[50%] left-[50%] rounded-full border-2 border-white', + base: 'w-4.5 h-4.5 top-[50%] left-[50%] rounded-full border-2 border-white box-border', variants: { isFocusVisible: { true: 'w-8 h-8' From a2e04f9b92261e31dbea417a5c31c3e1bb408e5b Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 21:47:42 -0800 Subject: [PATCH 09/49] Fix DatePicker button and scrolling --- starters/docs/src/ComboBox.tsx | 2 +- starters/docs/src/DateField.css | 2 -- starters/docs/src/DatePicker.css | 3 ++- starters/docs/src/DatePicker.tsx | 2 +- starters/docs/src/DateRangePicker.css | 11 +++++++++++ starters/docs/src/DateRangePicker.tsx | 18 ++++++++++-------- starters/docs/src/Form.css | 5 +++++ 7 files changed, 30 insertions(+), 13 deletions(-) diff --git a/starters/docs/src/ComboBox.tsx b/starters/docs/src/ComboBox.tsx index 6a58164e0ba..15a1ee7fa9b 100644 --- a/starters/docs/src/ComboBox.tsx +++ b/starters/docs/src/ComboBox.tsx @@ -30,7 +30,7 @@ export function ComboBox(
- +
{description && {description}} {errorMessage} diff --git a/starters/docs/src/DateField.css b/starters/docs/src/DateField.css index 2e1445a0860..34fb517cd19 100644 --- a/starters/docs/src/DateField.css +++ b/starters/docs/src/DateField.css @@ -20,8 +20,6 @@ white-space: nowrap; forced-color-adjust: none; cursor: text; - overflow-x: auto; - scrollbar-width: none; &[data-focus-within] { outline: 2px solid var(--focus-ring-color); diff --git a/starters/docs/src/DatePicker.css b/starters/docs/src/DatePicker.css index c4f0571ae5b..98675277e15 100644 --- a/starters/docs/src/DatePicker.css +++ b/starters/docs/src/DatePicker.css @@ -9,7 +9,8 @@ } .react-aria-DateInput { - width: 100%; + flex: 1; + min-width: 0; padding-right: var(--spacing-10); } } diff --git a/starters/docs/src/DatePicker.tsx b/starters/docs/src/DatePicker.tsx index 4fe3d4c7ef7..0d087b7b9ed 100644 --- a/starters/docs/src/DatePicker.tsx +++ b/starters/docs/src/DatePicker.tsx @@ -31,7 +31,7 @@ export function DatePicker( {(segment) => } - + {description && {description}} {errorMessage} diff --git a/starters/docs/src/DateRangePicker.css b/starters/docs/src/DateRangePicker.css index e73cb6552c3..bb2090beab0 100644 --- a/starters/docs/src/DateRangePicker.css +++ b/starters/docs/src/DateRangePicker.css @@ -3,6 +3,7 @@ .react-aria-DateRangePicker { color: var(--text-color); + max-width: 100%; .react-aria-Group { display: flex; @@ -31,6 +32,16 @@ } } + .date-fields { + flex: 1; + display: flex; + align-items: center; + width: fit-content; + overflow-x: auto; + overflow-y: clip; + scrollbar-width: none; + } + .field-Button { margin-left: auto; } diff --git a/starters/docs/src/DateRangePicker.tsx b/starters/docs/src/DateRangePicker.tsx index 237932e2c60..3a6d97ca4ff 100644 --- a/starters/docs/src/DateRangePicker.tsx +++ b/starters/docs/src/DateRangePicker.tsx @@ -28,14 +28,16 @@ export function DateRangePicker( - - {(segment) => } - - - - {(segment) => } - - +
+ + {(segment) => } + + + + {(segment) => } + +
+
{description && {description}} {errorMessage} diff --git a/starters/docs/src/Form.css b/starters/docs/src/Form.css index e42e10a1b26..ede03dabd4d 100644 --- a/starters/docs/src/Form.css +++ b/starters/docs/src/Form.css @@ -76,6 +76,11 @@ transition-duration: 200ms; -webkit-tap-highlight-color: transparent; + svg { + width: var(--spacing-4); + height: var(--spacing-4); + } + &:where([data-hovered], [data-pressed]) { background: var(--tint-300); color: var(--tint-1200); From e0fb8928e3a83727006afd8c4fc8d6cafae41e0d Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 21:50:55 -0800 Subject: [PATCH 10/49] Fix Autocomplete example overflowing --- packages/dev/s2-docs/pages/react-aria/Autocomplete.mdx | 2 +- packages/dev/s2-docs/pages/react-aria/Menu.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dev/s2-docs/pages/react-aria/Autocomplete.mdx b/packages/dev/s2-docs/pages/react-aria/Autocomplete.mdx index ebe93719fa9..13d49738fb3 100644 --- a/packages/dev/s2-docs/pages/react-aria/Autocomplete.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Autocomplete.mdx @@ -130,7 +130,7 @@ function Example(props) { return ( -
+
{/*- begin highlight -*/} -
+
{/*- begin highlight -*/} From 168b036088af113912545ccfe5e56ae41fadd888 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 22:26:32 -0800 Subject: [PATCH 11/49] Fix DateField scrolling --- starters/tailwind/src/DateField.tsx | 2 +- starters/tailwind/src/DateRangePicker.tsx | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/starters/tailwind/src/DateField.tsx b/starters/tailwind/src/DateField.tsx index e20e416de03..b6600e236a3 100644 --- a/starters/tailwind/src/DateField.tsx +++ b/starters/tailwind/src/DateField.tsx @@ -33,7 +33,7 @@ export function DateField( } const segmentStyles = tv({ - base: 'inline p-0.5 type-literal:p-0 rounded-xs outline outline-0 forced-color-adjust-none caret-transparent text-neutral-800 dark:text-neutral-200 forced-colors:text-[ButtonText]', + base: 'inline p-0.5 whitespace-nowrap type-literal:p-0 rounded-xs outline outline-0 forced-color-adjust-none caret-transparent text-neutral-800 dark:text-neutral-200 forced-colors:text-[ButtonText]', variants: { isPlaceholder: { true: 'text-neutral-600 dark:text-neutral-400' diff --git a/starters/tailwind/src/DateRangePicker.tsx b/starters/tailwind/src/DateRangePicker.tsx index ad117f4b3aa..124b7e307bb 100644 --- a/starters/tailwind/src/DateRangePicker.tsx +++ b/starters/tailwind/src/DateRangePicker.tsx @@ -26,12 +26,14 @@ export function DateRangePicker( { label, description, errorMessage, ...props }: DateRangePickerProps ) { return ( - + {label && } - - - +
+ + + +
From dd1969ca4ff440e2a0bd967ddfcd9e8e1b38aa63 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 22:27:05 -0800 Subject: [PATCH 12/49] Fix tailwind font sizes --- packages/dev/s2-docs/tailwind/home.global.css | 14 +++++++------- packages/dev/s2-docs/tailwind/tailwind.css | 14 +++++++------- starters/tailwind/src/ColorField.tsx | 2 +- starters/tailwind/src/Field.tsx | 2 +- starters/tailwind/src/TextField.tsx | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/dev/s2-docs/tailwind/home.global.css b/packages/dev/s2-docs/tailwind/home.global.css index 43f10c67319..80a05cbb6b9 100644 --- a/packages/dev/s2-docs/tailwind/home.global.css +++ b/packages/dev/s2-docs/tailwind/home.global.css @@ -24,13 +24,13 @@ body { @media (min-resolution: 200dpi) { :root { --spacing: calc(0.25rem * 1.25); - --text-xs: calc(0.75rem * 1.125); - --text-sm: calc(0.875rem * 1.125); - --text-base: calc(1rem * 1.125); - --text-lg: calc(1.125rem * 1.125); - --text-xl: calc(1.25rem * 1.125); - --text-2xl: calc(1.5rem * 1.125); - --text-3xl: calc(1.875rem * 1.125); + --text-xs: calc(0.75rem * 1.25); + --text-sm: round(down, 0.875rem * 1.25, 1px); + --text-base: calc(1rem * 1.25); + --text-lg: round(1.125rem * 1.25, 1px); + --text-xl: calc(1.25rem * 1.25); + --text-2xl: calc(1.5rem * 1.25); + --text-3xl: calc(1.875rem * 1.25); } } diff --git a/packages/dev/s2-docs/tailwind/tailwind.css b/packages/dev/s2-docs/tailwind/tailwind.css index 6ab6b5dd271..faa52c7911b 100644 --- a/packages/dev/s2-docs/tailwind/tailwind.css +++ b/packages/dev/s2-docs/tailwind/tailwind.css @@ -11,12 +11,12 @@ @media (min-resolution: 200dpi) { :root { --spacing: calc(0.25rem * 1.25); - --text-xs: calc(0.75rem * 1.125); - --text-sm: calc(0.875rem * 1.125); - --text-base: calc(1rem * 1.125); - --text-lg: calc(1.125rem * 1.125); - --text-xl: calc(1.25rem * 1.125); - --text-2xl: calc(1.5rem * 1.125); - --text-3xl: calc(1.875rem * 1.125); + --text-xs: calc(0.75rem * 1.25); + --text-sm: round(down, 0.875rem * 1.25, 1px); + --text-base: calc(1rem * 1.25); + --text-lg: round(1.125rem * 1.25, 1px); + --text-xl: calc(1.25rem * 1.25); + --text-2xl: calc(1.5rem * 1.25); + --text-3xl: calc(1.875rem * 1.25); } } diff --git a/starters/tailwind/src/ColorField.tsx b/starters/tailwind/src/ColorField.tsx index 9387ae3bf2a..cf708c8b5a6 100644 --- a/starters/tailwind/src/ColorField.tsx +++ b/starters/tailwind/src/ColorField.tsx @@ -11,7 +11,7 @@ import { composeTailwindRenderProps, focusRing } from './utils'; const inputStyles = tv({ extend: focusRing, - base: 'border-1 rounded-lg min-h-9 font-sans py-0 px-3 box-border transition', + base: 'border-1 rounded-lg min-h-9 font-sans text-sm py-0 px-3 box-border transition', variants: { isFocused: fieldBorderStyles.variants.isFocusWithin, isInvalid: fieldBorderStyles.variants.isInvalid, diff --git a/starters/tailwind/src/Field.tsx b/starters/tailwind/src/Field.tsx index 37f85290605..91e9e492431 100644 --- a/starters/tailwind/src/Field.tsx +++ b/starters/tailwind/src/Field.tsx @@ -44,5 +44,5 @@ export function FieldGroup(props: GroupProps) { } export function Input(props: InputProps) { - return + return } diff --git a/starters/tailwind/src/TextField.tsx b/starters/tailwind/src/TextField.tsx index 40606b5a5cc..d5da9723f24 100644 --- a/starters/tailwind/src/TextField.tsx +++ b/starters/tailwind/src/TextField.tsx @@ -11,7 +11,7 @@ import { composeTailwindRenderProps, focusRing } from './utils'; const inputStyles = tv({ extend: focusRing, - base: 'border-1 rounded-lg min-h-9 font-sans py-0 px-3 box-border transition', + base: 'border-1 rounded-lg min-h-9 font-sans text-sm py-0 px-3 box-border transition', variants: { isFocused: fieldBorderStyles.variants.isFocusWithin, isInvalid: fieldBorderStyles.variants.isInvalid, From ec68cad57a0f916f15dd6ee020306705cfd28571 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 22:27:18 -0800 Subject: [PATCH 13/49] Fix CommandPalette scrolling --- starters/docs/src/CommandPalette.css | 1 + starters/tailwind/src/CommandPalette.tsx | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/starters/docs/src/CommandPalette.css b/starters/docs/src/CommandPalette.css index 28d7be3729a..cd6b3d73fa4 100644 --- a/starters/docs/src/CommandPalette.css +++ b/starters/docs/src/CommandPalette.css @@ -3,6 +3,7 @@ .command-palette-dialog { width: min(90vw, 500px); height: min(90vh, 356px); + max-height: inherit; padding: var(--spacing-2); box-sizing: border-box; display: flex; diff --git a/starters/tailwind/src/CommandPalette.tsx b/starters/tailwind/src/CommandPalette.tsx index 8b450f7c05f..71573140948 100644 --- a/starters/tailwind/src/CommandPalette.tsx +++ b/starters/tailwind/src/CommandPalette.tsx @@ -38,7 +38,7 @@ export function CommandPalette(props: CommandPaletteProps) return ( - + (props: CommandPaletteProps) className="m-2" /> 'No results found.'} /> From b07d263107abf255eb6dee830985b47c79468e39 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 22:30:55 -0800 Subject: [PATCH 14/49] Fix RadioGroup scaling and disabled state --- starters/docs/src/RadioGroup.css | 11 ++++++----- starters/tailwind/src/RadioGroup.tsx | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/starters/docs/src/RadioGroup.css b/starters/docs/src/RadioGroup.css index 5ba376b9505..326b156aac1 100644 --- a/starters/docs/src/RadioGroup.css +++ b/starters/docs/src/RadioGroup.css @@ -30,6 +30,10 @@ color: var(--text-color); forced-color-adjust: none; -webkit-tap-highlight-color: transparent; + --dot-color: white; + @media (forced-colors: active) { + --dot-color: HighlightText; + } .indicator { position: relative; @@ -52,16 +56,13 @@ &[data-selected] { .indicator::after { - background: white; + background: var(--dot-color); scale: 0.37; - - @media (forced-colors: active) { - background: HighlightText; - } } } &[data-disabled] { color: var(--text-color-disabled); + --dot-color: var(--text-color-disabled); } } diff --git a/starters/tailwind/src/RadioGroup.tsx b/starters/tailwind/src/RadioGroup.tsx index 68d60e70f77..416728e7259 100644 --- a/starters/tailwind/src/RadioGroup.tsx +++ b/starters/tailwind/src/RadioGroup.tsx @@ -31,7 +31,7 @@ const styles = tv({ variants: { isSelected: { false: 'border-neutral-400 dark:border-neutral-400 group-pressed:border-neutral-500 dark:group-pressed:border-neutral-300', - true: 'border-[6px] border-neutral-700 dark:border-neutral-300 forced-colors:border-[Highlight]! group-pressed:border-neutral-800 dark:group-pressed:border-neutral-200' + true: 'border-[calc(var(--spacing)*1.5)] border-neutral-700 dark:border-neutral-300 forced-colors:border-[Highlight]! group-pressed:border-neutral-800 dark:group-pressed:border-neutral-200' }, isInvalid: { true: 'border-red-700 dark:border-red-600 group-pressed:border-red-800 dark:group-pressed:border-red-700 forced-colors:border-[Mark]!' From bae40b8aa009c8bd4e18a2f707e3adfc539f6578 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 22:35:02 -0800 Subject: [PATCH 15/49] Fix vanilla SearchField close button scaling --- starters/docs/src/SearchField.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/starters/docs/src/SearchField.css b/starters/docs/src/SearchField.css index e54e5f48a2f..63d248693a8 100644 --- a/starters/docs/src/SearchField.css +++ b/starters/docs/src/SearchField.css @@ -40,10 +40,10 @@ .clear-button { all: unset; grid-area: button; - width: 1rem; - height: 1rem; + width: var(--spacing-4); + height: var(--spacing-4); border-radius: 9999px; - margin-left: -24px; + margin-left: calc(-1 * var(--spacing-6)); text-align: center; background: var(--gray-700); color: var(--gray-50); From 6d426909fadebf4aadd0af9ef85196278f29c50a Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 22:39:01 -0800 Subject: [PATCH 16/49] Add press state to tailwind dropdown items for touch --- starters/tailwind/src/ListBox.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/starters/tailwind/src/ListBox.tsx b/starters/tailwind/src/ListBox.tsx index bc62b7253f3..d4da33f2557 100644 --- a/starters/tailwind/src/ListBox.tsx +++ b/starters/tailwind/src/ListBox.tsx @@ -60,8 +60,11 @@ export const dropdownItemStyles = tv({ false: 'text-neutral-900 dark:text-neutral-100', true: 'text-neutral-300 dark:text-neutral-600 forced-colors:text-[GrayText]' }, + isPressed: { + true: 'bg-neutral-100 dark:bg-neutral-800' + }, isFocused: { - true: 'bg-blue-600 text-white forced-colors:bg-[Highlight] forced-colors:text-[HighlightText]' + true: 'bg-blue-600 dark:bg-blue-600 text-white forced-colors:bg-[Highlight] forced-colors:text-[HighlightText]' } }, compoundVariants: [ From f42c35aedbf7ffd70611af71c1d0eb708dea40aa Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 22:42:53 -0800 Subject: [PATCH 17/49] Less layout shifting on Select example --- packages/dev/s2-docs/pages/react-aria/Select.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dev/s2-docs/pages/react-aria/Select.mdx b/packages/dev/s2-docs/pages/react-aria/Select.mdx index 8724009d5d8..c9273350493 100644 --- a/packages/dev/s2-docs/pages/react-aria/Select.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Select.mdx @@ -279,7 +279,7 @@ function Example(props) { let [animal, setAnimal] = useState("bison"); return ( -
+ <>
Current selection: {JSON.stringify(animal)}
-
+ ); } ``` From abdb347505055d9012886527345ec2f37291497f Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 22:47:49 -0800 Subject: [PATCH 18/49] Fix slider clipping, shorten vertical height --- starters/docs/src/Slider.css | 1 + starters/tailwind/src/Slider.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/starters/docs/src/Slider.css b/starters/docs/src/Slider.css index 1a65adb5a88..f47e3b4deae 100644 --- a/starters/docs/src/Slider.css +++ b/starters/docs/src/Slider.css @@ -93,6 +93,7 @@ &[data-orientation=vertical] { height: 150px; display: block; + margin: var(--spacing-3) 0; .react-aria-Label, .react-aria-SliderOutput { diff --git a/starters/tailwind/src/Slider.tsx b/starters/tailwind/src/Slider.tsx index 866afe343b1..c08d6ae88bf 100644 --- a/starters/tailwind/src/Slider.tsx +++ b/starters/tailwind/src/Slider.tsx @@ -66,7 +66,7 @@ export function Slider( {({ state }) => state.values.map((_, i) => state.getThumbValueLabel(i)).join(' – ')} - + {({ state, ...renderProps }) => <>
{state.values.length === 1 From 006f032d1c1cbac8da93007d01a5a6997bb221e3 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 23:01:20 -0800 Subject: [PATCH 19/49] Fix Tabs disabled state inheriting into Checkboxes Also Switch disabled state color --- starters/docs/src/Switch.css | 5 +++++ starters/docs/src/Switch.tsx | 4 ++-- starters/docs/src/utilities.css | 10 ++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/starters/docs/src/Switch.css b/starters/docs/src/Switch.css index 0d667e1430a..010a06e4a5a 100644 --- a/starters/docs/src/Switch.css +++ b/starters/docs/src/Switch.css @@ -65,5 +65,10 @@ .track { box-shadow: 0 0 0 1px var(--border-color); } + + &[data-selected] .handle { + background: var(--gray-200); + box-shadow: none; + } } } diff --git a/starters/docs/src/Switch.tsx b/starters/docs/src/Switch.tsx index eddc086c22c..d065aa8c695 100644 --- a/starters/docs/src/Switch.tsx +++ b/starters/docs/src/Switch.tsx @@ -13,9 +13,9 @@ export interface SwitchProps extends Omit { export function Switch({ children, ...props }: SwitchProps) { return ( - {({isSelected}) => (<> + {({isSelected, isDisabled}) => (<>
-
+
{children} )} diff --git a/starters/docs/src/utilities.css b/starters/docs/src/utilities.css index e250809b331..0eeacb73b03 100644 --- a/starters/docs/src/utilities.css +++ b/starters/docs/src/utilities.css @@ -164,8 +164,8 @@ scale: 0.9; } - [data-selected] &, - [data-indeterminate] & { + [data-selected] > &, + [data-indeterminate] > & { --indicator-color: var(--highlight-background); --indicator-background: var(--indicator-color); --indicator-highlight: rgb(255 255 255 / 0.3); @@ -192,7 +192,8 @@ } } - [data-invalid] & { + &[data-invalid], + [data-invalid] > & { --indicator-color: var(--invalid-color); @media (forced-colors: active) { @@ -206,7 +207,8 @@ outline-offset: 2px; } - [data-disabled] & { + &[data-disabled], + [data-disabled] > & { background: var(--field-background); box-shadow: inset 0 0 0 1px var(--border-color-disabled) } From 6f0a5de085bb16128f3a4f403969d410e8daebd1 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 23:14:08 -0800 Subject: [PATCH 20/49] Make add/remove tab buttons narrower, and fix client router example --- packages/dev/s2-docs/pages/react-aria/Tabs.mdx | 9 +++++++-- packages/dev/s2-docs/pages/s2/Tabs.mdx | 10 ++++++++-- packages/dev/s2-docs/src/client.tsx | 1 + 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/dev/s2-docs/pages/react-aria/Tabs.mdx b/packages/dev/s2-docs/pages/react-aria/Tabs.mdx index d6990c4bdc0..dab0d80a1ec 100644 --- a/packages/dev/s2-docs/pages/react-aria/Tabs.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Tabs.mdx @@ -121,6 +121,7 @@ export const description = 'Organizes content into multiple sections and allows import {Tabs, TabList, Tab, TabPanels, TabPanel} from 'vanilla-starter/Tabs'; import {Button} from 'vanilla-starter/Button'; import {useState} from 'react'; +import {Plus, Minus} from 'lucide-react'; function Example() { let [tabs, setTabs] = useState([ @@ -158,8 +159,12 @@ function Example() { {item => {item.title}}
- - + +
diff --git a/packages/dev/s2-docs/pages/s2/Tabs.mdx b/packages/dev/s2-docs/pages/s2/Tabs.mdx index 1250663e0e2..bb84f694fb3 100644 --- a/packages/dev/s2-docs/pages/s2/Tabs.mdx +++ b/packages/dev/s2-docs/pages/s2/Tabs.mdx @@ -62,6 +62,8 @@ import Settings from '@react-spectrum/s2/illustrations/gradient/generic1/GearSet import {ActionButton, ActionButtonGroup, Tabs, TabList, Tab, TabPanel, Collection} from '@react-spectrum/s2'; import {style} from '@react-spectrum/s2/style' with {type: 'macro'}; import {useState} from 'react'; +import AddCircle from '@react-spectrum/s2/icons/AddCircle'; +import RemoveCircle from '@react-spectrum/s2/icons/RemoveCircle'; function Example() { let [tabs, setTabs] = useState([ @@ -98,8 +100,12 @@ function Example() { {item => {item.title}} - Add tab - Remove tab + + + + + +
{/*- begin highlight -*/} diff --git a/packages/dev/s2-docs/src/client.tsx b/packages/dev/s2-docs/src/client.tsx index ab2c0bcf4dc..6a228d60ce9 100644 --- a/packages/dev/s2-docs/src/client.tsx +++ b/packages/dev/s2-docs/src/client.tsx @@ -243,6 +243,7 @@ document.addEventListener('click', e => { if ( link && isClientLink(link) && + link.pathname !== location.pathname && e.button === 0 && // left clicks only !e.metaKey && // open in new tab (mac) !e.ctrlKey && // open in new tab (windows) From 44e3d9a87108db77207337aee95e5f3e878a935c Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 23:15:07 -0800 Subject: [PATCH 21/49] Tailwind Toolbar flex wrap --- starters/tailwind/src/Toolbar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starters/tailwind/src/Toolbar.tsx b/starters/tailwind/src/Toolbar.tsx index 68717897c33..d401c25a1fe 100644 --- a/starters/tailwind/src/Toolbar.tsx +++ b/starters/tailwind/src/Toolbar.tsx @@ -4,7 +4,7 @@ import { Toolbar as RACToolbar, ToggleButtonGroupContext, ToolbarProps, composeR import { tv } from 'tailwind-variants'; const styles = tv({ - base: 'flex gap-2', + base: 'flex flex-wrap gap-2', variants: { orientation: { horizontal: 'flex-row items-center', From 1fa9dd0c8e53f638976973229b00a42bd82f20ea Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 23:18:52 -0800 Subject: [PATCH 22/49] Fix vanilla TreeItem height --- starters/docs/src/Tree.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/starters/docs/src/Tree.css b/starters/docs/src/Tree.css index 11914ca11de..8b86be191e7 100644 --- a/starters/docs/src/Tree.css +++ b/starters/docs/src/Tree.css @@ -54,8 +54,9 @@ display: flex; align-items: center; gap: var(--spacing-2); - min-height: 28px; - padding: 0.25025rem 0.25025rem 0.25025rem 0.499625rem; + min-height: var(--spacing-8); + padding: var(--spacing-1) var(--spacing-1) var(--spacing-1) var(--spacing-2); + box-sizing: border-box; --padding: var(--spacing-4); border-radius: var(--radius); outline: none; From 7722120e2f3f8d0ead45533e5e6ad11bd6e27a94 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 23:22:40 -0800 Subject: [PATCH 23/49] Only render VisualExample controls if there are props provided --- packages/dev/s2-docs/src/VisualExample.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dev/s2-docs/src/VisualExample.tsx b/packages/dev/s2-docs/src/VisualExample.tsx index 430c5f8eab7..29648e0a5ae 100644 --- a/packages/dev/s2-docs/src/VisualExample.tsx +++ b/packages/dev/s2-docs/src/VisualExample.tsx @@ -192,9 +192,9 @@ export function VisualExample({component, docs, links, importSource, props, init
-
+ {props.length > 0 &&
{Object.keys(controls).map(control => )} -
+
}
{files ? {output} : output}
From d527fab44dd08362da2272371b9be661937c0f15 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 23:34:06 -0800 Subject: [PATCH 24/49] Fix some API types in hook docs --- packages/dev/s2-docs/pages/react-aria/useMove.mdx | 4 ---- packages/dev/s2-docs/src/types.tsx | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/dev/s2-docs/pages/react-aria/useMove.mdx b/packages/dev/s2-docs/pages/react-aria/useMove.mdx index b8b1db60d4a..6edf7dd476f 100644 --- a/packages/dev/s2-docs/pages/react-aria/useMove.mdx +++ b/packages/dev/s2-docs/pages/react-aria/useMove.mdx @@ -20,10 +20,6 @@ export const description = 'Handles move interactions for pointer and keyboard, {docs.exports.useMove.description} -## API - - - ## Features Move events are fired as the pointer moves around, and specify the distance that the pointer traveled since the last event. In addition, after a user focuses the target element, move events are fired when the user presses the arrow keys. diff --git a/packages/dev/s2-docs/src/types.tsx b/packages/dev/s2-docs/src/types.tsx index d9295b9278d..6493a2934fe 100644 --- a/packages/dev/s2-docs/src/types.tsx +++ b/packages/dev/s2-docs/src/types.tsx @@ -84,7 +84,7 @@ const codeStyle = style({font: {default: 'code-xs', lg: 'code-sm'}}); let LINKS = {}; export function setLinks(links) { - LINKS = links; + Object.assign(LINKS, links); } export function Type({type}: {type: TType}) { From a8fbf88935b8aae191eb4cced45ad035e0ac584d Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 23:36:45 -0800 Subject: [PATCH 25/49] Disable native long press on images in GridList Improves drag and drop experience --- starters/docs/src/GridList.css | 1 + 1 file changed, 1 insertion(+) diff --git a/starters/docs/src/GridList.css b/starters/docs/src/GridList.css index ad7596390a2..21635b8b751 100644 --- a/starters/docs/src/GridList.css +++ b/starters/docs/src/GridList.css @@ -165,6 +165,7 @@ object-fit: cover; padding-bottom: var(--spacing-2); -webkit-user-drag: none; + -webkit-touch-callout: none; flex-shrink: 0; } From 0d8b047d69eb306f41054338fc5631a5a3928837 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 1 Dec 2025 23:39:51 -0800 Subject: [PATCH 26/49] Don't scroll library out of view on mobile if there is no toc --- packages/dev/s2-docs/src/Layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/s2-docs/src/Layout.tsx b/packages/dev/s2-docs/src/Layout.tsx index 883eb40983a..2f1ac72d42a 100644 --- a/packages/dev/s2-docs/src/Layout.tsx +++ b/packages/dev/s2-docs/src/Layout.tsx @@ -233,7 +233,7 @@ export async function Layout(props: PageProps & {children: ReactElement}) { } })}>
- } /> + } />
``` +## Features + +Landmarks provide a way to designate important subsections of a page. They allow screen reader users to get an overview of the various sections of the page, and jump to a specific section. +By default, browsers do not provide a consistent way to navigate between landmarks using the keyboard. +The `useLandmark` hook enables keyboard navigation between landmarks, and provides a consistent experience across browsers. + +* F6 and Shift+F6 key navigation between landmarks +* Alt+F6 key navigation to the main landmark +* Support for navigating nested landmarks + +## Anatomy + +Landmark elements can be registered with the `useLandmark` hook. The `role` prop is required. + +Pressing F6 will move focus to the next landmark on the page, and pressing Shift+F6 will move focus to the previous landmark. +If an element within a landmark was previously focused before leaving that landmark, focus will return to that element when navigating back to that landmark. +Alt+F6 will always move focus to the main landmark if it has been registered. + +If multiple landmarks are registered with the same role, they should have unique labels, which can be provided by aria-label or aria-labelledby. + +For an example of landmarks in use, see the [useToastRegion](https://react-spectrum.adobe.com/react-aria/useToast.html#anatomy) documentation. + ## API diff --git a/packages/dev/s2-docs/pages/react-aria/useLocale.mdx b/packages/dev/s2-docs/pages/react-aria/useLocale.mdx index 7ed25b06402..4f4c71b6ea1 100644 --- a/packages/dev/s2-docs/pages/react-aria/useLocale.mdx +++ b/packages/dev/s2-docs/pages/react-aria/useLocale.mdx @@ -17,6 +17,7 @@ export const description = 'Provides access to the current locale and layout dir # useLocale +{docs.exports.useLocale.description} ## Introduction @@ -32,7 +33,7 @@ so that the browser knows which language and direction the user interface should ## Example ```tsx -import {useLocale} from '@react-aria/i18n'; +import {useLocale} from 'react-aria'; function YourApp() { let {locale, direction} = useLocale(); diff --git a/packages/dev/s2-docs/pages/react-aria/useLongPress.mdx b/packages/dev/s2-docs/pages/react-aria/useLongPress.mdx index 9e6c89275ef..15379daa8cb 100644 --- a/packages/dev/s2-docs/pages/react-aria/useLongPress.mdx +++ b/packages/dev/s2-docs/pages/react-aria/useLongPress.mdx @@ -13,6 +13,8 @@ import {FunctionAPI} from '../../src/FunctionAPI'; import docs from 'docs:@react-aria/interactions'; import typesDocs from 'docs:@react-types/shared/src/events.d.ts'; import {InterfaceType} from '../../src/types'; +import {InlineAlert, Heading, Content} from '@react-spectrum/s2'; + export const section = 'Interactions'; export const description = 'Handles long press interactions across mouse and touch devices.'; @@ -20,38 +22,18 @@ export const description = 'Handles long press interactions across mouse and tou {docs.exports.useLongPress.description} -## Features - -A long press is triggered when a user presses and holds their pointer over a target for a minimum period of time. If the user moves their pointer off of the target before the time threshold, the interaction is canceled. Once a long press event is triggered, other pointer interactions that may be active such as `usePress` and `useMove` will be canceled so that only the long press is activated. - -* Handles mouse and touch events -* Uses pointer events where available, with fallbacks to mouse and touch events -* Ignores emulated mouse events in mobile browsers -* Prevents text selection on touch devices while long pressing -* Prevents browser and OS context menus from appearing while long pressing -* Customizable time threshold for long press -* Supports an accessibility description to indicate to assistive technology users that a long press action is available - -## Example - -This example shows a button that has both a normal press action using [usePress](usePress), as well as a long -press action using `useLongPress`. Pressing the button will set the mode to "Normal speed", and long pressing it will -set the mode to "Hyper speed". All of the emitted events are also logged below. Note that when long pressing the button, -only a long press is emitted, and no normal press is emitted on pointer up. - -**Note**: this example does not have a keyboard accessible way to trigger the long press action. Because the method of triggering -this action will differ depending on the component, it is outside the scope of `useLongPress`. Make sure to implement a keyboard -friendly alternative to all long press interactions if you are using this hook directly. - ```tsx render "use client"; import React from 'react'; -import {mergeProps} from '@react-aria/utils'; +import {mergeProps} from 'react-aria'; import {useLongPress, usePress} from '@react-aria/interactions'; function Example() { let [events, setEvents] = React.useState([]); let [mode, setMode] = React.useState('Activate'); + + /*- begin focus -*/ + // Long press to activate "Hyper speed" let {longPressProps} = useLongPress({ accessibilityDescription: 'Long press to activate hyper speed', onLongPressStart: e => setEvents( @@ -67,7 +49,9 @@ function Example() { ); } }); + /*- end focus -*/ + // Short press to activate "Normal speed" let {pressProps} = usePress({ onPress: e => { setMode('Normal speed'); @@ -92,6 +76,23 @@ function Example() { } ``` + + Accessibility + This example does not have a keyboard accessible way to trigger the long press action. Because the method of triggering +this action will differ depending on the component, it is outside the scope of `useLongPress`. Make sure to implement a keyboard +friendly alternative to all long press interactions if you are using this hook directly. + + +## Features + +A long press is triggered when a user presses and holds their pointer over a target for a minimum period of time. If the user moves their pointer off of the target before the time threshold, the interaction is canceled. Once a long press event is triggered, other pointer interactions that may be active such as `usePress` and `useMove` will be canceled so that only the long press is activated. + +* Handles mouse and touch events +* Prevents text selection on touch devices while long pressing +* Prevents browser and OS context menus from appearing while long pressing +* Customizable time threshold for long press +* Supports an accessibility description to indicate to assistive technology users that a long press action is available + ## API diff --git a/packages/dev/s2-docs/pages/react-aria/useMove.mdx b/packages/dev/s2-docs/pages/react-aria/useMove.mdx index 6edf7dd476f..28a7b67373f 100644 --- a/packages/dev/s2-docs/pages/react-aria/useMove.mdx +++ b/packages/dev/s2-docs/pages/react-aria/useMove.mdx @@ -20,27 +20,10 @@ export const description = 'Handles move interactions for pointer and keyboard, {docs.exports.useMove.description} -## Features - -Move events are fired as the pointer moves around, and specify the distance that the pointer traveled since the last event. In addition, after a user focuses the target element, move events are fired when the user presses the arrow keys. - -* Handles mouse and touch events -* Handles arrow key presses -* Uses pointer events where available, with fallbacks to mouse and touch events -* Ignores emulated mouse events in mobile browsers -* Handles disabling text selection on mobile while the press interaction is active -* Normalizes many cross browser inconsistencies - -## Example - -This example shows a ball that can be moved by dragging with a mouse or touch, or by tabbing to it and using -the arrow keys on your keyboard. The movement is clamped so that the ball cannot be dragged outside a box. -All of the move events are logged below so that you can inspect what is going on. - ```tsx render "use client"; import React from 'react'; -import {useMove} from '@react-aria/interactions'; +import {useMove} from 'react-aria'; function Example() { const CONTAINER_SIZE = 200; @@ -128,6 +111,13 @@ function Example() { } ``` +## Features + +Move events are emitted after the user presses down and then drags the pointer around. They specify the distance that the pointer traveled since the last event. In addition, after a user focuses the target element, move events are fired when the user presses the arrow keys. + +* Handles mouse and touch events +* Handles arrow key presses +* Disables text selection while the user drags ## API @@ -143,7 +133,4 @@ function Example() { ### MoveEvent -Each of these handlers is fired with a `MoveEvent`, which exposes information about the target and the -type of event that triggered the interaction. - diff --git a/packages/dev/s2-docs/pages/react-aria/useNumberFormatter.mdx b/packages/dev/s2-docs/pages/react-aria/useNumberFormatter.mdx index 10f83ffbc1b..9a7d3004e4b 100644 --- a/packages/dev/s2-docs/pages/react-aria/useNumberFormatter.mdx +++ b/packages/dev/s2-docs/pages/react-aria/useNumberFormatter.mdx @@ -19,6 +19,8 @@ export const description = 'Wraps Intl.NumberFormat and formats numbers for the # useNumberFormatter +{docs.exports.useNumberFormatter.description} + ## Introduction `useNumberFormatter` wraps a builtin browser [Intl.NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) @@ -34,7 +36,7 @@ using the [I18nProvider](I18nProvider) to specify the locale to display. ```tsx render 'use client'; -import {I18nProvider, useNumberFormatter} from '@react-aria/i18n'; +import {I18nProvider, useNumberFormatter} from 'react-aria'; function Currency({value, currency}) { let formatter = useNumberFormatter({ diff --git a/packages/dev/s2-docs/pages/react-aria/useObjectRef.mdx b/packages/dev/s2-docs/pages/react-aria/useObjectRef.mdx index 895bdb83666..d56d6a5601f 100644 --- a/packages/dev/s2-docs/pages/react-aria/useObjectRef.mdx +++ b/packages/dev/s2-docs/pages/react-aria/useObjectRef.mdx @@ -29,9 +29,7 @@ callback ref or object ref was passed in. This is useful for passing refs to Rea ```tsx render 'use client'; import React from 'react'; -import {useObjectRef} from '@react-aria/utils'; -import {useButton} from '@react-aria/button'; -import {AriaButtonProps} from '@react-types/button'; +import {useObjectRef, useButton, AriaButtonProps} from 'react-aria'; let Button = React.forwardRef((props: AriaButtonProps, ref: React.ForwardedRef) => { let objRef = useObjectRef(ref); diff --git a/packages/dev/s2-docs/pages/react-aria/usePress.mdx b/packages/dev/s2-docs/pages/react-aria/usePress.mdx index bb9a856b2f2..4d34195ee7b 100644 --- a/packages/dev/s2-docs/pages/react-aria/usePress.mdx +++ b/packages/dev/s2-docs/pages/react-aria/usePress.mdx @@ -20,35 +20,10 @@ export const description = 'Handles press interactions across mouse, touch, and {docs.exports.usePress.description} -## Features - -`usePress` returns the current press state, which can be used to adjust -the visual appearance of the target. If the pointer is released over the target, then an `onPress` event is fired. - -* Handles mouse and touch events -* Handles Enter or Space key presses -* Handles screen reader virtual clicks -* Uses pointer events where available, with fallbacks to mouse and touch events -* Normalizes focus behavior on mouse and touch interactions across browsers -* Handles disabling text selection on mobile while the press interaction is active -* Handles canceling press interactions on scroll -* Normalizes many cross browser inconsistencies - -Read our [blog post](blog/building-a-button-part-1) about the complexities of press event handling to learn more. - -## Example - -This example shows a simple target that handles press events with `usePress` and logs them to a list below. -It also uses the `isPressed` state to adjust the background color when the target is pressed. -Press down on the target and drag your pointer off and over to see when the events are fired, and try focusing -the target with a keyboard and pressing the Enter or Space keys to trigger events as well. - -**NOTE: for more advanced button functionality, see [useButton](https://react-spectrum.adobe.com/react-aria/useButton.html).** - ```tsx render "use client"; import React from 'react'; -import {usePress} from '@react-aria/interactions'; +import {usePress} from 'react-aria'; function Example() { let [events, setEvents] = React.useState([]); @@ -72,7 +47,8 @@ function Example() { background: isPressed ? 'darkgreen' : 'green', color: 'white', display: 'inline-block', - padding: 4, + padding: '8px 12px', + borderRadius: 8, cursor: 'pointer' }} role="button" @@ -91,6 +67,20 @@ function Example() { } ``` +## Features + +`usePress` returns the current press state, which can be used to adjust the visual appearance of the target. If the pointer is released over the target, then an `onPress` event is fired. + +* Handles mouse and touch events +* Handles Enter or Space key presses +* Handles screen reader virtual clicks +* Normalizes focus behavior on mouse and touch interactions across browsers +* Disables text selection while the press interaction is active +* Cancels press interactions on scroll +* Normalizes many cross browser inconsistencies + +Read our [blog post](blog/building-a-button-part-1) learn more. + ## API @@ -105,7 +95,4 @@ function Example() { ### PressEvent -Each of these handlers is fired with a `PressEvent`, which exposes information about the target and the -type of event that triggered the interaction. - - \ No newline at end of file + From dabf7350812450b1d8b79feae64e0d50fe7e17a4 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Tue, 2 Dec 2025 12:18:59 -0800 Subject: [PATCH 30/49] omit homepage from nav --- packages/dev/s2-docs/pages/react-aria/index.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/dev/s2-docs/pages/react-aria/index.mdx b/packages/dev/s2-docs/pages/react-aria/index.mdx index 8ce34bb8fe5..038781afd23 100644 --- a/packages/dev/s2-docs/pages/react-aria/index.mdx +++ b/packages/dev/s2-docs/pages/react-aria/index.mdx @@ -26,6 +26,7 @@ import {getBaseUrl} from '../../src/pageUtils'; export const section = 'Overview'; export const title = 'Home'; +export const omitFromNav = true; export const hideFromSearch = true; export const description = 'Accessible, high quality UI components and hooks for building design systems.'; From 96c900597e607f270885d4cbdfff3d67ba8ba400 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Tue, 2 Dec 2025 12:23:15 -0800 Subject: [PATCH 31/49] Fix dotted underline links in Safari --- packages/dev/s2-docs/src/Link.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/s2-docs/src/Link.tsx b/packages/dev/s2-docs/src/Link.tsx index 2fb4413d7cd..369ae0f164f 100644 --- a/packages/dev/s2-docs/src/Link.tsx +++ b/packages/dev/s2-docs/src/Link.tsx @@ -43,7 +43,7 @@ export function ColorLink({type, ...props}: RACLinkProps & {type?: 'keyword' | ' } export function CodeLink(props: RACLinkProps) { - return ({cursor: 'pointer', textDecoration: isHovered ? 'underline solid' : 'underline dotted'})} />; + return ({cursor: 'pointer', textDecoration: 'underline', textDecorationStyle: isHovered ? 'solid' : 'dotted'})} />; } const titleLink = style({ From 19d818c9ccd0f460ca093ec9b990e93402e89fcb Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Tue, 2 Dec 2025 12:52:27 -0800 Subject: [PATCH 32/49] Fix width of color editor blog example --- .../dev/s2-docs/pages/react-aria/blog/ColorEditorExample.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/s2-docs/pages/react-aria/blog/ColorEditorExample.tsx b/packages/dev/s2-docs/pages/react-aria/blog/ColorEditorExample.tsx index df70de58d99..653d6d654f6 100644 --- a/packages/dev/s2-docs/pages/react-aria/blog/ColorEditorExample.tsx +++ b/packages/dev/s2-docs/pages/react-aria/blog/ColorEditorExample.tsx @@ -30,7 +30,7 @@ function ColorEditor({hideAlphaChannel = false}: ColorEditorProps) { let formatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/color'); return ( -
+
From 16c49a3ada099ca0925c33b10e6e28147b2d146d Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Tue, 2 Dec 2025 13:30:27 -0800 Subject: [PATCH 33/49] Fix cross-library links --- packages/dev/s2-docs/pages/react-aria/Button.mdx | 3 +-- packages/dev/s2-docs/pages/react-aria/FileTrigger.mdx | 3 +-- .../pages/react-aria/blog/building-a-button-part-1.mdx | 2 +- .../pages/react-aria/blog/building-a-button-part-2.mdx | 4 ++-- .../s2-docs/pages/react-aria/blog/building-a-combobox.mdx | 4 ++-- .../creating-a-pointer-friendly-submenu-experience.mdx | 6 +++--- .../react-aria/blog/date-and-time-pickers-for-all.mdx | 8 ++++---- .../dev/s2-docs/pages/react-aria/blog/drag-and-drop.mdx | 8 ++++---- .../blog/how-we-internationalized-our-numberfield.mdx | 2 +- .../pages/react-aria/blog/introducing-react-spectrum.mdx | 6 +++--- .../dev/s2-docs/pages/react-aria/blog/rtl-date-time.mdx | 2 +- packages/dev/s2-docs/pages/s2/Calendar.mdx | 5 ++--- packages/dev/s2-docs/pages/s2/DateField.mdx | 3 +-- packages/dev/s2-docs/pages/s2/DatePicker.mdx | 3 +-- packages/dev/s2-docs/pages/s2/DateRangePicker.mdx | 3 +-- packages/dev/s2-docs/pages/s2/RangeCalendar.mdx | 5 ++--- packages/dev/s2-docs/pages/s2/TimeField.mdx | 3 +-- packages/dev/s2-docs/scripts/generateMarkdownDocs.mjs | 6 ++++++ packages/dev/s2-docs/src/Link.tsx | 5 +++++ 19 files changed, 42 insertions(+), 39 deletions(-) diff --git a/packages/dev/s2-docs/pages/react-aria/Button.mdx b/packages/dev/s2-docs/pages/react-aria/Button.mdx index 9e97fbed462..0cd92e40b35 100644 --- a/packages/dev/s2-docs/pages/react-aria/Button.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Button.mdx @@ -10,7 +10,6 @@ import vanillaDocs from 'docs:vanilla-starter/Button'; import tailwindDocs from 'docs:tailwind-starter/Button'; import '../../tailwind/tailwind.css'; import typesDocs from 'docs:@react-types/shared/src/events.d.ts'; -import {getBaseUrl} from '../../src/pageUtils'; export const tags = ['btn']; export const relatedPages = [{'title': 'useButton', 'url': 'https://react-spectrum.adobe.com/react-aria/useButton.html'}]; @@ -50,7 +49,7 @@ export const description = 'Allows a user to perform an action, with mouse, touc Use the `onPress` prop to handle interactions via mouse, keyboard, and touch. This is similar to `onClick`, but normalized for consistency across browsers, devices, and interaction methods. Read our [blog post](blog/building-a-button-part-1) to learn more. -The `onPressStart`, `onPressEnd`, and `onPressChange` events are also emitted as the user interacts with the button. Each of these handlers receives a , which provides information about the target and interaction method. See usePress for more details. +The `onPressStart`, `onPressEnd`, and `onPressChange` events are also emitted as the user interacts with the button. Each of these handlers receives a , which provides information about the target and interaction method. See [usePress](usePress) for more details. ```tsx render "use client"; diff --git a/packages/dev/s2-docs/pages/react-aria/FileTrigger.mdx b/packages/dev/s2-docs/pages/react-aria/FileTrigger.mdx index f174f18adec..63941e546e9 100644 --- a/packages/dev/s2-docs/pages/react-aria/FileTrigger.mdx +++ b/packages/dev/s2-docs/pages/react-aria/FileTrigger.mdx @@ -4,7 +4,6 @@ export default Layout; import docs from 'docs:react-aria-components'; import '../../tailwind/tailwind.css'; import {InlineAlert, Heading, Content} from '@react-spectrum/s2' -import {getBaseUrl} from '../../src/pageUtils'; export const tags = ['upload', 'input']; export const description = 'Allows a user to access the file system with any pressable React Aria or React Spectrum component.'; @@ -44,7 +43,7 @@ function Example(props) { ## Custom trigger -`FileTrigger` works with any pressable React Aria component (e.g. [Button](Button), [Link](Link), etc.). Use the `` component or usePress hook to wrap a custom trigger element such as a third party component or DOM element. +`FileTrigger` works with any pressable React Aria component (e.g. [Button](Button), [Link](Link), etc.). Use the `` component or [usePress](usePress) hook to wrap a custom trigger element such as a third party component or DOM element. ```tsx render "use client" diff --git a/packages/dev/s2-docs/pages/react-aria/blog/building-a-button-part-1.mdx b/packages/dev/s2-docs/pages/react-aria/blog/building-a-button-part-1.mdx index acccb5c6552..5724b6e896b 100644 --- a/packages/dev/s2-docs/pages/react-aria/blog/building-a-button-part-1.mdx +++ b/packages/dev/s2-docs/pages/react-aria/blog/building-a-button-part-1.mdx @@ -108,7 +108,7 @@ With the [usePress](../usePress) hook, our buttons handle interactions consisten