> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metabind.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Appearance — Color and style

> Modifiers that set foreground and background style, opacity, corners, borders, and shadows

export const PlatformStatuses = ({statuses}) => {
  const StatusBadge = ({status, label}) => {
    const styles = {
      green: {
        backgroundColor: '#dcfce7',
        color: '#166534'
      },
      orange: {
        backgroundColor: '#fed7aa',
        color: '#9a3412'
      },
      red: {
        backgroundColor: '#fecaca',
        color: '#991b1b'
      },
      gray: {
        backgroundColor: '#f3f4f6',
        color: '#4b5563'
      }
    };
    const baseStyle = {
      display: 'inline-flex',
      alignItems: 'center',
      padding: '0.125rem 0.625rem',
      borderRadius: '9999px',
      fontSize: '0.875rem',
      fontWeight: '500'
    };
    const colorStyle = styles[status] || styles.green;
    return <span style={{
      ...baseStyle,
      ...colorStyle
    }}>
        {label || status}
      </span>;
  };
  const STATUS_CONFIG = {
    supported: {
      label: "Supported",
      color: "green"
    },
    partial: {
      label: "Partial",
      color: "orange"
    },
    "not-implemented": {
      label: "Not Implemented",
      color: "gray"
    }
  };
  const renderCard = (platform, value) => {
    if (!value) return null;
    const {status, note} = typeof value === "string" ? {
      status: value
    } : value;
    const config = STATUS_CONFIG[status];
    if (!config) return null;
    const titleMap = {
      ios: "SwiftUI",
      android: "Jetpack Compose",
      web: "Web"
    };
    return <Card key={platform} title={titleMap[platform] || platform}>
          <StatusBadge status={config.color} label={config.label} />
          {note && <div style={{
      marginTop: '0.5rem',
      fontSize: '0.875rem',
      color: '#6b7280'
    }}>
              {note}
            </div>}
      </Card>;
  };
  if (statuses == null) {
    return null;
  }
  return <Columns cols="3">
      {Object.entries(statuses).map(([platform, value]) => renderCard(platform, value))}
    </Columns>;
};

export const ComposeJS = ({code, name, height}) => {
  const encodedCode = useMemo(() => {
    if (!code) return "";
    try {
      return btoa(code);
    } catch (e) {
      console.error("Failed to encode code", e);
      return "";
    }
  }, [code]);
  if (!encodedCode) {
    return null;
  }
  return <iframe src={`https://www.metabind.ai/embed?code=${encodedCode}&name=${name ?? 'Example'}`} loading="lazy" style={{
    width: "100%",
    height: height || '350px',
    border: "1px solid #e5e7eb",
    borderRadius: "var(--rounded-2xl,1rem)",
    overflow: "hidden"
  }} title="ComposeJS Preview" />;
};

These modifiers control a component's surface appearance. `opacity` sets transparency. `foregroundStyle` colors text and shape fills (and propagates to descendants), while `tint` colors interactive controls. `background` sits behind the component as a color, gradient, material, or another component.

`cornerRadius`, `border`, and `shadow` shape and outline the component. They compose in chain order — `padding` runs before `background`, so the background extends to cover the padded area.

## opacity

Sets the component's opacity.

```typescript theme={null}
.opacity(value: number): Component
```

<ParamField path="value" type="number" required>
  The opacity level, from `0` (fully transparent) to `1` (fully opaque).
</ParamField>

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: { status: "supported" },
web: { status: "supported" },
}}
/>

Unlike `.hidden()`, a component with `.opacity(0)` still occupies layout space and remains hittable (responds to tap gestures). Use `.allowsHitTesting(false)` in combination with `.opacity(0)` to make it non-interactive. Opacity applies to the entire component subtree, including all children.

**Semi-transparent component**

```typescript theme={null}
Text("50% opacity")
    .opacity(0.5)
```

**Fading an image**

```typescript theme={null}
Image({ url: "background.jpg" })
    .resizable()
    .scaledToFill()
    .opacity(0.3)
```

**Animated fade**

```typescript theme={null}
const body = () => {
    const [isVisible, setIsVisible] = useState(false)

    return VStack([
        Button("Toggle", () => setIsVisible(!isVisible)),
        Text("Fading content")
            .opacity(isVisible ? 1 : 0)
    ])
}
```

**Disabled appearance**

