# classNames

*Category:* Utilities
*Section:* Helper
*Source:* https://uikit.developers.rio.cloud/#/utilities/classNames
*Captured:* 2026-04-27T14:59:28.428Z

Small utility for composing CSS classes from optional string arguments. It keeps the common case readable without adding third-party runtime behavior.

## classNames

Use it for patterns like: classNames('base-class', isActive && 'active', className).

**Migration Note**

The old third-party classnames API also supported object-based syntax where object keys became class names. This worked, but it was harder to read and unnecessarily complex because the class name lived in the object key instead of being a direct argument.

Old classnames style (harder to read)

```tsx
classNames('base', { inverse: isInverse, double: isDoubleSized });
classNames('base', { 'cursor-pointer': clickable }, className);
```

classNames

(

'base'

,

{

:

,

:

}

)

;

classNames

(

'base'

,

{

'cursor-pointer'

:

}

,

)

;

New classNames API

```tsx
classNames('base', isInverse && 'inverse', isDoubleSized && 'double');
classNames('base', clickable && 'cursor-pointer', className);
```

classNames

(

'base'

,

&&

'inverse'

,

&&

'double'

)

;

classNames

(

'base'

,

&&

'cursor-pointer'

,

)

;

### Example: This class string is built from optional className arguments.

text-left text-center text-right Include optional border class
This class string is built from optional className arguments.
text-size-12 text-color-dark margin-bottom-20 border rounded padding-5 text-left

#### React (tsx)

```tsx
import { useState } from 'react';

import Button from '@rio-cloud/rio-uikit/Button';
import Checkbox from '@rio-cloud/rio-uikit/Checkbox';
import classNames from '@rio-cloud/rio-uikit/classNames';

const alignOptions = ['text-left', 'text-center', 'text-right'] as const;
type AlignOption = (typeof alignOptions)[number];

export default () => {
    const [alignClassName, setAlignClassName] = useState<AlignOption>('text-left');
    const [withBorder, setWithBorder] = useState(true);

    const demoClasses = classNames(
        'text-size-12',
        'text-color-dark',
        'margin-bottom-20',
        withBorder && 'border rounded padding-5',
        alignClassName
    );

    return (
        <div>
            <div className='display-flex gap-15 align-items-center margin-bottom-25'>
                <div className='btn-group'>
                    {alignOptions.map(option => (
                        <Button
                            key={option}
                            className={`btn btn-default btn-sm ${option === alignClassName ? 'active' : ''}`}
                            onClick={() => setAlignClassName(option)}
                        >
                            {option}
                        </Button>
                    ))}
                </div>
                <Checkbox checked={withBorder} onChange={event => setWithBorder(event.target.checked)}>
                    Include optional border class
                </Checkbox>
            </div>

            <div>
                <div className={demoClasses}>This class string is built from optional className arguments.</div>
                <code className='word-break-all'>{demoClasses}</code>
            </div>
        </div>
    );
};
```

#### HTML (html)

```html
<div>
    <div class="display-flex gap-15 align-items-center margin-bottom-25">
        <div class="btn-group">
            <button type="button" class="btn btn-default btn-component btn btn-default btn-sm active" tabindex="0">text-left</button>
            <button type="button" class="btn btn-default btn-component btn btn-default btn-sm " tabindex="0">text-center</button>
            <button type="button" class="btn btn-default btn-component btn btn-default btn-sm " tabindex="0">text-right</button>
        </div>
        <label class="checkbox" tabindex="0">
            <input type="checkbox" class="" checked="">
            <span class="checkbox-text">
                <span>Include optional border class</span>
            </span>
        </label>
    </div>
    <div>
        <div class="text-size-12 text-color-dark margin-bottom-20 border rounded padding-5 text-left">This class string is built from optional className arguments.</div>
        <code class="word-break-all">text-size-12 text-color-dark margin-bottom-20 border rounded padding-5 text-left</code>
    </div>
</div>
```

## mergeClassNameOverrides

For utility-class based styling, use mergeClassNameOverrides(defaults, overrides) to replace matching groups like margin, padding, text-size, and text-color while preserving other defaults.

### Example: Example 2

Override classes
Default: padding-x-20 padding-y-20 margin-bottom-20 text-size-16 text-color-dark border rounded
Merged: padding-x-20 text-size-16 border rounded padding-y-10 margin-bottom-0 text-color-gray
Utility overrides replace matching groups (like padding-y-* , margin-* , text-color-* ) and keep unrelated defaults.

#### React (tsx)

```tsx
import { useState } from 'react';

import { mergeClassNameOverrides } from '@rio-cloud/rio-uikit/mergeClassNameOverrides';

export default () => {
    const [overrides, setOverrides] = useState('padding-y-10 margin-bottom-0 text-color-gray');

    const defaultClassNames = 'padding-x-20 padding-y-20 margin-bottom-20 text-size-16 text-color-dark border rounded';

    const mergedClassNames = mergeClassNameOverrides(defaultClassNames, overrides);

    return (
        <div>
            <div className='form-group margin-bottom-25'>
                <label htmlFor='utility-overrides'>Override classes</label>
                <input
                    id='utility-overrides'
                    className='form-control'
                    value={overrides}
                    onChange={event => setOverrides(event.target.value)}
                />
            </div>
            <p className='margin-bottom-5'>
                Default: <code>{defaultClassNames}</code>
            </p>
            <p className='margin-bottom-25'>
                Merged: <code>{mergedClassNames}</code>
            </p>

            <div className={mergedClassNames}>
                Utility overrides replace matching groups (like <code>padding-y-*</code>, <code>margin-*</code>,{' '}
                <code>text-color-*</code>) and keep unrelated defaults.
            </div>
        </div>
    );
};
```

#### HTML (html)

```html
<div>
    <div class="form-group margin-bottom-25">
        <label for="utility-overrides">Override classes</label>
        <input id="utility-overrides" class="form-control" value="padding-y-10 margin-bottom-0 text-color-gray">
    </div>
    <p class="margin-bottom-5">Default: <code>padding-x-20 padding-y-20 margin-bottom-20 text-size-16 text-color-dark border rounded</code>
    </p>
    <p class="margin-bottom-25">Merged: <code>padding-x-20 text-size-16 border rounded padding-y-10 margin-bottom-0 text-color-gray</code>
    </p>
    <div class="padding-x-20 text-size-16 border rounded padding-y-10 margin-bottom-0 text-color-gray">Utility overrides replace matching groups (like <code>padding-y-*</code>, <code>margin-*</code>, <code>text-color-*</code>) and keep unrelated defaults.</div>
</div>
```