---
title: styled - Extend existing components | gluestack-style
description: With styled, you can easily extend existing components and make them customizable and themeable. gluestack-style has provided styled function for this.
---

import { Meta } from '@storybook/addon-docs';

<Meta title="Getting Started/styled()" />

import {
  AppProvider,
  Box,
  CodePreview,
  Button,
} from '@gluestack/design-system';

# styled()

With our `styled` function, you can easily extend existing components and make them **customizable and themeable**.

Creating a styled component:

```jsx
const StyledButton = styled(
  Pressable,
  {
    bg: '$primary600',
    px: '$6',
    py: '$4',
    _dark: {
      bg: '$gray800',
    },
  },
  componentConfig,
  extendedBaseConfig
);
```

## Configure styled

To configure **`styled`**, create a **`gluestack-style.config.ts`** file (**`.js`** works too)

**Note**: This file should be in the root of your project

## API

- Component
- componentStyleConfig
- componentConfig
- extendedBaseConfig

### componentConfig

**`componentConfig`** is an object that allows you to define the following:

1. **descendantStyle** is an array of strings that denotes the descendants of that component that should respond to parents state. This is useful for creating a complex styles that is dependent on the component that this prop is passed in.

   ```tsx
   {
     descendantStyle: ['_text', '_spinner'];
   }
   ```

2. **ancestorStyle** is an array of strings that denotes the ancestors of that component. This is useful for creating complex styles that is dependent on the ancestor component.

   ```tsx
   {
     ancestorStyle: ['_text'];
   }
   ```

   So if this component finds a parent component with `_text` prop, it will apply the styles to the component.

3. **resolveProps** is an array of strings that denotes the props that should be resolved. This is useful for props that are not passed into the style property rather goes in as a prop. For example, `placeholderTextColor` in TextInput.

   ```tsx
   {
     resolveProps: ['placeholderTextColor'];
   }
   ```

   Note: For this to work you also need to add the prop in `propertyTokenMap`, that can be defined in the next parameter of styled function i.e. **extendedBaseConfig**.

### extendedBaseConfig

**`extendedBaseConfig`** is a object that lets you extend the base config for the component. This is useful when you want to define some aliases, tokens, propertyTokenMap,
and propertyResolver that is specific to the component.

```tsx
{
  aliases: {
    pTC: 'placeholderTextColor',
    [aliasName]: [originalPropertyName],
    ...
  },
  tokens: {
    placeholderTextColor: 'placeholderTextColor',
    [tokenScale]: [tokenValue],
    [nestedTokenScale]: {
      [token]: [tokenValue],
      ...
      },
    ...
  },
  propertyTokenMap: {
    placeholderTextColor: 'colors',
    [propertyName]: [tokenScaleName],
  },
  propertyResolver: {
    placeholderTextColor: (rawValue,resolver)=>{
      return resolver(rawValue,[tokenScaleName]:?optional)
    },
    [propertyName]: [resolverCallbackFunction],
  },
}
```

This will merge the following to the base config (`gluestack-style.config.js`) for the scope of that component.

### componentStyleConfig:

### styles:

You can write styling properties in the style config object.

```jsx
const StyledButton = styled(Pressable, {
  // styles ---->
  bg: '$primary600',
  px: '$6',
  py: '$4',
  _text: {
    color: '$white',
  },
  // <--- styles
});
```

### Variants:

This allows you to easily create different variations of a component with different styles.

```jsx
const StyledButton = styled(
  Pressable,
  {
    variants:{
      variant:{
        solid:{
          bg: '$primary600',
          borderRadius: '$full',
          _text: {
            color: '$white',
          },
        },
        subtle:{
          bg: '$primary100',
          borderWidth:"$1",
          borderRadius: '$full',
          _text: {
            color: '$primary400',
          },
        },
        ...
      },
      size:{
        "sm":{
          px: '$3',
          py: '$2',
        },
        "md":{
          px: '$4',
          py: '$3',
        },
        ...
      }
    },
  },
  {
    descendantStyle: ['_text'],
  }
);
```

### Default props:

This allows you to specify default values for props that are passed to that component. This can be useful for providing default behavior for a component, or for handling cases where a required prop is not provided.