```typescript theme={null}
VStack([
    Button("Submit", () => {}),
    Text("Please fill in all fields")
])
    .opacity(0.4)
    .disabled(true)
```

## foregroundStyle

Sets the foreground style (text color, shape fill, etc.) for a component and its descendants.

```typescript theme={null}
.foregroundStyle(style: Style)
```

<ParamField path="style" type="Style" required>
  A [Color](/bindjs/styles/Color), gradient ([LinearGradient](/bindjs/styles/LinearGradient), [RadialGradient](/bindjs/styles/RadialGradient), etc.), or [Material](/bindjs/styles/Material) to apply as the foreground style.
</ParamField>

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: { status: "supported" },
web: { status: "supported" },
}}
/>

**Color text**

```typescript theme={null}
Text("Blue text")
    .foregroundStyle(Color("blue"))
```

**System color**

```typescript theme={null}
Text("Secondary text")
    .foregroundStyle(Color("secondaryLabel"))
```

**Gradient text**

```typescript theme={null}
Text("Gradient")
    .font("largeTitle")
    .foregroundStyle(LinearGradient({
        colors: ["red", "blue"],
        startPoint: "leading",
        endPoint: "trailing"
    }))
```

**Style a shape**

```typescript theme={null}
Circle()
    .frame({ width: 50, height: 50 })
    .foregroundStyle(Color("green"))
```

**Inherited by descendants**

```typescript theme={null}
VStack([
    Text("All text in this stack"),
    Text("will be red")
])
    .foregroundStyle(Color("red"))
```

## tint

Sets the tint color for interactive controls.

```typescript theme={null}
.tint(color: Color): Component
```

<ParamField path="color" type="Color" required>
  The tint color to apply to interactive controls such as buttons, toggles, and links.
</ParamField>

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: { status: "partial", note: "Registered but not applied; no visual effect on controls" },
web: "not-implemented",
}}
/>

`.tint()` affects the accent color of interactive controls, not the text color. Use [foregroundStyle](#foregroundstyle) to change text or shape fill colors. Tint propagates to child components through the environment.

**Tinted button**

```typescript theme={null}
Button("Delete", () => {})
    .tint(Color("red"))
```

**Tinted toggle**

```typescript theme={null}
const body = () => {
    const [isOn, setIsOn] = useState(false)
    return Toggle("Dark Mode", { isOn, setIsOn })
        .tint(Color("purple"))
}
```

**Tint a container**

Apply tint to a parent container to affect all interactive children.

```typescript theme={null}
VStack([
    Button("Primary Action", () => {}),
    Button("Secondary Action", () => {}),
]).tint(Color("orange"))
```

## background

Sets the background of a component to a color, gradient, material, or another component.

```typescript theme={null}
.background(style?: Style)
.background(content: Component)
.background(props: { alignment: Alignment }, content: Component)
```

<ParamField path="style" type="Style" optional>
  Style background overload: a [Color](/bindjs/styles/Color), gradient, or [Material](/bindjs/styles/Material) to fill the background.
</ParamField>

<ParamField path="content" type="Component" required>
  Component background overload: a component to render behind this component.
</ParamField>

<ParamField path="props" type="object" required>
  Component background with alignment overload.

  <Expandable title="props">
    <ParamField path="alignment" type="Alignment" required>
      How to position the background component within this component's bounds. See [Alignment](/bindjs/types/Alignment).
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="content" type="Component" required>
  A component to render behind this component, positioned according to `alignment`.
</ParamField>

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: { status: "supported" },
web: { status: "supported" },
}}
/>

**Color background**

```typescript theme={null}
Text("Hello")
    .padding(16)
    .background(Color("blue"))
```

**Gradient background**

```typescript theme={null}
Text("Gradient")
    .padding(16)
    .background(LinearGradient({
        colors: ["purple", "blue"],
        startPoint: "leading",
        endPoint: "trailing"
    }))
```

**Material background**

```typescript theme={null}
Text("Frosted")
    .padding(16)
    .background(Material("thin"))
```

**Component background**

```typescript theme={null}
Text("Labeled")
    .padding(16)
    .background(
        RoundedRectangle(12)
            .foregroundStyle(Color("blue"))
    )
```

**Component background with alignment**

```typescript theme={null}
Text("Badge")
    .padding(16)
    .background(
        { alignment: "topTrailing" },
        Circle()
            .frame({ width: 12, height: 12 })
            .foregroundStyle(Color("red"))
    )
```

## cornerRadius

