Skip to content
Merged
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
2 changes: 2 additions & 0 deletions .changeset/organize-mosaic-internals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
4 changes: 2 additions & 2 deletions .claude/skills/mosaic/references/stylex.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ rule reserves the `.stylex.ts` extension for StyleX define-primitives: **a
`inputStatusBorder` / `inputStatusFocusWithin` set instead of redefining the
border/focus treatment five times. Four exist today: `reset.styles.ts`,
`typography.styles.ts`, `focus-outline.styles.ts` and `rtl.styles.ts`.
- **DO** compose `rtl.mirror` from `utils/rtl.styles.ts` onto a direction-aware
- **DO** compose `rtl.mirror` from `styles/rtl.styles.ts` onto a direction-aware
icon — a chevron that means "forward"/"back", a pagination arrow, the
log-out arrow leaving its frame — via its
`xstyle`. It flips the glyph with `scaleX(-1)` only under an ancestor carrying
Expand Down Expand Up @@ -341,7 +341,7 @@ device, while touch devices look correct.
Worked example: `packages/mosaic/src/components/button/button.styles.ts`.

- **DON'T** write a focus ring by hand. Compose `focusOutline` from
`utils/focus-outline.styles.ts` into the element's `stylex.props(...)`:
`styles/focus-outline.styles.ts` into the element's `stylex.props(...)`:
`focusOutline.visible` for the element's own keyboard focus, `focusOutline.within`
for a **container** that should ring when a child is focused. The ring is one
decision for the whole system — width, style, colour and offset all come from
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/mosaic/references/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,5 @@ Write unit tests for:
- Timing that is slow to drive through the UI, such as a resend countdown. Use
fake timers.

`packages/mosaic/src/machines/__tests__/test-utils.ts` has `deferred<T>()`,
`packages/mosaic/src/__tests__/async.ts` has `deferred<T>()`,
`tick()`, and `noop`.
2 changes: 1 addition & 1 deletion packages/mosaic/src/__tests__/feature/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { act, render } from '@testing-library/react';
import type { ReactElement } from 'react';
import { vi } from 'vitest';

import { MosaicProvider } from '../../MosaicProvider';
import { MosaicProvider } from '../../mosaic-provider';
import { PUBLISHABLE_KEY } from './fake-fapi';

