# ControlGroup

**📖 Live documentation:** https://cds.coinbase.com/components/inputs/ControlGroup/?platform=mobile

A layout component that arranges and manages a group of related controls, such as radio buttons, switches, or checkboxes.

## Import

```tsx
import { ControlGroup } from '@coinbase/cds-mobile/controls/ControlGroup'
```

## Examples

### Checkbox Cell Group

```tsx
function CheckboxGroupExample() {
  const [selected, setSelected] = useState(['one', 'four']);
  return (
    <VStack gap={2}>
      <ControlGroup
        label={<Text font="headline">Checkbox Group</Text>}
        ControlComponent={CheckboxCell}
        value={selected}
        onChange={(value, checked) => {
          setSelected((prev) => (checked ? [...prev, value] : prev.filter((v) => v !== value)));
        }}
        options={[
          { value: 'one', title: 'Option 1', description: 'A description for the first option.' },
          { value: 'two', title: 'Option 2', description: 'A description for the second option.' },
          {
            value: 'three',
            title: 'Option 3',
            description: 'This option is disabled.',
            disabled: true,
          },
          {
            value: 'four',
            title: 'Option 4',
            description: 'This option is read-only.',
            readOnly: true,
          },
        ]}
      />
      <Text>Selected: {selected.join(', ')}</Text>
    </VStack>
  );
}
```

### Radio Cell Group

```tsx
function RadioGroupExample() {
  const [selected, setSelected] = useState('one');
  return (
    <VStack gap={2}>
      <ControlGroup
        label={<Text font="headline">Radio Group</Text>}
        ControlComponent={RadioCell}
        value={selected}
        role="radiogroup"
        onChange={(value) => setSelected(value)}
        options={[
          { value: 'one', title: 'Option 1', description: 'A description for the first option.' },
          { value: 'two', title: 'Option 2', description: 'A description for the second option.' },
          {
            value: 'three',
            title: 'Option 3',
            description: 'This option is disabled.',
            disabled: true,
          },
          {
            value: 'four',
            title: 'Option 4',
            description: 'This option is read-only.',
            readOnly: true,
          },
        ]}
      />
      <Text>Selected: {selected}</Text>
    </VStack>
  );
}
```

### Checkbox

```tsx
function CheckboxExample() {
  const [selected, setSelected] = useState(['one', 'four']);
  return (
    <VStack gap={2}>
      <ControlGroup
        label={<Text font="headline">Checkbox</Text>}
        ControlComponent={Checkbox}
        value={selected}
        onChange={(value, checked) => {
          setSelected((prev) => (checked ? [...prev, value] : prev.filter((v) => v !== value)));
        }}
        options={[
          { value: 'one', label: 'Option 1' },
          { value: 'two', label: 'Option 2' },
          { value: 'three', label: 'Option 3 (disabled)', disabled: true },
          { value: 'four', label: 'Option 4 (read-only)', readOnly: true },
        ]}
      />
      <Text>Selected: {selected.join(', ')}</Text>
    </VStack>
  );
}
```

### Radio

```tsx
function RadioExample() {
  const [selected, setSelected] = useState('one');
  return (
    <VStack gap={2}>
      <ControlGroup
        label={<Text font="headline">Radio</Text>}
        ControlComponent={Radio}
        value={selected}
        role="radiogroup"
        onChange={(value) => setSelected(value)}
        options={[
          { value: 'one', label: 'Option 1' },
          { value: 'two', label: 'Option 2' },
          { value: 'three', label: 'Option 3 (disabled)', disabled: true },
          { value: 'four', label: 'Option 4 (read-only)', readOnly: true },
        ]}
      />
      <Text>Selected: {selected}</Text>
    </VStack>
  );
}
```

### Switch

```tsx
function SwitchExample() {
  const [selected, setSelected] = useState(['one', 'four']);
  return (
    <VStack gap={2}>
      <ControlGroup
        label={<Text font="headline">Switch</Text>}
        ControlComponent={Switch}
        value={selected}
        onChange={(value, checked) => {
          setSelected((prev) => (checked ? [...prev, value] : prev.filter((v) => v !== value)));
        }}
        options={[
          { value: 'one', label: 'Option 1' },
          { value: 'two', label: 'Option 2' },
          { value: 'three', label: 'Option 3 (disabled)', disabled: true },
          { value: 'four', label: 'Option 4 (read-only)', readOnly: true },
        ]}
      />
      <Text>Selected: {selected.join(', ')}</Text>
    </VStack>
  );
}
```

