Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
f76034b
Add ShadCN MCP
tjementum Dec 23, 2025
40d8043
Add BaseUI and ShadCN component configuraiton
tjementum Dec 23, 2025
4ffdd80
Update frontend rules to document ShadCN 2.0 with BaseUI patterns
tjementum Dec 24, 2025
b51f9a8
Migrate Button component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
5762086
Migrate Input component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
73027df
Migrate Label component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
5fa811e
Migrate Badge component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
3829346
Migrate Separator component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
74e4f4f
Migrate TextField component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
e4eb0b7
Migrate Checkbox component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
0d1e781
Migrate RadioGroup component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
396e6e8
Migrate Select component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
c6f955e
Migrate Dialog and Modal components from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
1bc6c56
Migrate AlertDialog component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
0f15a3c
Migrate Menu components from React Aria to ShadCN 2.0 DropdownMenu
tjementum Dec 24, 2025
0da2f51
Migrate Popover component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
03049fe
Migrate Tooltip component from React Aria to BaseUI
tjementum Dec 24, 2025
7845222
Migrate Table component from React Aria to ShadCN 2.0
tjementum Dec 24, 2025
9273037
Migrate Toast component from React Aria to Sonner and replace custom …
tjementum Dec 25, 2025
fe47463
Migrate OneTimeCodeInput component from React Aria to ShadCN 2.0 Inpu…
tjementum Dec 25, 2025
c3b8e8f
Migrate SearchField component from React Aria to ShadCN composition
tjementum Dec 25, 2025
5a4e9b3
Migrate NumberField component from React Aria to ShadCN composition
tjementum Dec 25, 2025
ed68000
Migrate Link component from React Aria to native/ShadCN composition
tjementum Dec 25, 2025
de22bee
Migrate Heading and Text components from React Aria to native HTML el…
tjementum Dec 25, 2025
05a588c
Migrate Breadcrumbs component from React Aria to ShadCN 2.0
tjementum Dec 25, 2025
3e96c25
Migrate Form component from React Aria to native HTML form with FormV…
tjementum Dec 25, 2025
ac94b80
Migrate ListBox component from React Aria to native HTML
tjementum Dec 25, 2025
6db9d00
Migrate ToggleButton component from React Aria to ShadCN 2.0 Toggle
tjementum Dec 25, 2025
8b2bfc7
Migrate Calendar and DatePicker components to ShadCN compatible React…
tjementum Dec 25, 2025
5c362e0
Delete all unused React Aria components
tjementum Dec 25, 2025
7dca86b
Remove remaining React Aria Component dependencies and complete ShadC…
tjementum Dec 25, 2025
eb96f61
Update Dialog component with DialogBody for mobile full-screen and sc…
tjementum Jan 18, 2026
9d8a232
Update DialogClose to support DirtyDialog cancel bypass via type='reset'
tjementum Jan 18, 2026
7efe621
Update Select component to add larger touch targets and display the d…
tjementum Jan 18, 2026
8dc08bf
Update BreadcrumbLink to include text-sm styling
tjementum Jan 18, 2026
fd39238
Update DropdownMenu with w-auto width and larger touch targets
tjementum Jan 18, 2026
887c3f4
Update Button destructive variant with solid background for accessibi…
tjementum Jan 18, 2026
20fed87
Stabilize Firefox E2E tests under parallel load using dispatchEvent f…
tjementum Jan 19, 2026
005e81b
Use AlertDialogMedia to show icons in destructive dialogs
tjementum Jan 19, 2026
6033bd9
Update TablePagination to use ShadCN pagination
tjementum Jan 19, 2026
63606c7
Replace custom Avatar with ShadCN 2.0 Avatar component
tjementum Jan 19, 2026
e393a6f
Replace custom TenantLogo implementation with ShadCN Avatar wrapper
tjementum Jan 20, 2026
1756b36
Remove custom Image component in favor of native img with localized a…
tjementum Jan 20, 2026
316e8fa
Standardize heading elements with global styles and remove Heading co…
tjementum Jan 20, 2026
ba2f7d5
Standardize icon sizing to use size-N utility
tjementum Jan 20, 2026
143aae5
Replace deprecated social media icons and fix tooltips in PublicFooter
tjementum Jan 21, 2026
4179db3
Enable hot reload for shared-webapp monorepo packages with source bui…
tjementum Jan 20, 2026
e9dbcfb
Add README documenting UI component inventory and stock ShadCN diverg…
tjementum Jan 21, 2026
ffeab3a
Ensure input and other UI components have consistent background colors
tjementum Jan 22, 2026
86b209f
Update color theme to macOS-inspired dark mode
tjementum Jan 22, 2026
f3aa4f0
Ensure consistent focus ring when tabbing through the app using outli…
tjementum Jan 22, 2026
bf78d77
Fix TenantSelector logo animation during sidebar collapse and expand
tjementum Jan 22, 2026
05b6dbe
Increase interactive control heights to 44px for Apple HIG compliance…
tjementum Jan 22, 2026
5c8994b
Fix support dialog not opening from mobile menu by moving state to pa…
tjementum Jan 22, 2026
05ea6aa
Reorder keyboard navigation to prioritize skip link and defer sidebar…
tjementum Jan 22, 2026
768047b
Ensure CLI uses correct Node version by checking version manager inst…
tjementum Jan 23, 2026
b8b454d
Update documentation to reflect ShadCN 2.0 with Base UI migration
tjementum Jan 27, 2026
432f550
Remove generic success and HTTP status code titles from toasts and in…
tjementum Jan 27, 2026
cb33dc4
Replace cursor-default with cursor-pointer on interactive ShadCN comp…
tjementum Jan 27, 2026
2e797ee
Increase side menu max width from 300px to 350px
tjementum Jan 27, 2026
79b80d2
Add arrow key navigation and roving tabindex support to the Table com…
tjementum Jan 27, 2026
9f870ee
Make side pane close button keyboard-accessible by using a proper But…
tjementum Jan 27, 2026
e2a535c
Make table column headers keyboard-accessible
tjementum Jan 27, 2026
62d1b55
Eliminate duplicate user list API requests by isolating desktop and m…
tjementum Jan 27, 2026
15c2d17
Fix enabled option placement in api.useQuery calls and document corre…
tjementum Jan 27, 2026
72d844c
Stop table keyboard navigation from wrapping around at first and last…
tjementum Jan 27, 2026
7364f3d
Auto-scroll table to selected row for deep link navigation
tjementum Jan 27, 2026
3711365
Standardize z-index layering to use Tailwind defaults and semantic la…
tjementum Jan 27, 2026
d90bc0a
Simplify UserTable column visibility to single mobile/desktop breakpoint
tjementum Jan 27, 2026
cf9606c
Simplify UserQuerying and UserToolbar replacing event listeners with …
tjementum Jan 27, 2026
b1d1be8
Add consistent height and full-width mobile styling to dialog footer …
tjementum Jan 30, 2026
d9ae65d
Remove responsive hiding from recycle bin toolbar buttons
tjementum Jan 30, 2026
a4962a3
Remove SearchField component and use InputGroup with Field wrapper fo…
tjementum Jan 30, 2026
0ad8542
Add ShadCN Empty component and use it for empty states in user tables
tjementum Jan 31, 2026
45c3646
Add Skeleton component and replace spinners with skeleton loading states
tjementum Jan 31, 2026
d31b0a8
Set Monday as first day of week in Calendar component
tjementum Jan 31, 2026
32f1c56
Add ShadCN Tabs component and refactor UserTabNavigation to use it
tjementum Jan 31, 2026
aea3765
Add ShadCN Alert component with warning and info variants
tjementum Jan 31, 2026
7cf8ff2
Add ShadCN Card component and refactor dashboard, sessions, and legal…
tjementum Jan 31, 2026
43bc448
Add ScrollArea component and fix session list scrolling in SessionsModal
tjementum Jan 31, 2026
743b17e
Add reusable SidePane component and refactor UserProfileSidePane to u…
tjementum Jan 31, 2026
ffcaaaf
Remove sm:max-w-md constraint from DialogContent and add w-dialog-sm …
tjementum Jan 31, 2026
d86d0a7
Refactor ChangeUserRoleDialog to use ShadCN Choice Card pattern with …
tjementum Jan 31, 2026
5fdc8d2
Improve role change discoverability with edit icon and disabled state…
tjementum Jan 31, 2026
97e564e
Use Field component for avatar and logo upload sections
tjementum Jan 31, 2026
366fbff
Localize Calendar and DateRangePicker based on app locale setting
tjementum Jan 31, 2026
20f81a0
Add locale-aware date formatting using browser Intl API
tjementum Jan 31, 2026
821aa7a
Increase mobile font sizes globally using rem-based root font-size sc…
tjementum Feb 1, 2026
ec8a274
Reduce mobile menu button size and adjust position to match iOS conve…
tjementum Feb 2, 2026
591fbae
Improve mobile scroll behavior with sticky toolbar and scroll-away he…
tjementum Feb 2, 2026
cdf2ca0
Move Pending badge to second line on mobile to prevent horizontal scroll
tjementum Feb 2, 2026
180551f
Add press feedback on input components by changing the background for…
tjementum Feb 2, 2026
94e6f6d
Make tooltips work with click/tap instead of hover-only for mobile su…
tjementum Feb 2, 2026
f455139
Enhance DateRangePicker range editing with proper click tracking and …
tjementum Feb 2, 2026
d850bdb
Move DateRangePicker to second position in filter controls for better…
tjementum Feb 2, 2026
920f098
Prevent page flash when opening dialogs from mobile menu
tjementum Feb 3, 2026
b34b2fd
Add ShadCN ContextMenu component with long-press support for mobile u…
tjementum Feb 3, 2026
b02aff3
Balance login and signup form widths after mobile font scaling changes
tjementum Feb 3, 2026
c8153db
Make buttons full-width on mobile by default
tjementum Feb 3, 2026
1b8f2d9
Reduce gap between headings and separators to align horizontal divide…
tjementum Feb 3, 2026
ea9c7bd
Make date range picker selection visible on first click
tjementum Feb 3, 2026
c72e2c6
Change to rem-based sizes to allow for scaling the UI while maintaini…
tjementum Feb 5, 2026
40d9a16
Add configurable zoom level via --zoom-level CSS variable with localS…
tjementum Feb 5, 2026
96bee56
Add collapsible breadcrumbs that progressively collapse middle items …
tjementum Feb 5, 2026
219d181
Convert AppLayout and side menu to rem-based sizing
tjementum Feb 7, 2026
93240e4
Localize aria-labels in legal and footer pages and update translation…
tjementum Feb 7, 2026
88ec1a5
Remove git cherry-pick from blocked bash hook commands
tjementum Jan 14, 2026
1d91199
Replace Tailwind *: and **: variants with [&>*]: and [&_*]: to fix mo…
tjementum Feb 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 37 additions & 10 deletions .agent/rules/end-to-end-tests/end-to-end-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,34 +80,59 @@ These rules outline the structure, patterns, and best practices for writing end-
- Don't add timeouts to `.click()`, `.waitForSelector()`, etc.
- Global timeout configuration is handled in the shared Playwright—don't change this

