feat(11-01): mobile-responsive layout for wizard steps

- BackendSelectionStep: responsive grid (1-col mobile, 2-col desktop) for cards; button row stacks vertically on mobile
- BackendCard: add w-full to fill grid cell on all viewports
- RemoteConfigStep/DeploymentStep/ReviewStep: flex-col sm:flex-row button rows; w-full sm:w-auto on Back/Next buttons
- StepIndicator: add hidden sm:block to all three label spans (completed, active, future)
This commit is contained in:
2026-04-01 13:23:43 +02:00
parent e22d44d807
commit 07f97d9f25
6 changed files with 15 additions and 15 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ export function BackendCard({ name, description, selected = false, onClick, ...r
onClick={onClick} onClick={onClick}
data-selected={selected} data-selected={selected}
className={[ className={[
'flex flex-col items-start gap-1 rounded-xl border-2 p-4 text-left transition-all', 'w-full flex flex-col items-start gap-1 rounded-xl border-2 p-4 text-left transition-all',
selected selected
? 'border-primary bg-primary/10 shadow-md' ? 'border-primary bg-primary/10 shadow-md'
: 'border-outline bg-surface-container shadow hover:border-primary hover:bg-surface hover:shadow-md', : 'border-outline bg-surface-container shadow hover:border-primary hover:bg-surface hover:shadow-md',
@@ -72,7 +72,7 @@ export function BackendSelectionStep() {
helpText="This becomes the section header [name] in your rclone.conf. Example: azure-prod, backup-s3. Letters, numbers, dashes, underscores only." helpText="This becomes the section header [name] in your rclone.conf. Example: azure-prod, backup-s3. Letters, numbers, dashes, underscores only."
/> />
<RemoteNamePreview value={remoteName} /> <RemoteNamePreview value={remoteName} />
<div data-testid="backend-cards"> <div data-testid="backend-cards" className="grid grid-cols-1 sm:grid-cols-2 gap-3 mt-4">
{Object.entries(BACKEND_REGISTRY).map(([type, entry]) => ( {Object.entries(BACKEND_REGISTRY).map(([type, entry]) => (
<BackendCard <BackendCard
key={type} key={type}
@@ -83,8 +83,8 @@ export function BackendSelectionStep() {
/> />
))} ))}
</div> </div>
<div className="flex gap-3 mt-6"> <div className="flex flex-col sm:flex-row gap-3 mt-6">
<button type="submit" className={MD3_BTN_FILLED}> <button type="submit" className={`${MD3_BTN_FILLED} w-full sm:w-auto`}>
Next Next
</button> </button>
</div> </div>
+3 -3
View File
@@ -92,18 +92,18 @@ export function DeploymentStep() {
</fieldset> </fieldset>
{/* Navigation buttons */} {/* Navigation buttons */}
<div className="flex gap-3 mt-6"> <div className="flex flex-col sm:flex-row gap-3 mt-6">
<button <button
type="button" type="button"
onClick={() => dispatch({ type: 'SET_STEP', payload: 1 })} onClick={() => dispatch({ type: 'SET_STEP', payload: 1 })}
className={MD3_BTN_OUTLINED} className={`${MD3_BTN_OUTLINED} w-full sm:w-auto`}
> >
Back Back
</button> </button>
<button <button
type="button" type="button"
onClick={() => dispatch({ type: 'SET_STEP', payload: 3 })} onClick={() => dispatch({ type: 'SET_STEP', payload: 3 })}
className={MD3_BTN_FILLED} className={`${MD3_BTN_FILLED} w-full sm:w-auto`}
> >
Next / Review Next / Review
</button> </button>
+3 -3
View File
@@ -111,17 +111,17 @@ export function RemoteConfigStep() {
/> />
)) ))
)} )}
<div className="flex gap-3 mt-6"> <div className="flex flex-col sm:flex-row gap-3 mt-6">
<button <button
type="button" type="button"
onClick={() => dispatch({ type: 'SET_STEP', payload: 0 })} onClick={() => dispatch({ type: 'SET_STEP', payload: 0 })}
className={MD3_BTN_OUTLINED} className={`${MD3_BTN_OUTLINED} w-full sm:w-auto`}
> >
Back Back
</button> </button>
<button <button
type="submit" type="submit"
className={MD3_BTN_FILLED} className={`${MD3_BTN_FILLED} w-full sm:w-auto`}
> >
Next Next
</button> </button>
+2 -2
View File
@@ -131,11 +131,11 @@ export function ReviewStep() {
)} )}
{/* TECH-02: Back button — dispatches SET_STEP(2) */} {/* TECH-02: Back button — dispatches SET_STEP(2) */}
<div className="flex gap-3 mt-6"> <div className="flex flex-col sm:flex-row gap-3 mt-6">
<button <button
type="button" type="button"
onClick={() => dispatch({ type: 'SET_STEP', payload: 2 })} onClick={() => dispatch({ type: 'SET_STEP', payload: 2 })}
className={MD3_BTN_OUTLINED} className={`${MD3_BTN_OUTLINED} w-full sm:w-auto`}
> >
Back Back
</button> </button>
+3 -3
View File
@@ -42,21 +42,21 @@ export function StepIndicator() {
<span className="w-8 h-8 rounded-full bg-primary text-on-primary flex items-center justify-center text-sm font-medium group-focus-visible:ring-2 group-focus-visible:ring-primary/50"> <span className="w-8 h-8 rounded-full bg-primary text-on-primary flex items-center justify-center text-sm font-medium group-focus-visible:ring-2 group-focus-visible:ring-primary/50">
&#10003; &#10003;
</span> </span>
<span className="text-xs text-primary">{label}</span> <span className="text-xs text-primary hidden sm:block">{label}</span>
</button> </button>
) : isActive ? ( ) : isActive ? (
<div className="flex flex-col items-center gap-1"> <div className="flex flex-col items-center gap-1">
<span className="w-8 h-8 rounded-full border-2 border-primary bg-primary/10 text-primary font-bold flex items-center justify-center text-sm"> <span className="w-8 h-8 rounded-full border-2 border-primary bg-primary/10 text-primary font-bold flex items-center justify-center text-sm">
{i + 1} {i + 1}
</span> </span>
<span className="text-xs text-primary font-semibold">{label}</span> <span className="text-xs text-primary font-semibold hidden sm:block">{label}</span>
</div> </div>
) : ( ) : (
<div className="flex flex-col items-center gap-1"> <div className="flex flex-col items-center gap-1">
<span className="w-8 h-8 rounded-full border-2 border-outline text-on-surface-container/40 flex items-center justify-center text-sm"> <span className="w-8 h-8 rounded-full border-2 border-outline text-on-surface-container/40 flex items-center justify-center text-sm">
{i + 1} {i + 1}
</span> </span>
<span className="text-xs text-on-surface-container/40">{label}</span> <span className="text-xs text-on-surface-container/40 hidden sm:block">{label}</span>
</div> </div>
)} )}
</div> </div>