### Custom Card Toggle

```tsx
function CustomCardToggleExample() {
  // Custom component that works with ControlGroup
  const CustomCardToggle = ({
    checked,
    onChange,
    disabled,
    children,
    value,
    accessibilityLabel,
    ...props
  }) => {
    return (
      <Pressable
        onPress={() => !disabled && onChange(value, !checked)}
        disabled={disabled}
        accessibilityLabel={accessibilityLabel || children}
        accessibilityRole="checkbox"
        accessibilityState={{ checked }}
        {...props}
      >
        <Box
          background={checked ? 'bgPositive' : 'bgSecondary'}
          borderColor={checked ? 'bgPositive' : 'bgLineHeavy'}
          borderWidth={100}
          borderRadius={300}
          padding={3}
          opacity={disabled ? 0.6 : 1}
        >
          <HStack gap={2} alignItems="center">
            <Box
              width={20}
              height={20}
              borderRadius={1000}
              background={checked ? 'bg' : 'bgLineHeavy'}
              alignItems="center"
              justifyContent="center"
            >
              {checked && (
                <Text color="fgPositive" font="body">
                  ✓
                </Text>
              )}
            </Box>
            <Text color={checked ? 'fgInverse' : 'fg'} font="body">
              {children}
            </Text>
          </HStack>
        </Box>
      </Pressable>
    );
  };

  const [selected, setSelected] = useState(['premium']);
  return (
    <VStack gap={2}>
      <ControlGroup
        label={<Text font="headline">Custom Card Toggle</Text>}
        ControlComponent={CustomCardToggle}
        value={selected}
        onChange={(value, checked) => {
          setSelected((prev) => (checked ? [...prev, value] : prev.filter((v) => v !== value)));
        }}
        options={[
          { value: 'basic', label: 'Basic Plan' },
          { value: 'premium', label: 'Premium Plan' },
          { value: 'enterprise', label: 'Enterprise Plan' },
          { value: 'custom', label: 'Custom Plan (disabled)', disabled: true },
        ]}
      />
      <Text>Selected: {selected.join(', ')}</Text>
    </VStack>
  );
}
```

### Custom Radio Button

