Skip to content
Draft
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
6 changes: 6 additions & 0 deletions .changeset/consolidate-visually-hidden.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@astryxdesign/core': patch
---

[refactor] Consolidated 5 inline visually-hidden style blocks into the shared VisuallyHidden primitive (Button, Link, ProgressBar, Switch, TextArea); no behavior change.
@cixzhang
19 changes: 3 additions & 16 deletions packages/core/src/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
} from '../theme/tokens.stylex';
import {Tooltip} from '../Tooltip/Tooltip';
import {Spinner} from '../Spinner';
import {VisuallyHidden} from '../VisuallyHidden';

import {EDGE_COMP_ATTR} from '../Layout/edgeCompensation.stylex';
import {useSize} from '../SizeContext/SizeContext';
Expand Down Expand Up @@ -124,17 +125,6 @@ const styles = stylex.create({
textOverflow: 'ellipsis',
minWidth: 0,
},
visuallyHidden: {
position: 'absolute',
width: '1px',
height: '1px',
padding: 0,
margin: '-1px',
overflow: 'hidden',
clip: 'rect(0, 0, 0, 0)',
whiteSpace: 'nowrap',
borderWidth: 0,
},
link: {
textDecoration: 'none',
},
Expand Down Expand Up @@ -690,12 +680,9 @@ export function Button({
)}
</span>
{/* Live region for loading state announcements */}
<span
{...stylex.props(styles.visuallyHidden)}
role="status"
aria-live="polite">
<VisuallyHidden role="status" aria-live="polite">
{isLoadingState ? 'Loading' : ''}
</span>
</VisuallyHidden>
</>
);

Expand Down
15 changes: 2 additions & 13 deletions packages/core/src/Link/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
import {Icon} from '../Icon';
import {Tooltip} from '../Tooltip';
import {Text} from '../Text';
import {VisuallyHidden} from '../VisuallyHidden';
import type {
TextType,
TextSize,
Expand Down Expand Up @@ -98,18 +99,6 @@ const styles = stylex.create({
fontSize: typeScaleVars['--text-body-size'],
lineHeight: typeScaleVars['--text-body-leading'],
},
// Screen-reader-only text (announces the new-tab context change).
visuallyHidden: {
position: 'absolute',
width: 1,
height: 1,
margin: -1,
padding: 0,
overflow: 'hidden',
clip: 'rect(0, 0, 0, 0)',
whiteSpace: 'nowrap',
borderStyle: 'none',
},
});

/**
Expand Down Expand Up @@ -345,7 +334,7 @@ export function Link({
{isExternalLink && !renderAsButton && (
<>
<Icon icon="externalLink" size="xsm" color="inherit" />
<span {...stylex.props(styles.visuallyHidden)}>{newTabLabel}</span>
<VisuallyHidden>{newTabLabel}</VisuallyHidden>
</>
)}
</>
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/ProgressBar/ProgressBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
import {mergeProps} from '../utils';
import type {BaseProps} from '../BaseProps';
import {themeProps} from '../utils/themeProps';
import {VisuallyHidden} from '../VisuallyHidden';

/**
* Extensible variant map for ProgressBar.
Expand Down Expand Up @@ -313,9 +314,7 @@ export function ProgressBar({
)}
</div>
) : (
<span id={labelId} {...stylex.props(styles.visuallyHidden)}>
{label}
</span>
<VisuallyHidden id={labelId}>{label}</VisuallyHidden>
)}

{/* Progress track */}
Expand Down
18 changes: 2 additions & 16 deletions packages/core/src/Switch/Switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {switchScope} from './switch.markers.stylex';
import type {BaseProps} from '../BaseProps';
import type {SizeValue} from '../utils/types';
import {themeProps} from '../utils/themeProps';
import {VisuallyHidden} from '../VisuallyHidden';

// Fixed dimensions: 40px width, 24px height, 16px thumb (off), 20px thumb (on)
const SWITCH_WIDTH = 40;
Expand Down Expand Up @@ -179,17 +180,6 @@ const styles = stylex.create({
fontSize: typeScaleVars['--text-supporting-size'],
color: colorVars['--color-text-secondary'],
},
srOnly: {
position: 'absolute',
width: 1,
height: 1,
padding: 0,
margin: -1,
overflow: 'hidden',
clip: 'rect(0, 0, 0, 0)',
whiteSpace: 'nowrap',
borderWidth: 0,
},
});

export type SwitchLabelPosition = 'start' | 'end';
Expand Down Expand Up @@ -416,11 +406,7 @@ export function Switch({
{isBusy && <Spinner size="sm" />}
</div>
</div>
{isBusy && (
<span {...stylex.props(styles.srOnly)} role="status">
Loading
</span>
)}
{isBusy && <VisuallyHidden role="status">Loading</VisuallyHidden>}
</div>
);

Expand Down
16 changes: 3 additions & 13 deletions packages/core/src/TextArea/TextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import type {SizeValue} from '../utils/types';
import {useInputContainer} from '../hooks/useInputContainer';
import {useSize} from '../SizeContext/SizeContext';
import {themeProps} from '../utils/themeProps';
import {VisuallyHidden} from '../VisuallyHidden';

const COUNTER_WARNING_THRESHOLD = 0.8;

Expand Down Expand Up @@ -93,17 +94,6 @@ const styles = stylex.create({
counterError: {
color: colorVars['--color-error'],
},
srOnly: {
position: 'absolute',
width: '1px',
height: '1px',
padding: 0,
margin: '-1px',
overflow: 'hidden',
clip: 'rect(0,0,0,0)',
whiteSpace: 'nowrap',
borderWidth: 0,
},
statusIcon: {
position: 'absolute',
top: spacingVars['--spacing-2'],
Expand Down Expand Up @@ -451,13 +441,13 @@ export function TextArea({
optimisticValue.length > maxLength && styles.counterError,
)}>
{optimisticValue.length}/{maxLength}
<span aria-live="polite" {...stylex.props(styles.srOnly)}>
<VisuallyHidden aria-live="polite">
{optimisticValue.length >= maxLength * COUNTER_WARNING_THRESHOLD
? optimisticValue.length > maxLength
? `${optimisticValue.length - maxLength} characters over limit`
: `${maxLength - optimisticValue.length} characters remaining`
: ''}
</span>
</VisuallyHidden>
</div>
)}
</Field>
Expand Down
Loading