import { Meta, Source, ArgTypes } from '@storybook/addon-docs/blocks';
import * as SentimentSurfaceStories from './SentimentSurface.story';

<Meta title="Content/SentimentSurface/Developer Guide" />

# SentimentSurface Developer Guide

`SentimentSurface` is a polymorphic container component that establishes a semantic colour context by setting CSS custom properties (tokens) based on sentiment types. It does not apply any default background or text styling - instead, it provides access to sentiment-aware tokens that child components can use to style themselves appropriately.

## Basic Usage

Import and use the component with a required `sentiment` prop:

<Source dark code={`
import { SentimentSurface } from '@transferwise/components';

<SentimentSurface sentiment="negative">Your payment has failed</SentimentSurface>
`} />

### Props

<ArgTypes of={SentimentSurfaceStories} />

## Sentiment Types

The component supports five sentiment types (`negative`, `warning`, `neutral`, `proposition` and `success`), each communicating different types of information:

```tsx
<SentimentSurface sentiment="negative">
  Your payment has failed. Please try again.
</SentimentSurface>

<SentimentSurface sentiment="warning">
  Action required: Please verify your email address.
</SentimentSurface>

<SentimentSurface sentiment="neutral">
  Your account is up to date.
</SentimentSurface>

<SentimentSurface sentiment="proposition">
  Try our new feature and save time on transfers.
</SentimentSurface>

<SentimentSurface sentiment="success">
  Your payment was successful!
</SentimentSurface>
```

---

## Emphasis Levels

Each sentiment type supports two emphasis levels that provide different sets of token values (`base`, `elevated`):

```tsx
<SentimentSurface sentiment="success" emphasis="base">
  Base emphasis - provides tokens suited for subtle contexts
</SentimentSurface>

<SentimentSurface sentiment="success" emphasis="elevated">
  Elevated emphasis - provides tokens suited for prominent contexts
</SentimentSurface>
```

**When to use:**

- **Base**: For inline notifications, subtle callouts, or when sentiment needs to be communicated without drawing too much attention
- **Elevated**: For prominent banners, critical alerts, or when the sentiment should be immediately noticeable

Note: The component does not apply background or text colours by default. Use the provided tokens in your styles to achieve the desired visual effect.

---

## Polymorphic Rendering

The component is fully polymorphic, meaning it can render as any HTML element using the `as` prop while maintaining full type safety.

### Basic Examples

```tsx
// Render as div (default)
<SentimentSurface sentiment="neutral">
  Default div element
</SentimentSurface>

// Render as section
<SentimentSurface sentiment="negative" as="section">
  Semantic section element
</SentimentSurface>

// Render as article
<SentimentSurface sentiment="success" as="article">
  Article element for standalone content
</SentimentSurface>
```

### With HTML Attributes

The component accepts all valid HTML attributes for the rendered element:

```tsx
// Section with ARIA attributes
<SentimentSurface
  sentiment="negative"
  as="section"
  role="alert"
  aria-live="polite"
  aria-atomic="true"
>
  Critical error message
</SentimentSurface>

// Article with data attributes
<SentimentSurface
  sentiment="proposition"
  as="article"
  data-tracking-id="promo-banner"
  data-position="top"
>
  Promotional content
</SentimentSurface>
```

### Type Safety

TypeScript provides full type checking for HTML attributes based on the `as` prop:

```tsx
// ✅ Valid - section supports these attributes
<SentimentSurface as="section" role="region" aria-labelledby="heading">
  Content
</SentimentSurface>

// ❌ TypeScript error - 'href' is not valid for 'div'
<SentimentSurface as="div" href="/link">
  Content
</SentimentSurface>
```

---

## Nesting Sentiment Surfaces

Sentiment surfaces can be nested to create layered contexts. Each nested surface establishes its own colour context through CSS custom properties.

### Basic Nesting

```tsx
<SentimentSurface sentiment="negative" emphasis="base">
  <Title size="large">Payment Failed</Title>
  <Body>There was an issue processing your payment.</Body>

  <SentimentSurface sentiment="neutral" emphasis="elevated">
    <Title size="small">What happened?</Title>
    <Body>Your card was declined by your bank.</Body>
  </SentimentSurface>
</SentimentSurface>
```

### Multi-Level Nesting

```tsx
<SentimentSurface sentiment="success" emphasis="base">
  Outer: Payment successful
  <SentimentSurface sentiment="neutral" emphasis="elevated">
    Inner: Transaction details
    <SentimentSurface sentiment="warning" emphasis="base">
      Deepest: Additional fees may apply
    </SentimentSurface>
  </SentimentSurface>
</SentimentSurface>
```

### Nesting with Different Elements