8. Write deterministic tests for reliable testing:
8. Dropdown Menu Animation Handling:
- When clicking dropdown menu items (DropdownMenu, user profile menu, etc.), use `.dispatchEvent("click")` instead of regular `.click()`
- This is required because the DropdownMenu component has a 100ms animation and under parallel load Firefox doesn't reliably process regular clicks
- Pattern: Click trigger button, wait for menu visible, click menu item with dispatchEvent, verify menu closes
- Always wait for the menu to be visible before clicking: `await expect(page.getByRole("menu")).toBeVisible();`
- Don't use `waitForTimeout()` for menu animations - it causes focus loss which closes the dropdown

9. Write deterministic tests for reliable testing:
- Each test should have a clear, linear flow of actions and assertions
- Don't use if statements, custom error handling, or try/catch blocks in tests
- Don't use regular expressions in tests—use simple string matching instead

9. What to test:
- Enter invalid values such as empty strings, only whitespace characters, long strings, negative numbers, Unicode, etc.
- Tooltips, keyboard navigation, accessibility, validation messages, translations, responsiveness, etc.
10. What to test:
- Enter invalid values such as empty strings, only whitespace characters, long strings, negative numbers, Unicode, etc.
- Tooltips, keyboard navigation, accessibility, validation messages, translations, responsiveness, etc.

