Skip to content

Commit 0c5937a

Browse files
authored
cleans up pipelineDetails v2 (#1480)
## Description Updated UI components in PipelineDetails and RunDetails to use our UI primitives instead of raw HTML elements. This change implements the new UI guidelines by replacing div/span/h3 elements with `Text`, `BlockStack`, and `InlineStack` components from our UI library. ## Related Issue and Pull requests ## Type of Change - [ ] Bug fix - [ ] New feature - [x] Improvement - [x] Cleanup/Refactor - [ ] Breaking change - [x] Documentation update ## Checklist - [x] I have tested this does not break current pipelines / runs functionality - [x] I have tested the changes on staging ## Screenshots (if applicable) Before: ![Screenshot 2025-12-05 at 1.50.46 PM.png](https://app.graphite.com/user-attachments/assets/1e65c737-be1c-423b-a526-d5684859e207.png) ![Screenshot 2025-12-05 at 1.50.55 PM.png](https://app.graphite.com/user-attachments/assets/6c8cc119-8873-42c6-ad64-d7bbf47d037b.png) After ![Screenshot 2025-12-05 at 1.51.15 PM.png](https://app.graphite.com/user-attachments/assets/2389877c-94d8-4c2d-9edf-cbb03bb4368c.png) ![Screenshot 2025-12-05 at 1.51.26 PM.png](https://app.graphite.com/user-attachments/assets/98770f3e-4d5a-417f-a57a-e1446ce7ce93.png) ## Test Instructions 1. Open the Pipeline Details panel and verify all text, layout, and styling appears correctly 2. Open the Run Details panel and verify all text, layout, and styling appears correctly 3. Verify that copy functionality still works properly ## Additional Comments Added new UI Primitives guidelines to the .cursorrules file to document the preferred approach for future development.
1 parent 5c4c89f commit 0c5937a

File tree

4 files changed

+228
-136
lines changed

4 files changed

+228
-136
lines changed

.cursorrules

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,30 @@ This is a React + TypeScript application for building and running Machine Learni
5555
- Common spacing/layout patterns → Suggest utility classes or component abstractions
5656
- Similar form field styling → Create form field components
5757

58+
### UI Primitives (Prefer Over Raw HTML)
59+
60+
**Always prefer our UI primitives over raw HTML elements:**
61+
62+
- **Layout**: Use `BlockStack` and `InlineStack` from `@/components/ui/layout` instead of `<div className="flex ...">`
63+
- `BlockStack` = vertical flex (`flex-col`)
64+
- `InlineStack` = horizontal flex (`flex-row`)
65+
- Both support `gap`, `align`, `blockAlign` props
66+
- Use `as` prop for semantic elements: `<BlockStack as="ul">`, `<InlineStack as="li">`
67+
68+
- **Typography**: Use `Text` from `@/components/ui/typography` instead of raw `<h1-h6>`, `<p>`, `<span>`, `<dt>`, `<dd>`
69+
- `<Text as="h3" size="md" weight="semibold">` instead of `<h3 className="text-md font-semibold">`
70+
- `<Text as="dt" weight="semibold">` instead of `<dt className="font-semibold">`
71+
- `<Text as="p" size="sm">` instead of `<p className="text-sm">`
72+
- Supports: `as`, `size`, `weight`, `tone`, `font` props
73+
74+
- **Buttons**: Use `Button` from `@/components/ui/button`
75+
- **Icons**: Use `Icon` from `@/components/ui/icon`
76+
77+
**When raw HTML is acceptable:**
78+
- Semantic elements not supported by primitives (e.g., `<dl>`, `<ul>`, `<ol>`, `<table>`)
79+
- Complex layouts where primitives don't fit
80+
- Performance-critical sections where abstraction overhead matters
81+
5882
### State Management
5983

6084
- Use Tanstack Query for server state
@@ -202,6 +226,7 @@ export const useContext = () => {
202226
- Don't create side effects in render functions
203227
- Don't use barrel exports
204228
- Don't modify componentSpec structure without express permission
229+
- Don't use raw HTML elements when UI primitives exist (use `Text`, `BlockStack`, `InlineStack`, etc.)
205230

206231
## Other rules
207232

src/components/Editor/PipelineDetails.tsx

Lines changed: 85 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { CopyText } from "@/components/shared/CopyText/CopyText";
77
import { Button } from "@/components/ui/button";
88
import { Icon } from "@/components/ui/icon";
99
import { BlockStack, InlineStack } from "@/components/ui/layout";
10+
import { Text } from "@/components/ui/typography";
1011
import useToastNotification from "@/hooks/useToastNotification";
1112
import { useComponentSpec } from "@/providers/ComponentSpecProvider";
1213
import { useContextPanel } from "@/providers/ContextPanelProvider";
@@ -145,85 +146,108 @@ const PipelineDetails = () => {
145146
/>
146147
</InlineStack>
147148

148-
{/* General Metadata */}
149-
<div className="flex flex-col gap-2 text-xs text-secondary-foreground mb-2">
150-
<div className="flex flex-wrap gap-6">
151-
{fileMeta.createdBy && (
152-
<div>
153-
<span className="font-semibold">Created by:</span>{" "}
154-
{fileMeta.createdBy}
155-
</div>
156-
)}
157-
</div>
158-
<div className="flex flex-wrap gap-x-6">
159-
{fileMeta.creationTime && (
160-
<div>
161-
<span className="font-semibold">Created at:</span>{" "}
162-
{new Date(fileMeta.creationTime).toLocaleString()}
163-
</div>
164-
)}
165-
{fileMeta.modificationTime && (
166-
<div>
167-
<span className="font-semibold">Last updated:</span>{" "}
168-
{new Date(fileMeta.modificationTime).toLocaleString()}
169-
</div>
170-
)}
171-
</div>
172-
</div>
149+
{(fileMeta.createdBy ||
150+
fileMeta.creationTime ||
151+
fileMeta.modificationTime) && (
152+
<BlockStack>
153+
<Text as="h3" size="md" weight="semibold" className="mb-1">
154+
Pipeline Info
155+
</Text>
156+
<dl className="flex flex-col gap-1 text-xs text-secondary-foreground">
157+
{fileMeta.createdBy && (
158+
<InlineStack as="div" gap="1" blockAlign="center">
159+
<Text as="dt" weight="semibold">
160+
Created by:
161+
</Text>
162+
<dd>{fileMeta.createdBy}</dd>
163+
</InlineStack>
164+
)}
165+
{fileMeta.creationTime && (
166+
<InlineStack as="div" gap="1" blockAlign="center">
167+
<Text as="dt" weight="semibold">
168+
Created at:
169+
</Text>
170+
<dd>{new Date(fileMeta.creationTime).toLocaleString()}</dd>
171+
</InlineStack>
172+
)}
173+
{fileMeta.modificationTime && (
174+
<InlineStack as="div" gap="1" blockAlign="center">
175+
<Text as="dt" weight="semibold">
176+
Last updated:
177+
</Text>
178+
<dd>{new Date(fileMeta.modificationTime).toLocaleString()}</dd>
179+
</InlineStack>
180+
)}
181+
</dl>
182+
</BlockStack>
183+
)}
173184

174-
{/* Description */}
175185
{componentSpec.description && (
176-
<div>
177-
<h3 className="text-md font-medium mb-1">Description</h3>
178-
<div className="text-sm whitespace-pre-line">
186+
<BlockStack>
187+
<Text as="h3" size="md" weight="semibold" className="mb-1">
188+
Description
189+
</Text>
190+
<Text as="p" size="sm" className="whitespace-pre-line">
179191
{componentSpec.description}
180-
</div>
181-
</div>
192+
</Text>
193+
</BlockStack>
182194
)}
183195

184196
{/* Component Digest */}
185197
{digest && (
186-
<div className="mb-2">
187-
<h3 className="text-md font-medium mb-1">Digest</h3>
198+
<BlockStack>
199+
<Text as="h3" size="md" weight="semibold" className="mb-1">
200+
Digest
201+
</Text>
188202
<Button
189203
className="bg-gray-100 border border-gray-300 rounded p-2 h-fit text-xs w-full text-left hover:bg-gray-200 active:bg-gray-300 transition cursor-pointer"
190204
onClick={handleDigestCopy}
191205
variant="ghost"
192206
>
193-
<span className="font-mono break-all w-full text-wrap">
207+
<Text as="span" font="mono" className="break-all w-full text-wrap">
194208
{digest}
195-
</span>
209+
</Text>
196210
</Button>
197-
</div>
211+
</BlockStack>
198212
)}
199213

200214
{/* Annotations */}
201215
{Object.keys(annotations).length > 0 && (
202-
<div>
203-
<h3 className="text-md font-medium mb-1">Annotations</h3>
216+
<BlockStack>
217+
<Text as="h3" size="md" weight="semibold" className="mb-1">
218+
Annotations
219+
</Text>
204220
<ul className="text-xs text-secondary-foreground">
205221
{Object.entries(annotations).map(([key, value]) => (
206222
<li key={key}>
207-
<span className="font-semibold">{key}:</span>{" "}
208-
<span className="break-all">{String(value)}</span>
223+
<Text as="span" weight="semibold">
224+
{key}:
225+
</Text>{" "}
226+
<Text as="span" className="break-all">
227+
{String(value)}
228+
</Text>
209229
</li>
210230
))}
211231
</ul>
212-
</div>
232+
</BlockStack>
213233
)}
214234

215235
{/* Artifacts (Inputs & Outputs) */}
216-
<div>
217-
<h3 className="text-md font-medium mb-1">Artifacts</h3>
218-
<div className="flex gap-4 flex-col">
219-
<div className="flex-1">
220-
<h4 className="text-sm font-semibold mb-1">Inputs</h4>
236+
<BlockStack>
237+
<Text as="h3" size="md" weight="semibold" className="mb-1">
238+
Artifacts
239+
</Text>
240+
<BlockStack gap="4">
241+
<BlockStack>
242+
<Text as="h4" size="sm" weight="semibold" className="mb-1">
243+
Inputs
244+
</Text>
221245
{componentSpec.inputs && componentSpec.inputs.length > 0 ? (
222246
<div className="flex flex-col">
223247
{componentSpec.inputs.map((input) => {
224248
return (
225249
<div
226-
className="flex flex-row justify-between even:bg-white odd:bg-gray-100 gap-1 px-2 py-0 rounded-xs items-center"
250+
className="flex flex-row justify-between even:bg-white odd:bg-gray-100 gap-1 px-2 py-1 rounded-xs items-center"
227251
key={input.name}
228252
>
229253
<div className="text-xs flex-1 truncate max-w-[200px]">
@@ -267,14 +291,16 @@ const PipelineDetails = () => {
267291
) : (
268292
<div className="text-xs text-muted-foreground">No inputs</div>
269293
)}
270-
</div>
271-
<div className="flex-1">
272-
<h4 className="text-sm font-semibold mb-1">Outputs</h4>
294+
</BlockStack>
295+
<BlockStack>
296+
<Text as="h4" size="sm" weight="semibold" className="mb-1">
297+
Outputs
298+
</Text>
273299
{componentSpec.outputs && componentSpec.outputs.length > 0 ? (
274300
<div className="flex flex-col">
275301
{componentSpec.outputs.map((output) => (
276302
<div
277-
className="flex flex-row justify-between even:bg-white odd:bg-gray-100 gap-1 px-2 py-0 rounded-xs items-center"
303+
className="flex flex-row justify-between even:bg-white odd:bg-gray-100 gap-1 px-2 py-1 rounded-xs items-center"
278304
key={output.name}
279305
>
280306
<div className="text-xs flex-1 truncate max-w-[200px]">
@@ -309,20 +335,22 @@ const PipelineDetails = () => {
309335
) : (
310336
<div className="text-xs text-muted-foreground">No outputs</div>
311337
)}
312-
</div>
313-
</div>
314-
</div>
338+
</BlockStack>
339+
</BlockStack>
340+
</BlockStack>
315341

316342
{/* Validations */}
317-
<div className="mt-2">
318-
<h3 className="text-md font-medium mb-1">Validations</h3>
343+
<BlockStack>
344+
<Text as="h3" size="md" weight="semibold" className="mb-1">
345+
Validations
346+
</Text>
319347
<PipelineValidationList
320348
isComponentTreeValid={isComponentTreeValid}
321349
groupedIssues={groupedIssues}
322350
totalIssueCount={globalValidationIssues.length}
323351
onIssueSelect={handleIssueClick}
324352
/>
325-
</div>
353+
</BlockStack>
326354
</BlockStack>
327355
);
328356
};

0 commit comments

Comments
 (0)