export async function renderWithClerk(ui: ReactElement) {
Expand Down
2 changes: 1 addition & 1 deletion packages/mosaic/src/__tests__/localization.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import { describe, expect, it } from 'vitest';

import { mosaicMessages, resolveLocalization, useLocale, useMessages } from '../localization';
import { MosaicProvider } from '../MosaicProvider';
import { MosaicProvider } from '../mosaic-provider';

describe('resolveLocalization', () => {
it('returns the base messages untouched when nothing is overridden', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import React from 'react';
import { renderToString } from 'react-dom/server';
import { describe, expect, it } from 'vitest';

import { MosaicProvider } from '../MosaicProvider';
import { MosaicProvider } from '../mosaic-provider';

describe('MosaicProvider SSR', () => {
it('renders on the server without throwing', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { describe, expect, it } from 'vitest';
import type { MosaicIconOverrides } from '../icons/overrides';
import { useMosaicIcons } from '../icons/overrides';
import { useLocale, useMessages } from '../localization';
import { MosaicProvider } from '../MosaicProvider';
import { MosaicProvider } from '../mosaic-provider';

describe('MosaicProvider icons', () => {
it('exposes the icon overrides via useMosaicIcons', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { act, renderHook, waitFor } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';

import { createActor } from '../../machine/createActor';
import { createActor } from '../../machine/create-actor';
import { confirmationMachine, useConfirmationController } from './confirmation.controller';

function start() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { setup } from '../../machine/setup';
import { useMachine } from '../../machine/useMachine';
import { useMachine } from '../../machine/use-machine';

export interface ConfirmationContext {
run: () => Promise<void>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event';
import { describe, expect, it, vi } from 'vitest';

import { Button } from '../../components/button';
import { MosaicProvider } from '../../MosaicProvider';
import { MosaicProvider } from '../../mosaic-provider';
import type { ConfirmationControlledProps, ConfirmationHandleProps } from './confirmation';
import { Confirmation } from './confirmation';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { ClerkRuntimeError } from '@clerk/shared/error';
import { act, renderHook, waitFor } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';

import { deferred } from '../../__tests__/async';
import type { ReverificationController } from '../../features/reverification';
import { deferred } from '../../machines/__tests__/test-utils';
import { useDestructiveController } from './destructive.controller';

const idleReverification = { status: 'idle', visible: false, reset: vi.fn() } as ReverificationController;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { describe, expect, it, vi } from 'vitest';
import { Button } from '../../components/button';
import { Menu } from '../../components/menu';
import type { ReverificationController } from '../../features/reverification';
import { MosaicProvider } from '../../MosaicProvider';
import { MosaicProvider } from '../../mosaic-provider';
import type { DestructiveControlledProps, DestructiveHandleProps } from './destructive';
import { Destructive } from './destructive';

Expand Down
4 changes: 2 additions & 2 deletions packages/mosaic/src/components/action-bar/action-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import { mergeProps, useRender } from '../../primitives/utils';
import { getComputedStyle } from '../../primitives/utils/dom';
import type { MosaicComponentProps, XStyle } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { reset } from '../../utils/reset.styles';
import { tabularNumbersStyle } from '../../utils/typography.styles';
import { reset } from '../../styles/reset.styles';
import { tabularNumbersStyle } from '../../styles/typography.styles';
import type { ButtonProps } from '../button';
import { Button } from '../button';
import { Icon } from '../icon';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, expect, it, vi } from 'vitest';

import { MosaicProvider } from '../../MosaicProvider';
import { MosaicProvider } from '../../mosaic-provider';
import { ActionMenu } from './action-menu';

function renderMenu(actions: Parameters<typeof ActionMenu>[0]['actions']) {
Expand Down
4 changes: 2 additions & 2 deletions packages/mosaic/src/components/avatar/avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import React from 'react';
import { useRender } from '../../primitives/utils';
import type { MosaicComponentProps, MosaicElementProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { focusOutline } from '../../utils/focus-outline.styles';
import { reset } from '../../utils/reset.styles';
import { focusOutline } from '../../styles/focus-outline.styles';
import { reset } from '../../styles/reset.styles';
import { shapes, sizes, styles } from './avatar.styles';

type ImageLoadingStatus = 'idle' | 'loading' | 'loaded' | 'error';
Expand Down
2 changes: 1 addition & 1 deletion packages/mosaic/src/components/badge/badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from 'react';
import { useRender } from '../../primitives/utils';
import type { MosaicComponentProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { reset } from '../../utils/reset.styles';
import { reset } from '../../styles/reset.styles';
import { withTruncatableLabel } from '../../utils/truncatable-label';
import { BadgeContext } from './badge.context';
import { colors, styles } from './badge.styles';
Expand Down
2 changes: 1 addition & 1 deletion packages/mosaic/src/components/banner/banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { IconName } from '../../icons/registry';
import { useRender } from '../../primitives/utils';
import type { MosaicComponentProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { reset } from '../../utils/reset.styles';
import { reset } from '../../styles/reset.styles';
import { Icon } from '../icon';
import { descriptionColors, rootColors, styles } from './banner.styles';

Expand Down
4 changes: 2 additions & 2 deletions packages/mosaic/src/components/branding/branding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import React from 'react';
import { useRender } from '../../primitives/utils';
import type { MosaicComponentProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { focusOutline } from '../../utils/focus-outline.styles';
import { reset } from '../../utils/reset.styles';
import { focusOutline } from '../../styles/focus-outline.styles';
import { reset } from '../../styles/reset.styles';
import { ClerkLogo } from '../clerk-logo';
import { styles } from './branding.styles';

Expand Down
4 changes: 2 additions & 2 deletions packages/mosaic/src/components/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import React from 'react';
import { Button as HeadlessButton } from '../../primitives/button';
import type { MosaicElementProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { focusOutline } from '../../utils/focus-outline.styles';
import { reset } from '../../utils/reset.styles';
import { focusOutline } from '../../styles/focus-outline.styles';
import { reset } from '../../styles/reset.styles';
import { withTruncatableLabel } from '../../utils/truncatable-label';
import { ButtonContext } from './button.context';
import { buttonScope } from './button.markers.stylex';
Expand Down
2 changes: 1 addition & 1 deletion packages/mosaic/src/components/button/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ export { SubmitButton } from './submit-button';
export type { SubmitButtonProps } from './submit-button';
// Named here rather than only inside `SubmitButtonProps`, so a consumer can type the object they
// pass to `spinDelay`.
export type { SpinDelayOptions } from '../../hooks/useSpinDelay';
export type { SpinDelayOptions } from '../../hooks/use-spin-delay';
6 changes: 3 additions & 3 deletions packages/mosaic/src/components/button/submit-button.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as stylex from '@stylexjs/stylex';
import React from 'react';

import type { SpinDelayOptions } from '../../hooks/useSpinDelay';
import { useSpinDelay } from '../../hooks/useSpinDelay';
import type { SpinDelayOptions } from '../../hooks/use-spin-delay';
import { useSpinDelay } from '../../hooks/use-spin-delay';
import { mergeStyleProps, themeProps } from '../../props';
import { reset } from '../../utils/reset.styles';
import { reset } from '../../styles/reset.styles';
import { withTruncatableLabel } from '../../utils/truncatable-label';
import { Spinner } from '../spinner';
import type { ButtonProps } from './button';
Expand Down
2 changes: 1 addition & 1 deletion packages/mosaic/src/components/card/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from 'react';
import { useRender } from '../../primitives/utils';
import type { MosaicComponentProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { reset } from '../../utils/reset.styles';
import { reset } from '../../styles/reset.styles';
import { Branding } from '../branding';
import { Button } from '../button';
import { Dialog, DialogContext, isInDialog } from '../dialog';
Expand Down
4 changes: 2 additions & 2 deletions packages/mosaic/src/components/checkbox/checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import React from 'react';

import type { MosaicStyleProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { focusOutline } from '../../utils/focus-outline.styles';
import { reset } from '../../utils/reset.styles';
import { focusOutline } from '../../styles/focus-outline.styles';
import { reset } from '../../styles/reset.styles';
import { useOptionalFieldContext, useOptionalFieldControlProps } from '../field/field.context';
import { Icon } from '../icon';
import { checkboxInputMarker } from './checkbox.markers.stylex';
Expand Down
2 changes: 1 addition & 1 deletion packages/mosaic/src/components/combobox/combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Combobox as HeadlessCombobox } from '../../primitives/combobox';
import { useRender } from '../../primitives/utils';
import type { MosaicComponentProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { reset } from '../../utils/reset.styles';
import { reset } from '../../styles/reset.styles';
import { Icon } from '../icon';
import { Input, type InputVariant } from '../input';
import { useOptionalInputGroupContext } from '../input-group/input-group.context';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { render, screen } from '@testing-library/react';
import { describe, expect, it } from 'vitest';

import { MosaicProvider } from '../../MosaicProvider';
import { MosaicProvider } from '../../mosaic-provider';
import { DataList } from './data-list';

function renderList(props?: { divided?: boolean }) {
Expand Down
4 changes: 2 additions & 2 deletions packages/mosaic/src/components/data-list/data-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import React from 'react';
import { useRender } from '../../primitives/utils';
import type { MosaicComponentProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { reset } from '../../utils/reset.styles';
import { truncationStyles } from '../../utils/typography.styles';
import { reset } from '../../styles/reset.styles';
import { truncationStyles } from '../../styles/typography.styles';
import * as slots from './data-list.styles';

export type DataListProps = MosaicComponentProps<'dl'> & {
Expand Down
6 changes: 3 additions & 3 deletions packages/mosaic/src/components/dialog/dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as stylex from '@stylexjs/stylex';
import React from 'react';

import { useAccessibleDescriptionWarning } from '../../hooks/useAccessibleDescriptionWarning';
import { useAccessibleNameWarning } from '../../hooks/useAccessibleNameWarning';
import { useAccessibleDescriptionWarning } from '../../hooks/use-accessible-description-warning';
import { useAccessibleNameWarning } from '../../hooks/use-accessible-name-warning';
import type {
DialogFocusTarget,
DialogHandle,
Expand All @@ -12,7 +12,7 @@ import type {
import { Dialog as Primitive, useDialogContext as useHeadlessDialogContext } from '../../primitives/dialog';
import type { MosaicComponentProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { reset } from '../../utils/reset.styles';
import { reset } from '../../styles/reset.styles';
import { Button } from '../button';
import { Icon } from '../icon';
import { ToastProvider } from '../toast/toast';
Expand Down
2 changes: 1 addition & 1 deletion packages/mosaic/src/components/drawer/drawer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, expect, it } from 'vitest';

import { MosaicProvider } from '../../MosaicProvider';
import { MosaicProvider } from '../../mosaic-provider';
import { Dialog } from '../dialog';
import { Drawer } from './drawer';

Expand Down
2 changes: 1 addition & 1 deletion packages/mosaic/src/components/drawer/drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { DrawerFocusTarget, DrawerProps as HeadlessDrawerProps } from '../.
import { Drawer as Primitive, registerDrawerCssVars } from '../../primitives/drawer';
import type { MosaicComponentProps, MosaicStyleProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { reset } from '../../utils/reset.styles';
import { reset } from '../../styles/reset.styles';
import { DialogContext, isInDialog } from '../dialog';
import { styles } from './drawer.styles';

Expand Down
2 changes: 1 addition & 1 deletion packages/mosaic/src/components/empty-state/empty-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { IconName } from '../../icons/registry';
import { useRender } from '../../primitives/utils';
import type { MosaicComponentProps, MosaicElementProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { reset } from '../../utils/reset.styles';
import { reset } from '../../styles/reset.styles';
import { Icon, IconFrame } from '../icon';
import { styles } from './empty-state.styles';

Expand Down
8 changes: 4 additions & 4 deletions packages/mosaic/src/components/field/field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { useTransition } from '../../primitives/hooks';
import { useRender } from '../../primitives/utils';
import type { MosaicComponentProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { feedbackHeight, feedbackStyles } from '../../styles/feedback.styles';
import { reset } from '../../styles/reset.styles';
import { sizes as typographySizes, styles as typographyStyles } from '../../styles/typography.styles';
import { visuallyHidden } from '../../styles/visually-hidden.styles';
import { FeedbackBody, hasMessage, useHeldMessage, useMessageHeight } from '../../utils/feedback';
import { feedbackHeight, feedbackStyles } from '../../utils/feedback.styles';
import { reset } from '../../utils/reset.styles';
import { sizes as typographySizes, styles as typographyStyles } from '../../utils/typography.styles';
import { visuallyHidden } from '../../utils/visually-hidden.styles';
import type { FieldFeedback as FormFieldFeedback } from '../form';
import type { FieldOrientation } from './field.context';
import {
Expand Down
2 changes: 1 addition & 1 deletion packages/mosaic/src/components/flow/flow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from 'react';
import { Flow as HeadlessFlow, type FlowDirection } from '../../primitives/flow';
import type { MosaicComponentProps } from '../../props';
import { mergeStyleProps, themeProps } from '../../props';
import { reset } from '../../utils/reset.styles';
import { reset } from '../../styles/reset.styles';
import { styles } from './flow.styles';

export interface FlowRootProps<State> extends Omit<MosaicComponentProps<'div'>, 'children'> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { act, renderHook } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';

import { tick } from '../../__tests__/async';
import type { FieldFeedback } from './form-submit-error';
import { FormSubmitError } from './form-submit-error';
import { useForm } from './use-form';

const flush = () => new Promise<void>(resolve => setTimeout(resolve, 0));

interface EditPasswordValues {
currentPassword: string;
newPassword: string;
Expand Down Expand Up @@ -59,7 +58,7 @@ describe('useForm: edit password', () => {
});
await act(async () => {
finish();
await flush();
await tick();
});
expect(form.isSubmitting).toBe(false);
});
Expand All @@ -69,7 +68,7 @@ describe('useForm: edit password', () => {

act(() => result.current.setValue('currentPassword', 'old-secret'));
act(() => result.current.setValue('newPassword', 'short'));
await act(flush);
await act(tick);
expect(result.current.fields.newPassword.feedback).toBeUndefined();
expect(result.current.canSubmit).toBe(false);

Expand All @@ -81,14 +80,14 @@ describe('useForm: edit password', () => {

act(() => result.current.setValue('newPassword', 'longenough'));
expect(result.current.fields.newPassword.isValidating).toBe(true);
await act(flush);
await act(tick);
expect(result.current.fields.newPassword.feedback).toEqual({
type: 'warning',
message: 'Your password works, but could be stronger.',
});

act(() => result.current.setValue('newPassword', 'longenough1'));
await act(flush);
await act(tick);
expect(result.current.fields.newPassword.feedback).toEqual({
type: 'success',
message: 'Your password meets all the necessary requirements.',
Expand Down Expand Up @@ -134,11 +133,11 @@ describe('useForm: edit password', () => {
const { result } = renderHook(() => useEditPasswordForm(onSubmit));
act(() => result.current.setValue('currentPassword', 'wrong'));
act(() => result.current.setValue('newPassword', 'longenough1'));
await act(flush);
await act(tick);
act(() => result.current.setValue('confirmPassword', 'longenough1'));
await act(async () => {
result.current.submit();
await flush();
await tick();
});
expect(result.current.error).toBe('Password could not be changed.');
expect(result.current.fields.currentPassword.feedback).toEqual({ type: 'error', message: 'Incorrect password.' });
Expand Down
Loading
Loading