# Best Practices

## ✅ Do

### Use semantic props for accessibility

```html
<!-- Provide a label for icon-only buttons -->
<r-button icon="cross" r-aria-label="Close dialog"></r-button>

<!-- Use label when visible text is absent -->
<r-icon-button name="search" label="Search products"></r-icon-button>
```

### Always provide `label` for form controls

Every form control must have a `label` prop (or a `<slot name="label">`). Never rely on placeholder text as a label — placeholder disappears on input and is not announced consistently by screen readers.

```html
<!-- ✅ correct -->
<r-input label="Email address" name="email" type="email"></r-input>

<!-- ❌ wrong — placeholder is not a label -->
<r-input placeholder="Email address" name="email" type="email"></r-input>
```

### Use `name` prop for form submission

All form controls participating in form submission require a `name` prop:

```html
<r-input label="Full name" name="fullname" required></r-input>
```

### Use component event names (not native event names)

Components emit prefixed custom events. Native DOM events (`click`, `change`, `input`) fire on the host element but carry no component-specific payload. Use `rClick`, `rChange`, `rInput`, etc.

```js
// ✅ correct
el.addEventListener('rClick', handler);

// ❌ avoid for form data — no detail payload
el.addEventListener('click', handler);
```

### Use `ifDefined()` in lit-html templates

Always use `ifDefined()` for optional attributes in Storybook stories:

```ts
html`<r-button variant=${ifDefined(args.variant)}></r-button>`
```

### Use component props for validation and error messages

Components render `r-hint` internally using the `error` prop and internal validation state:

```html
<r-input label="Name" name="name" type="text" value-missing-message="Provide your name" required></r-input>
```

### Use slots for composition

Content projection into Shadow DOM components is done through named and default slots:

```html
<r-alert status="warning" headline="Important notice">
  <span>Your account will expire in 3 days.</span>
</r-alert>
```

### Use CSS variables or CSS parts for custom styling

To apply custom styles to components, use CSS Custom Properties (`var(--r-*)`) or CSS Shadow Parts (`::part()`).

```scss
/* ✅ correct */
/* Using CSS Custom Properties */
r-badge {
  --r-badge--content--max-width: 8rem;
}

/* Using CSS Shadow Parts */
r-badge::part(content) {
  max-width: 8rem;
}

/* ❌ wrong — does not work due to Shadow DOM encapsulation */
r-badge .r-badge--content {
  max-width: 8rem;
}
```

### Preserve inherited theme context

Set `data-theme`, `data-r-ui`, and `data-r-ui-brand` on an application wrapper, not on a component
only to restyle it. Components inherit semantic tokens through Shadow DOM.

```html
<div data-theme="dark" data-r-ui="alta" data-r-ui-brand="partner-name">
  <r-badge>Overdue</r-badge>
</div>
```

Use documented component custom properties with semantic token values. Do not pair `data-theme`
with a UI or brand selector in authored token CSS; use one flat UI or brand selector with
`light-dark()` when mode values differ.

---

## ❌ Don't

### Don't hardcode colors, spacing, or font values

Components must use `var(--r-*)` tokens. Never use raw hex, px sizes, or font-family strings.

```scss
/* ❌ wrong */
color: #1a1a1a;
font-size: 14px;

/* ✅ correct */
color: var(--r-text-regular);
font-size: var(--r-font-size-300);
```

---

## Accessibility Checklist

When using web components:

- [ ] Every interactive component has visible text, `r-aria-label`, or component-specific accessible label such as `r-icon-button`'s `label`
- [ ] Form controls have a `label` prop (not just `placeholder`)
- [ ] Status messages use `r-alert` with `announced` (default `true`) for screen reader announcements
- [ ] Dialogs (`r-dialog`) trap focus and return focus on close
- [ ] Color-only status indicators are supplemented with text or icons
- [ ] Keyboard navigation works without a mouse (Tab, Enter, Space, Arrow keys)
