Skip to content

Commit a3db26e

Browse files
v6: Restyle @graphiql/plugin-history (#4295)
## Summary - Migrate `@graphiql/plugin-history` CSS to OKLCH tokens. - New row layout: status dot, mono query name, variables snippet below, action buttons on the right. - Replace the bespoke header div with `PanelHeader`; subtitle carries the ⌥-click hint. - Storybook stories: `Empty`, `FewRows`, `ManyRows`, `Mixed`, and individual item variants. ## Test plan - [x] Open the History panel; confirm the header reads "History" with the subtitle. - [x] Run a query; verify the row appears with a green status dot, mono query name, and a variable snippet if variables were provided. - [x] Click a history row; confirm the query loads into the editor. - [ ] ⌥-click a row (diff behavior) and confirm it still works. - [x] Click "Clear"; confirm rows are removed and the button shows "Cleared" briefly. - [x] Open Storybook under "Plugins/History"; verify all stories render correctly. Refs: #4219
1 parent b73d951 commit a3db26e

6 files changed

Lines changed: 473 additions & 111 deletions

File tree

.changeset/restyle-history.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphiql/plugin-history': patch
3+
---
4+
5+
Restyle to the v6 design. New row layout with status dot, mono name label, and inline variables snippet. Uses `PanelHeader` for the panel chrome.

packages/graphiql-plugin-history/src/components.tsx

Lines changed: 105 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
Button,
1313
Tooltip,
1414
UnStyledButton,
15+
PanelHeader,
1516
} from '@graphiql/react';
1617
import { useHistory, useHistoryActions } from './context';
1718