```tsx
<SentimentSurface sentiment="negative" as="section">
  <Title size="large">Error Section</Title>

  <SentimentSurface sentiment="neutral" as="article">
    <Title size="small">Details</Title>
    <Body>More information about the error.</Body>
  </SentimentSurface>

  <SentimentSurface sentiment="proposition" as="aside">
    <Body>Need help? Contact support.</Body>
  </SentimentSurface>
</SentimentSurface>
```

---

## CSS Custom Properties (Tokens)

The component sets CSS custom properties (CSS variables) that child components can use to style themselves according to the sentiment context. The component itself does not apply any visual styling - it simply makes these tokens available for use in your own styles or by sentiment-aware child components.

### Available Tokens

Each `SentimentSurface` sets tokens for content, interactive elements, and background surfaces. See the [Tokens story](?path=/story/content-sentimentsurface--tokens) for a visual demonstration of all tokens across sentiments and emphasis levels:

#### Content Tokens

```css
--color-sentiment-content-primary
--color-sentiment-content-primary-hover
--color-sentiment-content-primary-active
```

#### Interactive Primary Tokens

```css
--color-sentiment-interactive-primary
--color-sentiment-interactive-primary-hover
--color-sentiment-interactive-primary-active
```

#### Interactive Secondary Tokens

```css
--color-sentiment-interactive-secondary
--color-sentiment-interactive-secondary-hover
--color-sentiment-interactive-secondary-active
```

#### Interactive Secondary Neutral Tokens

```css
--color-sentiment-interactive-secondary-neutral
--color-sentiment-interactive-secondary-neutral-hover
--color-sentiment-interactive-secondary-neutral-active
```

#### Interactive Control Tokens

```css
--color-sentiment-interactive-control
--color-sentiment-interactive-control-hover
--color-sentiment-interactive-control-active
```

#### Background Surface Tokens

```css
--color-sentiment-background-surface
--color-sentiment-background-surface-hover
--color-sentiment-background-surface-active
```

### Using Tokens in Component Styles

Components can reference these tokens with fallbacks to maintain functionality outside of a `SentimentSurface`:

```css
.wds-Button {
  /* Primary button uses interactive primary tokens */
  --Button-background: var(--color-sentiment-interactive-primary, var(--color-interactive-accent));
  --Button-background-hover: var(
    --color-sentiment-interactive-primary-hover,
    var(--color-interactive-accent-hover)
  );
  --Button-background-active: var(
    --color-sentiment-interactive-primary-active,
    var(--color-interactive-accent-active)
  );

  /* Button text color uses control tokens */
  --Button-color: var(--color-sentiment-interactive-control, var(--color-interactive-control));
  --Button-color-hover: var(
    --color-sentiment-interactive-control-hover,
    var(--color-interactive-control-hover)
  );
  --Button-color-active: var(
    --color-sentiment-interactive-control-active,
    var(--color-interactive-control-active)
  );
}

.wds-Button--secondary {
  /* Secondary button uses secondary tokens */
  --Button-background: var(
    --color-sentiment-interactive-secondary,
    var(--color-interactive-neutral)
  );
  --Button-background-hover: var(
    --color-sentiment-interactive-secondary-hover,
    var(--color-interactive-neutral-hover)
  );
  --Button-color: var(--color-sentiment-interactive-primary, var(--color-interactive-primary));
}
```

### Example: Button in Sentiment Context

```tsx
import { Button, Body } from '@transferwise/components';

// Button automatically adapts to the sentiment context
<SentimentSurface sentiment="success">
  <Body>Your payment was successful!</Body>
  <Button v2 priority="primary">View Receipt</Button>
  <Button v2 priority="secondary">Send Another</Button>
</SentimentSurface>

// Same buttons in different sentiment context
<SentimentSurface sentiment="negative">
  <Body>Payment failed</Body>
  <Button v2 priority="primary">Try Again</Button>
  <Button v2 priority="secondary">Cancel</Button>
</SentimentSurface>
```

The buttons will automatically use appropriate colours based on the sentiment context.

### Applying Sentiment Tokens

To visually style content within a SentimentSurface, use the provided tokens in your styles:

```tsx
// Apply tokens via inline styles
<SentimentSurface sentiment="warning">
  <div
    style={{
      padding: '24px',
      borderRadius: '16px',
      backgroundColor: 'var(--color-sentiment-background-surface)',
      color: 'var(--color-sentiment-content-primary)',
    }}
  >
    This content uses the sentiment tokens for styling
  </div>
</SentimentSurface>
```

### Creating Custom Components with Sentiment Tokens

You can create your own components that respect sentiment context:

