diff --git a/.changeset/swingset-proptable-style-rows.md b/.changeset/swingset-proptable-style-rows.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/swingset-proptable-style-rows.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/swingset/src/components/PropTable.tsx b/packages/swingset/src/components/PropTable.tsx index 22d2fd228b2..80ed0655551 100644 --- a/packages/swingset/src/components/PropTable.tsx +++ b/packages/swingset/src/components/PropTable.tsx @@ -15,16 +15,9 @@ interface ExtraProp { interface PropTableProps { meta: StoryMeta; extra?: ExtraProp[]; - /** Set false for a component that styles itself and does not want `className`/`style` advertised. */ - styleProps?: boolean; } -const STYLEX_ROWS: ExtraProp[] = [ - { name: 'className', type: 'string' }, - { name: 'style', type: 'CSSProperties' }, -]; - -export function PropTable({ meta, extra = [], styleProps = true }: PropTableProps) { +export function PropTable({ meta, extra = [] }: PropTableProps) { const playground = usePlayground(); const variants = meta.styles?._variants ?? {}; const defaults = meta.styles?._defaultVariants ?? {}; @@ -40,7 +33,7 @@ export function PropTable({ meta, extra = [], styleProps = true }: PropTableProp return { name, type, default: defDisplay }; }), ...extra, - ...(styleProps ? STYLEX_ROWS : []), + { name: 'xstyle', type: 'XStyle' }, ]; return ( @@ -56,7 +49,7 @@ export function PropTable({ meta, extra = [], styleProps = true }: PropTableProp {rows.map(row => { // The default is a static cell; the Value column is the live control. Variant - // props get a knob there; non-variant rows (the engine rows, extra) have no control. + // props get a knob there; the extra and xstyle rows have no control. const knob = playground?.knobs[row.name]; return ( diff --git a/packages/swingset/src/stories/banner.mdx b/packages/swingset/src/stories/banner.mdx index cbccb761c8c..ff38bc97db9 100644 --- a/packages/swingset/src/stories/banner.mdx +++ b/packages/swingset/src/stories/banner.mdx @@ -13,7 +13,6 @@ import * as BannerStories from './banner.stories'; ## Usage diff --git a/packages/swingset/src/stories/otp.component.mdx b/packages/swingset/src/stories/otp.component.mdx index b4777ef644c..a27f1291fe1 100644 --- a/packages/swingset/src/stories/otp.component.mdx +++ b/packages/swingset/src/stories/otp.component.mdx @@ -13,7 +13,6 @@ import * as OtpStories from './otp.component.stories'; screen.getAllByRole('textbox'); +const atoms = stylex.create({ + spaced: { marginTop: '8px' }, +}); + describe('Mosaic Otp', () => { it('renders one slot per character and applies the default status', () => { render( @@ -214,4 +219,16 @@ describe('Mosaic Otp', () => { expect(ref.current).toBe(slots()[0]); }); + + it('merges xstyle atoms after the root atoms', () => { + render( + , + ); + + const group = screen.getByRole('group', { name: 'Verification code' }); + expect(group).toHaveClass('cl-otp', stylex.props(atoms.spaced).className ?? ''); + }); }); diff --git a/packages/ui/src/mosaic/components/otp/otp.tsx b/packages/ui/src/mosaic/components/otp/otp.tsx index a5fdc5b1a1d..e6e46d021ae 100644 --- a/packages/ui/src/mosaic/components/otp/otp.tsx +++ b/packages/ui/src/mosaic/components/otp/otp.tsx @@ -3,6 +3,7 @@ import { Otp as Primitive } from '@clerk/headless/otp'; import * as stylex from '@stylexjs/stylex'; import React from 'react'; +import type { MosaicStyleProps } from '../../props'; import { mergeStyleProps, themeProps } from '../../props'; import { inputStyles } from '../../utils/input.styles'; import { reset } from '../../utils/reset.styles'; @@ -12,7 +13,8 @@ import { styles } from './otp.styles'; /** How the entered code currently reads back to the user. */ export type OtpStatus = 'neutral' | 'success' | 'error'; -export interface OtpProps extends Omit { +export interface OtpProps + extends Omit, MosaicStyleProps { /** The number of boxes in the code. @default 6 */ length?: number; /** Colours every slot for the verification outcome. Defaults to the enclosing `Field`'s validity. */ @@ -58,6 +60,7 @@ export const Otp = React.forwardRef(function MosaicO 'aria-invalid': ariaInvalidProp, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, + xstyle, ...rest }, ref, @@ -82,7 +85,7 @@ export const Otp = React.forwardRef(function MosaicO disabled={disabled} required={required} id={fieldProps?.id ?? id} - {...mergeStyleProps(themeProps('otp', { status, disabled }), stylex.props(reset.base, styles.root))} + {...mergeStyleProps(themeProps('otp', { status, disabled }), stylex.props(reset.base, styles.root, xstyle))} aria-labelledby={fieldProps?.['aria-labelledby'] ?? ariaLabelledBy} aria-describedby={fieldProps?.['aria-describedby'] ?? ariaDescribedBy} >