hyperdx/agent_docs/code_style.md
Elizabet Oliveira 72d4642b6e
feat: add link variant for Button and ActionIcon (#1938)
## Summary

- Adds a new `variant="link"` for `Button` and `ActionIcon` that renders as a plain text link — no background, no border, no padding. Text is muted by default and brightens on hover (adapts to light/dark mode).
- Adds a **Brand** theme switcher to the Storybook toolbar so stories can be previewed in both HyperDX and ClickStack themes.
- Documents the new variant in `code_style.md` and adds comprehensive Storybook stories.

## Changes

| File | What |
|------|------|
| `themes/hyperdx/mantineTheme.ts` | `link` variant for Button (`vars` + `classNames`) and ActionIcon (`vars` + `classNames`) |
| `themes/clickstack/mantineTheme.ts` | Same for ClickStack theme |
| `styles/variants.module.scss` | Hover color transition and transparent disabled state for link variants |
| `stories/Button.stories.tsx` | Link variant in CustomVariants, DisabledStates, LoadingStates |
| `stories/ActionIcon.stories.tsx` | Link variant in CustomVariants, DisabledStates, LoadingStates |
| `.storybook/preview.tsx` | Brand theme switcher (HyperDX / ClickStack) in toolbar |
| `agent_docs/code_style.md` | Documented link variant usage and guidelines |

## Test plan

- [ ] Verify `variant="link"` renders without background/border/padding in Storybook
- [ ] Verify hover brightens text in both light and dark modes
- [ ] Verify disabled state shows reduced opacity with no background
- [ ] Switch brand theme in Storybook toolbar and confirm both HyperDX and ClickStack render correctly


Made with [Cursor](https://cursor.com)
2026-03-18 18:25:36 +00:00

3.9 KiB

Code Style & Best Practices

Note

: Pre-commit hooks handle formatting automatically. Focus on implementation patterns.

TypeScript

  • Avoid any - use proper typing
  • Use Zod schemas for runtime validation
  • Define clear interfaces for data structures
  • Implement proper error boundaries

Code Organization

  • Single Responsibility: One clear purpose per component/function
  • File Size: Max 300 lines - refactor when approaching limit
  • DRY: Reuse existing functionality; consolidate duplicates
  • In-Context Learning: Explore similar files before implementing

React Patterns

  • Functional components with hooks (not class components)
  • Extract reusable logic into custom hooks
  • Define TypeScript interfaces for props
  • Use proper keys for lists, memoization for expensive computations

Mantine UI Components

The project uses Mantine UI with custom variants defined in packages/app/src/theme/mantineTheme.ts.

Button & ActionIcon Variants (REQUIRED)

ONLY use these variants for Button and ActionIcon components:

Variant Use Case Example
variant="primary" Primary actions (Submit, Save, Create, Run) <Button variant="primary">Save</Button>
variant="secondary" Secondary actions (Cancel, Clear, auxiliary actions) <Button variant="secondary">Cancel</Button>
variant="danger" Destructive actions (Delete, Remove, Rotate API Key) <Button variant="danger">Delete</Button>
variant="link" Link-style actions with no background or border (View Details, navigation-style CTAs) <Button variant="link">View Details</Button>

DO NOT USE (Forbidden Patterns)

The following patterns are NOT ALLOWED for Button and ActionIcon:

// ❌ WRONG - Don't use these
<Button variant="light" color="green">Save</Button>
<Button variant="light" color="gray">Cancel</Button>
<Button variant="light" color="red">Delete</Button>
<Button variant="outline" color="green">Save</Button>
<Button variant="outline" color="gray">Cancel</Button>
<Button variant="outline" color="red">Delete</Button>
<Button variant="filled" color="gray">Cancel</Button>
<Button variant="default">Cancel</Button>
<ActionIcon variant="light" color="red">...</ActionIcon>
<ActionIcon variant="filled" color="gray">...</ActionIcon>

// ✅ CORRECT - Use custom variants
<Button variant="primary">Save</Button>
<Button variant="secondary">Cancel</Button>
<Button variant="danger">Delete</Button>
<Button variant="link">View Details</Button>
<ActionIcon variant="primary">...</ActionIcon>
<ActionIcon variant="secondary">...</ActionIcon>
<ActionIcon variant="danger">...</ActionIcon>
<ActionIcon variant="link">...</ActionIcon>

Link variant details: Renders with no background, no border, and muted text color. On hover, text brightens to full contrast. Use for link-style CTAs that should blend into surrounding content (e.g., "View Details", "View Full Trace").

Note: variant="filled" is still valid for form inputs (Select, TextInput, etc.), just not for Button/ActionIcon.

Icon-Only Buttons → ActionIcon

If a Button only contains an icon (no text), use ActionIcon instead:

// ❌ WRONG - Button with only an icon
<Button variant="secondary" px="xs">
  <IconRefresh size={18} />
</Button>

// ✅ CORRECT - Use ActionIcon for icon-only buttons
<ActionIcon variant="secondary" size="input-sm">
  <IconRefresh size={18} />
</ActionIcon>

This pattern cannot be enforced by ESLint and requires manual code review.

Refactoring

  • Edit files directly - don't create component-v2.tsx copies
  • Look for duplicate code across the affected area
  • Verify all callers and integrations after changes
  • Refactor to improve clarity or reduce complexity, not just to change

File Naming

  • Clear, descriptive names following package conventions
  • Avoid "temp", "refactored", "improved" in permanent filenames