# Choosing CSS selectors for tours and smart tips

Highlight steps target a DOM element via a CSS selector (`domQuery`). Selector quality decides whether a tour survives the next redesign.

## Selector preference order

1. **A dedicated data attribute you add to the code** — `[data-produktly="new-project-btn"]`. As a coding agent working in the customer's repo, this is your superpower: ADD the attribute to the component and use it. It is refactor-proof and self-documenting.
2. An existing stable `data-testid` / `data-test` attribute: `[data-testid='new-project']`.
3. A semantic id: `#new-project-button` (only if ids are stable and unique).
4. Stable ARIA/role/name combinations: `button[aria-label='Create project']`.
5. LAST RESORT: class names or DOM paths (`.btn-primary`, `div > ul > li:nth-child(2)`). Generated class names (CSS modules, Tailwind JIT-ish hashes, styled-components) break on every build — never use them.

## Rules of thumb

- The selector must match EXACTLY ONE element on the page where the step runs. Test with `document.querySelectorAll(sel).length === 1`.
- The element must exist when the step shows. If it renders late (async data), the tour waits up to the tour's `timeout` setting (default 5s) and then falls back to a centered modal — or skips the step if the step sets `skipIfNotFound`.
- For elements inside dropdowns/menus that must stay open, set the step's `expandSelectors` to include the dropdown container.
- Prefer targeting the interactive element itself (the button, not its wrapping div) — highlight steps can let users click the highlighted element (`allowClickEvents`, default true).

## Workflow for a coding agent

1. Find the UI element in the customer's codebase.
2. Add `data-produktly="<kebab-case-name>"` to it (a one-attribute change — safe, invisible to users).
3. Use `[data-produktly='<name>']` as the step's `domQuery`.
4. Repeat per highlight step; commit the attribute additions together with a note that Produktly tours reference them.
