diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 8188301f87..39f70a9d90 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -27,6 +27,10 @@ "messageformat": "Close", "description": "Axo Design System > Dialog Component > Close Button > Generic accessibility label" }, + "icu:AxoPasswordField.Reveal": { + "messageformat": "Show Password", + "description": "Axo Design System > Password Field Component > Reveal Button > Generic accessibility label" + }, "icu:AxoTextField.Clear": { "messageformat": "Clear", "description": "Axo Design System > Text Field Component > Clear Button > Generic accessibility label" diff --git a/ts/axo/AxoTextField.dom.tsx b/ts/axo/AxoTextField.dom.tsx deleted file mode 100644 index 74ae742fb6..0000000000 --- a/ts/axo/AxoTextField.dom.tsx +++ /dev/null @@ -1,627 +0,0 @@ -// Copyright 2026 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only -import { memo, useCallback, useId, useMemo, useRef } from 'react'; -import type { FC, InputEvent, MouseEvent, ReactNode, RefObject } from 'react'; -import { mergeRefs } from '@react-aria/utils'; -import { AxoSymbol } from './AxoSymbol.dom.tsx'; -import { tw } from './tw.dom.tsx'; -import { assert } from './_internal/assert.std.tsx'; -import { utf8 } from './_internal/utf8.std.ts'; -import { - createStrictContext, - useStrictContext, -} from './_internal/StrictContext.dom.tsx'; -import { useAxoIntl } from './_internal/AxoIntl.dom.tsx'; -import { variants } from './_internal/variants.dom.tsx'; - -/** - * A single-line text input with optional icons, action buttons, and - * character/byte limiting. - * - * @example Anatomy - * ```tsx - * - * - * - * - * - * - * ``` - * @see {@link https://w3c.github.io/aria/#textbox | `textbox` role - WAI-ARIA 1.3} - * @see {@link https://w3c.github.io/aria/#group | `group` role - WAI-ARIA 1.3} - */ -export namespace AxoTextField { - /** - * - * -------------------------------------------------------------------------- - */ - - /** @internal */ - type RootContextType = Readonly<{ - disabled?: boolean; - readOnly?: boolean; - }>; - - /** @internal */ - const RootContext = createStrictContext('AxoTextField.Root'); - - /** - * The preferred width of the text field. - * - * TODO(jamie): Get real sizes from design - * - * - `xs` – 200px - * - `sm` – 300px - * - `md` – 400px - * - `lg` – 500px - * - `xl` – 600px - * - `full` – stretches to fill the container (default) - * - * All sizes shrink to fit the container if it is narrower than the minimum. - */ - export type Width = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full'; - - export type RootProps = Readonly<{ - /** Leading icon displayed before the input. */ - symbol?: AxoSymbol.IconName; - /** Controls the width of the entire field. Defaults to `full`. */ - width?: Width; - /** Disables all inputs and actions within the field. */ - disabled?: boolean; - /** Makes all inputs within the field read-only. */ - readOnly?: boolean; - /** Should be `Input`, `Action`, and/or `Separator` elements. */ - children: ReactNode; - }>; - - /** - * Container for the text field. Provides shared `disabled`/`readOnly` state - * to child inputs and actions. - * - * @example Basic usage - * ```tsx - * - * - * - * ``` - * - * @example Segmented field with icon and action - * ```tsx - * - * - * - * - * - * - * ``` - */ - export const Root: FC = memo(props => { - const { disabled, readOnly } = props; - - const context = useMemo((): RootContextType => { - return { disabled, readOnly }; - }, [disabled, readOnly]); - - return ( - - - {props.symbol != null && } - {props.children} - - - ); - }); - - Root.displayName = 'AxoTextField.Root'; - - /** - * - * -------------------------------------------------------------------------- - */ - - const GroupWidthStyles = variants('AxoTextField.Width', { - xs: tw('w-[calc-size(fit-content,min(max(200px,size),100%))]'), - sm: tw('w-[calc-size(fit-content,min(max(300px,size),100%))]'), - md: tw('w-[calc-size(fit-content,min(max(400px,size),100%))]'), - lg: tw('w-[calc-size(fit-content,min(max(500px,size),100%))]'), - xl: tw('w-[calc-size(fit-content,min(max(600px,size),100%))]'), - full: tw('w-full'), - }); - - /** @internal */ - type GroupProps = Readonly<{ - width: Width; - children: ReactNode; - }>; - - /** @internal */ - const Group: FC = memo(props => { - return ( -
- {props.children} -
- ); - }); - - Group.displayName = 'AxoTextField.Group'; - - /** - * - * -------------------------------------------------------------------------- - */ - - /** - * How an `Input` sizes itself within the field group. - * - `fixed`: Takes up all remaining space (default). - * - `grow`: Expands with typed content, up to available space. - * - `fit`: Shrinks to fit typed content, useful for segmented fields. - */ - export type Sizing = 'fixed' | 'grow' | 'fit'; - - export type InputProps = Readonly<{ - /** Ref to the underlying `` element. */ - ref?: RefObject; - /** Provide your own id for the `` to target with a `