Skip to content

Commit 43d6452

Browse files
committed
Refine create flow support surfaces
1 parent 595e7be commit 43d6452

5 files changed

Lines changed: 76 additions & 86 deletions

File tree

frontend/src/__tests__/App.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ describe('App', () => {
9999
});
100100
fireEvent.click(screen.getByRole('button', { name: 'Generate feed URL' }));
101101

102-
expect(screen.getByText('Unlock custom feed creation')).toBeInTheDocument();
102+
expect(screen.getByText('Save one token in this browser session to continue.')).toBeInTheDocument();
103103
expect(mockConvertFeed).not.toHaveBeenCalled();
104104
});
105105

@@ -176,7 +176,7 @@ describe('App', () => {
176176
fireEvent.click(screen.getByRole('button', { name: 'Generate feed URL' }));
177177
const accessTokenInput = document.getElementById('access-token') as HTMLInputElement;
178178
fireEvent.input(accessTokenInput, { target: { value: 'token-123' } });
179-
fireEvent.click(screen.getByRole('button', { name: 'Save token' }));
179+
fireEvent.click(screen.getByRole('button', { name: 'Continue' }));
180180

181181
await waitFor(() => {
182182
expect(mockSaveToken).toHaveBeenCalledWith('token-123');

frontend/src/components/App.tsx

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useEffect, useState } from 'preact/hooks';
22
import { ResultDisplay } from './ResultDisplay';
3-
import { CreateFeedPanel, InstanceInfo, QuickToolsPanel, type Strategy } from './AppPanels';
3+
import { CreateFeedPanel, InstanceInfo, type Strategy } from './AppPanels';
44
import { useAccessToken } from '../hooks/useAccessToken';
55
import { useApiMetadata } from '../hooks/useApiMetadata';
66
import { useFeedConversion } from '../hooks/useFeedConversion';
@@ -167,42 +167,37 @@ export function App() {
167167
{result ? (
168168
<ResultDisplay result={result} onCreateAnother={handleCreateAnother} />
169169
) : (
170-
<div class="support-stack">
171-
<CreateFeedPanel
172-
feedFormData={feedFormData}
173-
feedFieldErrors={feedFieldErrors}
174-
conversionError={conversionError}
175-
isConverting={isConverting}
176-
strategies={strategies}
177-
strategiesLoading={strategiesLoading}
178-
strategiesError={strategiesError}
179-
feedCreationEnabled={feedCreation.enabled}
180-
accessTokenRequired={feedCreation.access_token_required}
181-
hasAccessToken={hasToken}
182-
tokenDraft={tokenDraft}
183-
tokenError={tokenError}
184-
showTokenPrompt={showTokenPrompt}
185-
onFeedSubmit={handleFeedSubmit}
186-
onFeedFieldChange={setFeedField}
187-
onTokenDraftChange={(value) => {
188-
setTokenDraft(value);
189-
setTokenError('');
190-
}}
191-
onSaveToken={handleSaveToken}
192-
onCancelTokenPrompt={() => {
193-
setShowTokenPrompt(false);
194-
setTokenError('');
195-
}}
196-
strategyHint={strategyHint}
197-
/>
198-
<QuickToolsPanel />
199-
</div>
170+
<CreateFeedPanel
171+
feedFormData={feedFormData}
172+
feedFieldErrors={feedFieldErrors}
173+
conversionError={conversionError}
174+
isConverting={isConverting}
175+
strategies={strategies}
176+
strategiesLoading={strategiesLoading}
177+
strategiesError={strategiesError}
178+
feedCreationEnabled={feedCreation.enabled}
179+
accessTokenRequired={feedCreation.access_token_required}
180+
hasAccessToken={hasToken}
181+
tokenDraft={tokenDraft}
182+
tokenError={tokenError}
183+
showTokenPrompt={showTokenPrompt}
184+
onFeedSubmit={handleFeedSubmit}
185+
onFeedFieldChange={setFeedField}
186+
onTokenDraftChange={(value) => {
187+
setTokenDraft(value);
188+
setTokenError('');
189+
}}
190+
onSaveToken={handleSaveToken}
191+
onCancelTokenPrompt={() => {
192+
setShowTokenPrompt(false);
193+
setTokenError('');
194+
}}
195+
strategyHint={strategyHint}
196+
/>
200197
)}
201198

202199
{!result && (
203200
<InstanceInfo
204-
feedCreationEnabled={feedCreation.enabled}
205-
accessTokenRequired={feedCreation.access_token_required}
206201
hasAccessToken={hasToken}
207202
onClearToken={() => {
208203
clearToken();

frontend/src/components/AppPanels.tsx

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,6 @@ function feedAccessNote(feedCreationEnabled: boolean, accessTokenRequired: boole
2222
return '';
2323
}
2424

25-
function instanceNote(feedCreationEnabled: boolean, accessTokenRequired: boolean, hasAccessToken: boolean) {
26-
if (!feedCreationEnabled) return 'This deployment is currently serving read-only feed functionality.';
27-
if (!accessTokenRequired) return 'This deployment can generate feeds without additional access setup.';
28-
return hasAccessToken
29-
? 'An access token is currently stored in this browser session.'
30-
: 'This deployment asks for an access token only when you create a custom feed.';
31-
}
32-
3325
interface CreateFeedPanelProps {
3426
feedFormData: FeedFormData;
3527
feedFieldErrors: FeedFieldErrors;
@@ -150,20 +142,18 @@ export function CreateFeedPanel({
150142
{showTokenPrompt && (
151143
<div class="token-gate" role="group" aria-label="Access token">
152144
<div class="token-gate__copy">
153-
<p class="eyebrow">Access token</p>
154-
<h3>Unlock custom feed creation</h3>
155-
<p class="muted-copy">
156-
Save a token in this browser session to generate feeds from your own URLs.
157-
</p>
145+
<span class="field-label">Access token</span>
146+
<p class="muted-copy">Save one token in this browser session to continue.</p>
158147
</div>
159148
<div class="token-gate__controls">
160149
<label class="field-block" htmlFor="access-token">
161-
<span class="field-label">Access token</span>
162150
<input
163151
id="access-token"
164152
name="access-token"
165153
type="password"
166154
class="input input--mono"
155+
aria-label="Access token"
156+
placeholder="Paste access token"
167157
autocomplete="off"
168158
value={tokenDraft}
169159
onInput={(event) => onTokenDraftChange((event.target as HTMLInputElement).value)}
@@ -172,7 +162,7 @@ export function CreateFeedPanel({
172162
</label>
173163
<div class="token-gate__actions">
174164
<button type="button" class="btn btn--primary" onClick={onSaveToken}>
175-
Save token
165+
Continue
176166
</button>
177167
<button type="button" class="btn btn--ghost" onClick={onCancelTokenPrompt}>
178168
Cancel
@@ -199,39 +189,26 @@ export function CreateFeedPanel({
199189
);
200190
}
201191

202-
export function QuickToolsPanel() {
203-
return (
204-
<section class="surface surface--quiet">
205-
<div class="surface__header">
206-
<h2>Bookmarklet</h2>
207-
</div>
208-
<Bookmarklet />
209-
</section>
210-
);
211-
}
212-
213192
interface InstanceInfoProps {
214-
feedCreationEnabled: boolean;
215-
accessTokenRequired: boolean;
216193
hasAccessToken: boolean;
217194
onClearToken: () => void;
218195
}
219196

220-
export function InstanceInfo({
221-
feedCreationEnabled,
222-
accessTokenRequired,
223-
hasAccessToken,
224-
onClearToken,
225-
}: InstanceInfoProps) {
197+
export function InstanceInfo({ hasAccessToken, onClearToken }: InstanceInfoProps) {
226198
return (
227199
<section class="surface surface--info">
228200
<div class="surface__header">
229201
<h2>Run your own instance</h2>
230202
</div>
231203

232204
<div class="instance-info">
233-
<p>Start locally with Docker, then use included feeds, automatic generation, or custom configs.</p>
234-
<p>{instanceNote(feedCreationEnabled, accessTokenRequired, hasAccessToken)}</p>
205+
<p>
206+
Start locally with Docker, then wire in included feeds, automatic generation, or custom configs.
207+
</p>
208+
</div>
209+
210+
<div class="instance-utility">
211+
<Bookmarklet />
235212
</div>
236213

237214
<div class="surface__toolbar">

frontend/src/components/Bookmarklet.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export function Bookmarklet() {
1212
return (
1313
<div class="bookmarklet-inline" aria-label="Bookmarklet utility">
1414
<p class="bookmarklet-inline__title">Browser shortcut</p>
15-
<p>Drag this into your bookmarks bar to send the current page back here.</p>
15+
<p>Drag this into your bookmarks bar.</p>
1616
<a id="bookmarklet" class="bookmarklet-link" href={bookmarkletHref}>
1717
Convert page to feed
1818
</a>

frontend/src/styles/main.css

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ textarea {
118118
.preview-loading,
119119
.token-gate,
120120
.token-gate__controls,
121-
.instance-info {
121+
.instance-info,
122+
.instance-utility {
122123
display: grid;
123124
}
124125

@@ -127,10 +128,6 @@ textarea {
127128
gap: var(--space-5);
128129
}
129130

130-
.support-stack {
131-
gap: calc(var(--space-5) * 0.8);
132-
}
133-
134131
.field-stack,
135132
.composer-block,
136133
.feed-preview,
@@ -139,6 +136,7 @@ textarea {
139136
.token-gate,
140137
.token-gate__controls,
141138
.instance-info,
139+
.instance-utility,
142140
.empty-state {
143141
gap: var(--space-3);
144142
}
@@ -463,19 +461,17 @@ a:focus-visible {
463461
}
464462

465463
.token-gate {
466-
padding: var(--space-4);
464+
grid-template-columns: minmax(0, 1fr);
465+
gap: var(--space-2);
466+
padding: var(--space-3);
467467
border: var(--border-width) solid var(--border-strong);
468468
border-radius: var(--radius-md);
469469
background: rgba(255, 255, 255, 0.018);
470470
}
471471

472472
.token-gate__copy {
473473
display: grid;
474-
gap: var(--space-2);
475-
}
476-
477-
.token-gate__copy h3 {
478-
font-size: var(--font-size-2);
474+
gap: var(--space-1);
479475
}
480476

481477
.token-gate__actions {
@@ -484,6 +480,19 @@ a:focus-visible {
484480
flex-wrap: wrap;
485481
}
486482

483+
.token-gate__controls {
484+
grid-template-columns: minmax(0, 1fr) auto;
485+
align-items: start;
486+
}
487+
488+
.token-gate__controls .field-block {
489+
gap: var(--space-1);
490+
}
491+
492+
.token-gate__controls .field-label {
493+
display: none;
494+
}
495+
487496
.result-layout {
488497
align-items: start;
489498
}
@@ -578,20 +587,25 @@ a:focus-visible {
578587

579588
.bookmarklet-inline {
580589
margin: 0;
581-
display: grid;
590+
display: flex;
591+
align-items: center;
582592
gap: var(--space-2);
593+
flex-wrap: wrap;
583594
}
584595

585596
.bookmarklet-inline__title {
586597
margin: 0;
587598
color: var(--text-strong);
588-
font-family: var(--font-family-display);
589-
font-size: var(--font-size-2);
599+
font-size: var(--font-size-00);
600+
text-transform: uppercase;
601+
letter-spacing: 0.05em;
602+
font-weight: 600;
590603
}
591604

592605
.bookmarklet-inline p {
593606
margin: 0;
594607
color: var(--text-muted);
608+
font-size: var(--font-size-00);
595609
}
596610

597611
.bookmarklet-link {
@@ -674,6 +688,10 @@ a:focus-visible {
674688
grid-template-columns: 1fr;
675689
}
676690

691+
.token-gate__controls {
692+
grid-template-columns: 1fr;
693+
}
694+
677695
.result-secondary {
678696
justify-items: stretch;
679697
}

0 commit comments

Comments
 (0)