# 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 rAriaLabel when visible text is absent or insufficient -->
<r-icon-button name="search" r-aria-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;
}
```

---

## ❌ 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 a visible or programmatic label (`r-aria-label` or visible text)
- [ ] 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)