Rounds the corners of a component.

```typescript theme={null}
.cornerRadius(radius: number)
```

<ParamField path="radius" type="number" required>
  The corner radius in points.
</ParamField>

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: { status: "supported" },
web: { status: "supported" },
}}
/>

`cornerRadius` clips the content at the corners. For more control over the clipping shape, use [clipShape](/bindjs/modifiers/clipShape) with a `RoundedRectangle`.

**Round a card**

```typescript theme={null}
VStack([
    Text("Card Title").font("headline"),
    Text("Card content goes here.")
])
    .padding(16)
    .background(Color("white"))
    .cornerRadius(12)
```

**Round an image**

```typescript theme={null}
Image({ url: "photo.jpg" })
    .resizable()
    .frame({ width: 100, height: 100 })
    .cornerRadius(8)
```

**Pill shape with large radius**

```typescript theme={null}
Text("Tag")
    .padding({ leading: 16, trailing: 16, top: 8, bottom: 8 })
    .background(Color("blue"))
    .foregroundStyle(Color("white"))
    .cornerRadius(20)
```

## border

Adds a border around a component.

```typescript theme={null}
.border(config?: { style: Style; width?: number } | Style | number)
```

<ParamField path="config" type="{ style: Style; width?: number } | Style | number" optional>
  The border configuration. Can be:

  * An object with `style` (a [Color](/bindjs/styles/Color) or gradient) and optional `width`
  * A [Style](/bindjs/styles/Color) value directly (uses default width of 1)
  * A number specifying just the width (uses the foreground style)
</ParamField>

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: { status: "supported" },
web: { status: "supported" },
}}
/>

**Simple color border**

```typescript theme={null}
Text("Bordered")
    .padding(12)
    .border(Color("gray"))
```

**Border with custom width**

```typescript theme={null}
Text("Thick border")
    .padding(12)
    .border({ style: Color("blue"), width: 2 })
```

**Gradient border**

```typescript theme={null}
Text("Gradient border")
    .padding(12)
    .border({
        style: LinearGradient({
            colors: ["red", "blue"],
            startPoint: "leading",
            endPoint: "trailing"
        }),
        width: 2
    })
```

**Combined with corner radius**

```typescript theme={null}
Text("Rounded bordered")
    .padding(12)
    .cornerRadius(8)
    .border({ style: Color("blue"), width: 1 })
```

## shadow

Adds a drop shadow to a component.

```typescript theme={null}
.shadow(props?: {
    radius: number;
    x?: number;
    y?: number;
    color?: Color;
}): Component
```

<ParamField path="props" type="object" optional>
  <Expandable title="properties">
    <ParamField path="radius" type="number" required>
      The blur radius of the shadow in points. Larger values produce a softer, more spread-out shadow.
    </ParamField>

    <ParamField path="x" type="number" optional default="0">
      Horizontal offset of the shadow.
    </ParamField>

    <ParamField path="y" type="number" optional default="0">
      Vertical offset of the shadow.
    </ParamField>

    <ParamField path="color" type="Color" optional>
      The shadow color. Defaults to a semi-transparent black.
    </ParamField>
  </Expandable>
</ParamField>

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: { status: "supported" },
web: { status: "supported" },
}}
/>

**Basic shadow**

```typescript theme={null}
RoundedRectangle(12)
    .frame({ width: 200, height: 100 })
    .foregroundStyle(Color("white"))
    .shadow({ radius: 8 })
```

**Offset shadow**

```typescript theme={null}
Text("Elevated")
    .font("title")
    .padding(16)
    .background(Color("white"))
    .cornerRadius(12)
    .shadow({ radius: 4, x: 0, y: 2 })
```

**Colored shadow**

```typescript theme={null}
Circle()
    .frame({ width: 80, height: 80 })
    .foregroundStyle(Color("blue"))
    .shadow({ radius: 12, color: Color("blue").opacity(0.5) })
```

## See also

* [overlay](/bindjs/modifiers/overlay) — render a component on top of this one
* [clipShape](/bindjs/modifiers/clipShape) — clip the component to an arbitrary shape
* [hidden](/bindjs/modifiers/hidden) — hide a component and remove it from hit testing
* [Color](/bindjs/styles/Color) — color values for foreground, background, and border
* [Material](/bindjs/styles/Material) — frosted-glass background materials
* [Alignment](/bindjs/types/Alignment) — alignment values for component backgrounds
