Add tracker pattern detail page with properties and detected trackers sections
Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
72
.cursor/rules/relay-connection-item-components.mdc
Normal file
72
.cursor/rules/relay-connection-item-components.mdc
Normal file
@@ -0,0 +1,72 @@
|
||||
---
|
||||
description: Extract connection list items (table rows, list entries) into their own fragment component
|
||||
globs: "**/*.tsx"
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Extract connection items into fragment components
|
||||
|
||||
When rendering items from a Relay connection (e.g. `edges.map(…)`), each item
|
||||
MUST be rendered by a dedicated component that owns its own fragment — never
|
||||
inline the rendering of node fields directly in the parent's `.map()` body.
|
||||
|
||||
This ensures:
|
||||
- Data requirements are colocated with the rendering component
|
||||
- Adding/removing fields in a row doesn't bloat the parent's fragment
|
||||
- The row component is independently testable and reusable
|
||||
|
||||
## Pattern
|
||||
|
||||
```tsx
|
||||
// _components/ThingRow.tsx — owns its fragment
|
||||
const thingRowFragment = graphql`
|
||||
fragment ThingRow_thing on Thing {
|
||||
id
|
||||
name
|
||||
status
|
||||
}
|
||||
`;
|
||||
|
||||
interface ThingRowProps {
|
||||
thingKey: ThingRow_thing$key;
|
||||
}
|
||||
|
||||
export function ThingRow({ thingKey }: ThingRowProps) {
|
||||
const thing = useFragment(thingRowFragment, thingKey);
|
||||
return (
|
||||
<Tr>
|
||||
<Td>{thing.name}</Td>
|
||||
<Td>{thing.status}</Td>
|
||||
</Tr>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
```tsx
|
||||
// Parent — spreads the row fragment in its connection and renders the component
|
||||
const parentFragment = graphql`
|
||||
fragment ParentPage_things on Query
|
||||
@refetchable(queryName: "ParentPageRefetchQuery") {
|
||||
things(first: $first, after: $after) @connection(key: "ParentPage_things") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...ThingRow_thing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// In JSX:
|
||||
{things.map(thing => (
|
||||
<ThingRow key={thing.id} thingKey={thing} />
|
||||
))}
|
||||
```
|
||||
|
||||
## Naming
|
||||
|
||||
- File: `_components/<NodeType>Row.tsx` (for table rows) or
|
||||
`_components/<NodeType>Card.tsx` (for card lists)
|
||||
- Fragment: `<ComponentName>_<typeName>` (e.g. `ThingRow_thing`)
|
||||
- Prop: `<typeName>Key` (e.g. `thingKey`)
|
||||
@@ -39,3 +39,6 @@ interface EditCookieRowProps {
|
||||
|
||||
Callback props (`onSave`, `onCancel`) and configuration props (`isUpdating`,
|
||||
`variant`) are fine — only **domain data** must come from fragments.
|
||||
|
||||
For connection items (table rows, list entries rendered in `.map()`), see the
|
||||
companion rule `relay-connection-item-components.mdc`.
|
||||
|
||||
Reference in New Issue
Block a user