```tsx
function CustomRadioButtonExample() {
  // Custom radio component with enhanced styling
  const CustomRadioButton = ({
    checked,
    onChange,
    disabled,
    children,
    value,
    accessibilityLabel,
    ...props
  }) => {
    const getDescription = (val) => {
      switch (val) {
        case 'starter':
          return 'Perfect for beginners';
        case 'professional':
          return 'For growing businesses';
        case 'enterprise':
          return 'For large organizations';
        default:
          return '';
      }
    };

    return (
      <Pressable
        onPress={() => !disabled && onChange(value)}
        disabled={disabled}
        accessibilityLabel={accessibilityLabel || children}
        accessibilityRole="radio"
        accessibilityState={{ checked }}
        {...props}
      >
        <Box
          background={checked ? 'accentBoldBlue' : 'bg'}
          borderColor={checked ? 'accentBoldBlue' : 'bgLineHeavy'}
          borderWidth={200}
          borderRadius={200}
          padding={3}
          opacity={disabled ? 0.6 : 1}
        >
          <HStack gap={3} alignItems="center">
            <Box
              width={24}
              height={24}
              borderRadius={1000}
              background={checked ? 'bg' : 'transparent'}
              borderWidth={checked ? 0 : 200}
              borderColor="bgLineHeavy"
              alignItems="center"
              justifyContent="center"
            >
              {checked && (
                <Box width={12} height={12} borderRadius={1000} background="accentBoldBlue" />
              )}
            </Box>
            <VStack gap={0} alignItems="flex-start">
              <Text color={checked ? 'fgInverse' : 'fg'} font="body">
                {children}
              </Text>
              <Text color={checked ? 'fgInverse' : 'fgMuted'} font="caption">
                {getDescription(value)}
              </Text>
            </VStack>
          </HStack>
        </Box>
      </Pressable>
    );
  };

  const [selected, setSelected] = useState('professional');
  return (
    <VStack gap={2}>
      <ControlGroup
        label={<Text font="headline">Custom Radio Button</Text>}
        ControlComponent={CustomRadioButton}
        value={selected}
        accessibilityRole="radiogroup"
        onChange={(value) => setSelected(value)}
        options={[
          { value: 'starter', label: 'Starter' },
          { value: 'professional', label: 'Professional' },
          { value: 'enterprise', label: 'Enterprise' },
        ]}
      />
      <Text>Selected: {selected}</Text>
    </VStack>
  );
}
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `ControlComponent` | `ComponentClass<ControlComponentProps, any> \| FunctionComponent<ControlComponentProps>` | Yes | `-` | The control component to render for each option. |
| `options` | `(ControlGroupOption<ControlComponentProps> & { value: ControlValue; })[]` | Yes | `-` | Control options for the group. |
| `value` | `string \| ControlValue[]` | Yes | `-` | Current selected value(s). Use a string for single-select (e.g., RadioGroup) and an array of strings for multi-select (e.g., CheckboxGroup). |
| `accessibilityLabel` | `string` | No | `-` | Accessibility label describing the group of items. Overrides the text thats read by the screen reader when the user interacts with the element. By default, the label is constructed by traversing all the children and accumulating all the Text nodes separated by space. |
| `alignContent` | `flex-start \| flex-end \| center \| stretch \| space-between \| space-around \| space-evenly` | No | `-` | - |
| `alignItems` | `flex-start \| flex-end \| center \| stretch \| baseline` | No | `-` | - |
| `alignSelf` | `auto \| FlexAlignType` | No | `-` | - |
| `animated` | `boolean` | No | `-` | - |
| `aspectRatio` | `string \| number` | No | `-` | - |
| `background` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
| `borderBottomLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
| `borderBottomRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
| `borderBottomWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
| `borderColor` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
| `borderEndWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
| `borderRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
| `borderStartWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
| `borderTopLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
| `borderTopRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
| `borderTopWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
| `borderWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
| `bordered` | `boolean` | No | `-` | Add a border around all sides of the box. |
| `borderedBottom` | `boolean` | No | `-` | Add a border to the bottom side of the box. |
| `borderedEnd` | `boolean` | No | `-` | Add a border to the trailing side of the box. |
| `borderedHorizontal` | `boolean` | No | `-` | Add a border to the leading and trailing sides of the box. |
| `borderedStart` | `boolean` | No | `-` | Add a border to the leading side of the box. |
| `borderedTop` | `boolean` | No | `-` | Add a border to the top side of the box. |
| `borderedVertical` | `boolean` | No | `-` | Add a border to the top and bottom sides of the box. |
| `bottom` | `null \| number \| AnimatedNode \| auto \| ${number}%` | No | `-` | - |
| `color` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
| `columnGap` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
| `dangerouslySetBackground` | `string` | No | `-` | - |
| `direction` | `horizontal \| vertical` | No | `vertical` | Direction a group of components should flow. |
| `display` | `flex \| none \| contents` | No | `-` | - |
| `divider` | `ComponentType<{ children?: ReactNode; }> \| null` | No | `-` | Divider Component to include between each item in a group. |
| `elevation` | `0 \| 1 \| 2` | No | `-` | Determines box shadow styles. Parent should have overflow set to visible to ensure styles are not clipped. |
| `flexBasis` | `null \| number \| AnimatedNode \| auto \| ${number}%` | No | `-` | - |
| `flexDirection` | `row \| column \| row-reverse \| column-reverse` | No | `-` | - |
| `flexGrow` | `number` | No | `-` | - |
| `flexShrink` | `number` | No | `-` | - |
| `flexWrap` | `wrap \| nowrap \| wrap-reverse` | No | `-` | - |
| `font` | `inherit \| FontFamily` | No | `-` | - |
| `fontFamily` | `inherit \| FontFamily` | No | `-` | - |
| `fontSize` | `inherit \| FontSize` | No | `-` | - |
| `fontWeight` | `inherit \| FontWeight` | No | `-` | - |
| `gap` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | Gap to insert between siblings. |
| `height` | `null \| number \| AnimatedNode \| auto \| ${number}%` | No | `-` | - |
| `justifyContent` | `flex-start \| flex-end \| center \| space-between \| space-around \| space-evenly` | No | `-` | - |
| `label` | `null \| string \| number \| bigint \| false \| true \| ReactElement<unknown, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal \| Promise<AwaitedReactNode>` | No | `-` | Set a label for the group. |
| `left` | `null \| number \| AnimatedNode \| auto \| ${number}%` | No | `-` | - |
| `lineHeight` | `inherit \| LineHeight` | No | `-` | - |
| `margin` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
| `marginBottom` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
| `marginEnd` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
| `marginStart` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
| `marginTop` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
| `marginX` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
| `marginY` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
| `maxHeight` | `null \| number \| AnimatedNode \| auto \| ${number}%` | No | `-` | - |
| `maxWidth` | `null \| number \| AnimatedNode \| auto \| ${number}%` | No | `-` | - |
| `minHeight` | `null \| number \| AnimatedNode \| auto \| ${number}%` | No | `-` | - |
| `minWidth` | `null \| number \| AnimatedNode \| auto \| ${number}%` | No | `-` | - |
| `onChange` | `((value: ControlValue, checked?: boolean \| undefined) => void) \| undefined` | No | `-` | Handle change events. |
| `onPointerCancel` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerCancelCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerDown` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerDownCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerEnter` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerEnterCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerLeave` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerLeaveCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerMove` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerMoveCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerUp` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerUpCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `opacity` | `number \| AnimatedNode` | No | `-` | - |
| `overflow` | `visible \| hidden \| scroll` | No | `-` | - |
| `padding` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
| `paddingBottom` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
| `paddingEnd` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
| `paddingStart` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
| `paddingTop` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
| `paddingX` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
| `paddingY` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
| `pin` | `top \| bottom \| left \| right \| all` | No | `-` | Direction in which to absolutely pin the box. |
| `position` | `absolute \| relative \| static` | No | `-` | - |
| `ref` | `null \| RefObject<View \| null> \| (instance: View \| null) => void \| (() => VoidOrUndefinedOnly)` | No | `-` | - |
| `renderItem` | `(((info: { Wrapper: ComponentType<PropsWithChildren<BoxBaseProps>>; item: string \| number \| ReactElement<unknown, string \| JSXElementConstructor<any>>; index: number; isFirst: boolean; isLast: boolean; }) => string \| number \| ReactElement<unknown, string \| JSXElementConstructor<any>>) & ((info: { Wrapper: ComponentType<PropsWithChildren<BoxProps>>; item: string \| number \| ReactElement<unknown, string \| JSXElementConstructor<any>>; index: number; isFirst: boolean; isLast: boolean; }) => string \| number \| ReactElement<unknown, string \| JSXElementConstructor<any>>))` | No | `Box component for given platform` | Control the layout of each item in a group. |
| `right` | `null \| number \| AnimatedNode \| auto \| ${number}%` | No | `-` | - |
| `rowGap` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
| `style` | `false \|  \| RegisteredStyle<ViewStyle> \| Value \| AnimatedInterpolation<string \| number> \| WithAnimatedObject<ViewStyle> \| WithAnimatedArray<Falsy \| ViewStyle \| RegisteredStyle<ViewStyle> \| RecursiveArray<Falsy \| ViewStyle \| RegisteredStyle<ViewStyle>> \| readonly (Falsy \| ViewStyle \| RegisteredStyle<ViewStyle>)[]> \| null` | No | `-` | - |
| `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID Used to locate this view in end-to-end tests. |
| `textAlign` | `left \| right \| auto \| center \| justify` | No | `-` | - |
| `textDecorationLine` | `none \| underline \| line-through \| underline line-through` | No | `-` | - |
| `textDecorationStyle` | `solid \| dotted \| dashed \| double` | No | `-` | - |
| `textTransform` | `none \| capitalize \| uppercase \| lowercase` | No | `-` | - |
| `top` | `null \| number \| AnimatedNode \| auto \| ${number}%` | No | `-` | - |
| `transform` | `string \| readonly (({ scaleX: AnimatableNumericValue; } & { scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ scaleY: AnimatableNumericValue; } & { scaleX?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ translateX: AnimatableNumericValue \| ${number}%; } & { scaleX?: undefined; scaleY?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ translateY: AnimatableNumericValue \| ${number}%; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ perspective: AnimatableNumericValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotate: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateX: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateY: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateZ: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ scale: AnimatableNumericValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ skewX: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ skewY: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; matrix?: undefined; }) \| ({ matrix: AnimatableNumericValue[]; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; }))[]` | No | `-` | - |
| `userSelect` | `none \| auto \| text \| contain \| all` | No | `-` | - |
| `width` | `null \| number \| AnimatedNode \| auto \| ${number}%` | No | `-` | - |
| `zIndex` | `number` | No | `-` | - |