```tsx
// CustomCard.css
.custom-card {
  background-color: var(
    --color-sentiment-background-surface,
    var(--color-background-surface)
  );
  color: var(
    --color-sentiment-content-primary,
    var(--color-content-primary)
  );
  border: 1px solid var(
    --color-sentiment-interactive-secondary,
    var(--color-border-neutral)
  );
}

.custom-card:hover {
  background-color: var(
    --color-sentiment-background-surface-hover,
    var(--color-background-surface-hover)
  );
}

.custom-card-link {
  color: var(
    --color-sentiment-interactive-primary,
    var(--color-interactive-primary)
  );
}

.custom-card-link:hover {
  color: var(
    --color-sentiment-interactive-primary-hover,
    var(--color-interactive-primary-hover)
  );
}
```

```tsx
// CustomCard.tsx
function CustomCard({ children }) {
  return (
    <div className="custom-card">
      {children}
      <a href="#" className="custom-card-link">
        Learn more
      </a>
    </div>
  );
}

// Usage
<SentimentSurface sentiment="warning">
  <CustomCard>This card adapts to the warning sentiment</CustomCard>
</SentimentSurface>;
```

---

## Accessibility Considerations

### Semantic HTML

Use appropriate HTML elements via the `as` prop to ensure proper document structure:

```tsx
// ✅ Good - semantic HTML for alerts
<SentimentSurface
  sentiment="negative"
  as="section"
  role="alert"
  aria-live="assertive"
>
  Critical error: Payment failed
</SentimentSurface>

// ✅ Good - article for standalone content
<SentimentSurface sentiment="proposition" as="article">
  <Title size="large">New Feature Available</Title>
  <Body>Try our new instant transfer feature...</Body>
</SentimentSurface>
```

### ARIA Attributes

Add appropriate ARIA attributes for screen readers:

```tsx
// For errors or critical warnings
<SentimentSurface
  sentiment="negative"
  role="alert"
  aria-live="assertive"
  aria-atomic="true"
>
  Error: Your session has expired
</SentimentSurface>

// For important but not critical information
<SentimentSurface
  sentiment="warning"
  role="status"
  aria-live="polite"
>
  Please verify your email address
</SentimentSurface>

// For regions with headings
<SentimentSurface
  sentiment="success"
  as="section"
  role="region"
  aria-labelledby="success-heading"
>
  <Title id="success-heading" size="large">Payment Successful</Title>
  <Body>Your payment has been processed.</Body>
</SentimentSurface>
```

### Color Contrast

The tokens provided by the component are designed with WCAG AA contrast ratios in mind:

- **Base emphasis**: Tokens provide sufficient contrast for body text
- **Elevated emphasis**: Tokens provide higher contrast, often with inverted colours

Always test your content for contrast compliance, especially when:

- Applying tokens via `style` or `className`
- Using small text sizes
- Displaying important information

### Don't Rely on Color Alone

Sentiment should not be conveyed through colour alone. Always include:

```tsx
// ✅ Good - includes text and icons
<SentimentSurface sentiment="negative">
  <ErrorIcon aria-hidden="true" />
  <strong>Error:</strong> Payment failed
</SentimentSurface>

// ❌ Bad - relies only on colour
<SentimentSurface sentiment="negative">
  Payment failed
</SentimentSurface>
```

### Focus Management

When using for alerts, consider focus management:

```tsx
function ErrorBanner({ error }) {
  const errorRef = useRef<HTMLElement>(null);

  useEffect(() => {
    if (error && errorRef.current) {
      errorRef.current.focus();
    }
  }, [error]);

  if (!error) return null;

  return (
    <SentimentSurface
      ref={errorRef}
      sentiment="negative"
      as="section"
      role="alert"
      tabIndex={-1}
      aria-live="assertive"
    >
      {error.message}
    </SentimentSurface>
  );
}
```

---

## Best Practices

### Do's

✅ Use semantic HTML elements via the `as` prop  
✅ Include ARIA attributes for screen readers  
✅ Combine colour with icons and text for clarity  
✅ Use appropriate sentiment types for the content  
✅ Leverage CSS tokens for consistent theming  
✅ Test contrast ratios for accessibility  
✅ Provide focus management for critical alerts

### Don'ts

❌ Don't rely solely on colour to convey meaning  
❌ Don't nest too many levels (3+ levels can be confusing)  
❌ Don't override sentiment tokens without good reason  
❌ Don't use `sentiment="negative"` for informational content  
❌ Don't forget to test with screen readers

---

## Further Reading

- [Component Source Code](./SentimentSurface.tsx)
- [Storybook Examples](?path=/docs/content-sentimentsurface--docs)
- [WCAG Color Contrast Guidelines](https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html)
- [ARIA Live Regions](https://www.w3.org/WAI/WCAG21/Understanding/status-messages.html)