```jsx
const StyledButton = styled(
  Pressable,
  {
    variants:{
      variant:{
        solid:{
          ...
        },
        subtle:{
          ...
        },
        ...
      },
      size:{
        "sm":{
          ...
        },
        "md":{
          ...
        },
        ...
      }
    },
    defaultProps:{
      variant:"solid",
      size:"md",
    }
  },
  {
    descendantStyle: ['_text'],
  }
);
```

## Features:

### State-Based Styling:

- This includes the ability to define styles based on the component's state. This allows you to create dynamic and interactive styles that change based on user interactions or other events.
- The extended component accept a **`states`** prop, which is an object containing the state of the component. This prop can contain any number of state keys and values, such as **`{hover: true, active: true}`**. The library then uses this prop to apply the corresponding state styles to the component.
- The **`states`** prop allows developers to easily control the state of the component and its styles. For example, it can be used to apply hover styles to a button when the mouse is over the button, or to apply active styles to a button when it is clicked. The library uses the **`states`** prop to look up the state styles in the global style map and apply them to the component.
- It's important to note that the **`states`** prop is optional and will be used only if passed, otherwise the component will use the default styles.
- Sure, here's an example of how the **`states`** prop can be used:

```jsx
const StyledButton = styled(Button, {
  'bg': '$primary600',
  'px': '$6',
  'py': '$4',
  ':hover': {
    bg: '$blue300',
  },
});

function MyComponent() {
  const [isHovered, setIsHovered] = useState(false);
  const [isActive, setIsActive] = useState(false);
  return (
    <StyledButton
      states={{ hover: isHovered, active: isActive }}
      onMouseEnter={() => setIsHovered(true)}
      onMouseLeave={() => setIsHovered(false)}
      onMouseDown={() => setIsActive(true)}
      onMouseUp={() => setIsActive(false)}
    >
      Click Me
    </StyledButton>
  );
}
```

In the example above, we have a functional component that wraps a **`StyledButton`** component, which is the component returned by the **`styled`** function. The **`MyComponent`** component uses state hooks to keep track of whether the button is currently being hovered over or pressed (active). It then passes the current state to the **`StyledButton`** component via the **`states`** prop.
When the button is hovered over, the **`isHovered`** state is set to **`true`**, which causes the **`StyledButton`** component to apply the **`:hover`** styles to itself. When the button is pressed, the **`isActive`** state is set to **`true`**, which causes the **`StyledButton`** component to apply the **`:active`** styles to itself.
This way the developer can easily control the state of the component and its styles with the help of **`states`** prop.

### Platform-Based Styling:

This allows you to easily create styles that are specific to a particular platform, such as web or mobile.

```jsx
const StyledButton = styled(
  Pressable,
  {
    bg: '$primary600',
    px: '$6',
    py: '$4',
    _web: {
      bg: '$amber500',
    },
    _ios: {
      bg: '$blue500',
    },
    _android: {
      bg: '$red500',
    },
  },
  {}
);
```

### Color Mode-Based Styling:

This allows you to easily create styles that are specific to a particular color mode, like light or dark mode.

```jsx
const StyledButton = styled(Pressable, {
  bg: '$primary600',
  px: '$6',
  py: '$4',
  _dark: {
    bg: '$info600',
  },
  _light: {
    bg: '$info800',
  },
});
```

### Media Query:

This allows you to apply styles based on screen width.

```jsx
const StyledButton = styled(Pressable, {
  'bg': '$primary600',
  'px': '$6',
  'py': '$4',
  '@lg': {
    _dark: {
      bg: '$red500',
    },
    _light: {
      bg: '$blue500',
    },
  },
});
```

### Context-Based Styling:

This allows you to easily propagate context-specific styles to child components, without having to pass props or manually style each child component individually.

```jsx
const StyledButton = styled(
  Pressable,
  {
    bg: '$primary600',
    px: '$6',
    py: '$4',
    _text: {
      color: '$white',
    },
  },
  {
    descendantStyle: ['_text'],
  }
);
```

### ComponentName:

This allows you to extendTheme from createConfig.

```jsx
const StyledButton = styled(
  Pressable,
  {
    bg: '$primary600',
    px: '$6',
    py: '$4',
    _text: {
      color: '$white',
    },
  },
  {
    descendantStyle: ['_text'],
  },
  {},
  {},
  'Button'
);
```