10. Test Fixtures and Page Management:
11. Test Fixtures and Page Management:
- Use appropriate fixtures: `{ page }` for basic tests, `{ anonymousPage }` for tests with existing tenant/owner but not logged in, `{ ownerPage }`, `{ adminPage }`, `{ memberPage }` for authenticated tests
- Destructure anonymous page data: `const { page, tenant } = anonymousPage; const existingUser = tenant.owner;`
- Pre-logged in users (`ownerPage`, `adminPage`, `memberPage`) are isolated between workers and will not conflict between tests
- When using pre-logged in users, do not put the tenant or user into an invalid state that could affect other tests

11. Test Data and Constants:
12. Test Data and Constants:
- Use underscore separators: `const timeout = 30_000; // 30 seconds`
- Generate unique data: `const email = uniqueEmail();`
- Use faker.js to generate realistic test data: `const firstName = faker.person.firstName(); const email = faker.internet.email();`
- Long string testing: `const longEmail = \`${"a".repeat(90)}@example.com\`; // 101 characters total`

12. Memory Management in End-to-End Tests:
13. Memory Management in End-to-End Tests:
- Playwright automatically handles browser context cleanup after tests
- Manual cleanup steps are unnecessary—focus on test clarity over micro-optimizations
- End-to-End test suites have minimal memory leak concerns due to their limited scope and duration