@@ -64,24 +65,28 @@ export const History: FC = () => {
6465
const hasFavorites = Boolean(favorites.length);
6566
const hasItems = Boolean(items.length);
6667

68+
const clearButton =
69+
clearStatus || hasItems ? (
70+
<Button
71+
type="button"
72+
state={clearStatus || undefined}
73+
disabled={!items.length}
74+
onClick={handleClearStatus}
75+
>
76+
{{
77+
success: 'Cleared',
78+
error: 'Failed to Clear',
79+
}[clearStatus!] || 'Clear'}
80+
</Button>
81+
) : undefined;
82+
6783
return (
6884
<section aria-label="History" className="graphiql-history">
69-
<div className="graphiql-history-header">
70-
History
71-
{(clearStatus || hasItems) && (
72-
<Button
73-
type="button"
74-
state={clearStatus || undefined}
75-
disabled={!items.length}
76-
onClick={handleClearStatus}
77-
>
78-
{{
79-
success: 'Cleared',
80-
error: 'Failed to Clear',
81-
}[clearStatus!] || 'Clear'}
82-
</Button>
83-
)}
84-
</div>
85+
<PanelHeader
86+
title="History"
87+
subtitle="Last 20 runs."
88+
actions={clearButton}
89+
/>
8590

8691
{hasFavorites && (
8792
<ul className="graphiql-history-items">
@@ -166,6 +171,10 @@ export const HistoryItem: FC<QueryHistoryItemProps> = props => {
166171
toggleFavorite(props.item);
167172
};
168173

174+
const variablesSnippet = props.item.variables
175+
? formatVariables(props.item.variables)
176+
: null;
177+
169178
return (
170179
<li className={cn('graphiql-history-item', isEditable && 'editable')}>
171180
{isEditable ? (
@@ -193,54 +202,71 @@ export const HistoryItem: FC<QueryHistoryItemProps> = props => {
193202
</>
194203
) : (
195204
<>
196-
<Tooltip label="Set active">
197-
<UnStyledButton
198-
type="button"
199-
className="graphiql-history-item-label"
200-
onClick={handleHistoryItemClick}
201-
aria-label="Set active"
202-
>
203-
{displayName}
204-
</UnStyledButton>
205-
</Tooltip>
206-
<Tooltip label="Edit label">
207-
<UnStyledButton
208-
type="button"
209-
className="graphiql-history-item-action"
210-
onClick={handleEditLabel}
211-
aria-label="Edit label"
212-
>
213-
<PenIcon aria-hidden="true" />
214-
</UnStyledButton>
215-
</Tooltip>
216-
<Tooltip
217-
label={props.item.favorite ? 'Remove favorite' : 'Add favorite'}
218-
>
219-
<UnStyledButton
220-
type="button"
221-
className="graphiql-history-item-action"
222-
onClick={handleToggleFavorite}
223-
aria-label={
224-
props.item.favorite ? 'Remove favorite' : 'Add favorite'
225-
}
205+
<div className="graphiql-history-item-inner">
206+
<div className="graphiql-history-item-row">
207+
<span
208+
className="graphiql-history-item-status"
209+
aria-hidden="true"
210+
/>
211+
<Tooltip label="Set active">
212+
<UnStyledButton
213+
type="button"
214+
className="graphiql-history-item-label"
215+
onClick={handleHistoryItemClick}
216+
aria-label="Set active"
217+
>
218+
{displayName}
219+
</UnStyledButton>
220+
</Tooltip>
221+
</div>
222+
{variablesSnippet && (
223+
<div className="graphiql-history-item-meta">
224+
<span className="graphiql-history-item-variables">
225+
{variablesSnippet}
226+
</span>
227+
</div>
228+
)}
229+
</div>
230+
<div className="graphiql-history-item-actions">
231+
<Tooltip label="Edit label">
232+
<UnStyledButton
233+
type="button"
234+
className="graphiql-history-item-action"
235+
onClick={handleEditLabel}
236+
aria-label="Edit label"
237+
>
238+
<PenIcon aria-hidden="true" />
239+
</UnStyledButton>
240+
</Tooltip>
241+
<Tooltip
242+
label={props.item.favorite ? 'Remove favorite' : 'Add favorite'}
226243
>
227-
{props.item.favorite ? (
228-
<StarFilledIcon aria-hidden="true" />
229-
) : (
230-
<StarIcon aria-hidden="true" />
231-
)}
232-
</UnStyledButton>
233-
</Tooltip>
234-
<Tooltip label="Delete from history">
235-
<UnStyledButton
236-
type="button"
237-
className="graphiql-history-item-action"
238-
onClick={handleDeleteItemFromHistory}
239-
aria-label="Delete from history"
240-
>
241-
<TrashIcon aria-hidden="true" />
242-
</UnStyledButton>
243-
</Tooltip>
244+
<UnStyledButton
245+
type="button"
246+
className="graphiql-history-item-action"
247+
onClick={handleToggleFavorite}
248+
aria-label={
249+
props.item.favorite ? 'Remove favorite' : 'Add favorite'
250+
}
251+
>
252+
{props.item.favorite ? (
253+
<StarFilledIcon aria-hidden="true" />
254+
) : (
255+
<StarIcon aria-hidden="true" />
256+
)}
257+
</UnStyledButton>
258+
</Tooltip>
259+
<Tooltip label="Delete from history">
260+
<UnStyledButton
261+
type="button"
262+
className="graphiql-history-item-action"
263+
onClick={handleDeleteItemFromHistory}
264+
aria-label="Delete from history"
265+
>
266+
<TrashIcon aria-hidden="true" />
267+
</UnStyledButton>
268+
</Tooltip>
269+
</div>
244270
</>
245271
)}
246272
</li>
@@ -256,3 +282,19 @@ export function formatQuery(query?: string) {
256282
.replaceAll('}', ' } ')
257283
.replaceAll(/[\s]{2,}/g, ' ');
258284
}
285+
286+
export function formatVariables(variables: string) {
287+
try {
288+
const parsed = JSON.parse(variables) as Record<string, unknown>;
289+
const entries = Object.entries(parsed);
290+
if (!entries.length) {
291+
return null;
292+
}
293+
return entries
294+
.slice(0, 3)
295+
.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)
296+
.join(', ');
297+
} catch {
298+
return variables.slice(0, 60);
299+
}
300+
}

0 commit comments

Comments
 (0)