Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/selectable-card-mark-touch-one-frame.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[feat] Under a finger (a coarse primary pointer), a SelectableCard's selection mark now changes in one frame, as UIKit's selection marks do. Before, the inset ring appeared or vanished at once while the border faded over the theme's fast duration, so the mark changed in two steps. With a mouse the card keeps the theme's fade, and under Reduce Motion a mouse's change is now immediate.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/selection-marks-touch-one-frame.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[feat] Under a finger (a coarse primary pointer), a checkbox or radio mark now changes in the frame the selection lands, the way UIKit shows a selection mark. The box or circle used to fade between its two colors over the theme duration, so a tap first showed half-filled frames. With a mouse the marks keep the theme duration and easing, and under Reduce Motion they still change at once.

@vjeux
16 changes: 14 additions & 2 deletions packages/core/src/Indicator/CheckboxIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

/**
* @file CheckboxIndicator.tsx
* @input Indicator state props
* @input Indicator state props; the mark-change clock of a touch presentation
* (selectionMotion.stylex.ts, mirroring motion/uikit/selection.ts)
* @output Exports CheckboxIndicator — the default checkbox selection visual
* @position Decorative checkbox visual shared by CheckboxInput, CheckboxList,
* and decorative menu markers
Expand All @@ -20,8 +21,12 @@ import {isRenderable} from '../utils/isRenderable';
import {mergeProps} from '../utils/mergeProps';
import {themeProps} from '../utils/themeProps';
import {indicatorScope} from './indicator.markers.stylex';
import {selectionMotionConsts} from './selectionMotion.stylex';
import type {IndicatorProps} from './types';

/** How long the mark takes to change under a finger: one frame. */
const MARK_CHANGE = `${selectionMotionConsts.markChangeMs}ms`;

const styles = stylex.create({
box: {
boxSizing: 'border-box',
Expand All @@ -35,7 +40,14 @@ const styles = stylex.create({
transitionProperty: 'background-color, border-color',
transitionDuration: {
default: durationVars['--duration-fast'],
'@media (prefers-reduced-motion: reduce)': '0s',
// Under a finger the mark changes in the frame the selection lands, as
// UIKit's marks do (motion/uikit/selection.ts). Under Reduce Motion a
// mouse's change is immediate too.
// The keys are spelled out: an imported at-rule key lands in another
// StyleX priority layer than a literal one.
'@media (pointer: coarse)': MARK_CHANGE,
'@media (prefers-reduced-motion: reduce) and (not (pointer: coarse))':
'0s',
},
transitionTimingFunction: easeVars['--ease-standard'],
},
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/Indicator/Indicator.doc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const docs = {
name: 'CheckboxIndicator',
displayName: 'Checkbox Indicator',
description:
'The checkbox visual: a square box with a checkmark or an indeterminate bar. Decorative (aria-hidden); the owning control keeps the input, role, accessible name, focus, and keyboard behavior.',
'The checkbox visual: a square box with a checkmark or an indeterminate bar. Decorative (aria-hidden); the owning control keeps the input, role, accessible name, focus, and keyboard behavior. Under a finger (a coarse primary pointer) the box changes in one frame, as UIKit selection marks do; with a mouse its colors fade over the theme duration.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: under Reduce Motion a mouse's change is immediate, so "with a mouse its colors fade over the theme duration" is not true there. Suggest ending with "; under Reduce Motion it changes at once", as SelectableCard.doc.mjs does. The RadioIndicator description at line 100 has the same sentence.

props: [
{
name: 'state',
Expand Down Expand Up @@ -97,7 +97,7 @@ export const docs = {
name: 'RadioIndicator',
displayName: 'Radio Indicator',
description:
'The radio visual: a circle with a filled inner dot when selected. Draws in both states; an unselected radio is an empty circle, which is what lets it stand in for a checkmark in a selection slot.',
'The radio visual: a circle with a filled inner dot when selected. Draws in both states; an unselected radio is an empty circle, which is what lets it stand in for a checkmark in a selection slot. Under a finger (a coarse primary pointer) the circle changes in one frame, as UIKit selection marks do; with a mouse its colors fade over the theme duration.',
props: [
{
name: 'state',
Expand Down
16 changes: 14 additions & 2 deletions packages/core/src/Indicator/RadioIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

/**
* @file RadioIndicator.tsx
* @input Indicator state props
* @input Indicator state props; the mark-change clock of a touch presentation
* (selectionMotion.stylex.ts, mirroring motion/uikit/selection.ts)
* @output Exports RadioIndicator — the default radio selection visual
* @position Decorative radio visual shared by RadioList, decorative menu
* markers, and any selection slot themed to use a radio
Expand All @@ -20,8 +21,12 @@ import {isRenderable} from '../utils/isRenderable';
import {mergeProps} from '../utils/mergeProps';
import {themeProps} from '../utils/themeProps';
import {indicatorScope} from './indicator.markers.stylex';
import {selectionMotionConsts} from './selectionMotion.stylex';
import type {IndicatorProps} from './types';

/** How long the mark takes to change under a finger: one frame. */
const MARK_CHANGE = `${selectionMotionConsts.markChangeMs}ms`;

const styles = stylex.create({
circle: {
boxSizing: 'border-box',
Expand All @@ -39,7 +44,14 @@ const styles = stylex.create({
transitionProperty: 'background-color, border-color',
transitionDuration: {
default: durationVars['--duration-fast'],
'@media (prefers-reduced-motion: reduce)': '0s',
// Under a finger the mark changes in the frame the selection lands, as
// UIKit's marks do (motion/uikit/selection.ts). Under Reduce Motion a
// mouse's change is immediate too.
// The keys are spelled out: an imported at-rule key lands in another
// StyleX priority layer than a literal one.
'@media (pointer: coarse)': MARK_CHANGE,
'@media (prefers-reduced-motion: reduce) and (not (pointer: coarse))':
'0s',
},
transitionTimingFunction: easeVars['--ease-standard'],
},
Expand Down
Loading