## Examples

### Dropdown Menu Clicks
```typescript
// ✅ DO: Use dispatchEvent for menu item clicks
await page.getByRole("button", { name: "User profile menu" }).click();
const menu = page.getByRole("menu");
await expect(menu).toBeVisible();
const menuItem = page.getByRole("menuitem", { name: "Log out" });
await expect(menuItem).toBeVisible();
await menuItem.dispatchEvent("click");

// ❌ DON'T: Use waitForTimeout - causes focus loss and menu closure
await page.getByRole("button", { name: "User profile menu" }).click();
const menu = page.getByRole("menu");
await expect(menu).toBeVisible();
await page.waitForTimeout(200); // Focus is lost, menu closes during wait
await page.getByRole("menuitem", { name: "Log out" }).click(); // Fails - menu is closed
```

### ✅ Good Step Naming Examples
```typescript
// ✅ DO: Business action + details & expected outcome
Expand All @@ -126,10 +151,12 @@ await step("Sign up with valid credentials & verify account creation")(async ()

await step("Update user role to admin & verify permission change")(async () => {
const userRow = page.locator("tbody tr").first();

await userRow.getByLabel("User actions").click();
await page.getByRole("menuitem", { name: "Change role" }).click();

const menu = page.getByRole("menu");
await expect(menu).toBeVisible();
await page.getByRole("menuitem", { name: "Change role" }).dispatchEvent("click");

await expect(page.getByRole("alertdialog", { name: "Change user role" })).toBeVisible();
})();
```
Expand Down
12 changes: 6 additions & 6 deletions .agent/rules/frontend/form-with-validation.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
---
trigger: glob
globs: **/*.tsx
description: Rules for forms with validation using React Aria Components
description: Rules for forms with validation using ShadCN 2.0 components
---
# Form With Validation

Guidelines for implementing forms with validation in the frontend, covering UI components, mutation handling, and validation error display.

## Implementation

1. Use React Aria Components from `@repo/ui/components` for form elements
1. Use ShadCN components from `@repo/ui/components` for form elements
2. Use `api.useMutation` or TanStack's `useMutation` for form submissions
3. Use the custom `mutationSubmitter` to handle form submission and data mapping
4. Handle validation errors using the `validationErrors` prop from the mutation error
5. Show loading state in submit buttons
5. Show loading state in submit buttons using `disabled={mutation.isPending}`
6. For complex scenarios with multiple API calls, create a custom mutation with a `mutationFn`

## Anti-patterns
Expand Down Expand Up @@ -66,7 +66,7 @@ export function UserProfileForm({ user }) {
defaultValue={user?.title}
/>

<Button type="submit" isDisabled={updateUserMutation.isPending}>
<Button type="submit" disabled={updateUserMutation.isPending}>
{updateUserMutation.isPending ? <Trans>Saving...</Trans> : <Trans>Save changes</Trans>}
</Button>
</Form>
Expand Down Expand Up @@ -105,7 +105,7 @@ function BadUserProfileForm({ user }) {
<TextField name="lastName" defaultValue={user?.lastName} isRequired />
<TextField name="title" defaultValue={user?.title} />

<Button type="submit" isDisabled={isLoading}>
<Button type="submit" disabled={isLoading}>
{isLoading ? <Trans>Saving...</Trans> : <Trans>Save changes</Trans>}
</Button>
</Form>
Expand Down Expand Up @@ -160,7 +160,7 @@ export function UserProfileWithAvatarForm({ user, onSuccess, onClose }) {
>
{/* Form fields */}

<Button type="submit" isDisabled={saveMutation.isPending}>
<Button type="submit" disabled={saveMutation.isPending}>
{saveMutation.isPending ? <Trans>Saving...</Trans> : <Trans>Save changes</Trans>}
</Button>
</Form>
Expand Down
Loading
Loading