feat(09-03): apply MD3 button styles and elevation across all wizard steps

- BackendCard: rounded-lg -> rounded-xl, added shadow/shadow-md elevation
- OutputBlock: pre rounded -> rounded-xl + shadow-sm; Copy/Download use MD3_BTN_OUTLINED small variant
- BackendSelectionStep: added explicit Next submit button with MD3_BTN_FILLED
- RemoteConfigStep: Back uses MD3_BTN_OUTLINED, Next uses MD3_BTN_FILLED
- DeploymentStep: Back uses MD3_BTN_OUTLINED, Next/Review uses MD3_BTN_FILLED
- ReviewStep: Back uses MD3_BTN_OUTLINED, Download All (ZIP) uses MD3_BTN_FILLED
- All 179 tests pass (zero regressions)
This commit is contained in:
2026-04-01 09:29:52 +02:00
parent e560a6af84
commit d7a2cad7ea
6 changed files with 24 additions and 12 deletions
+3 -3
View File
@@ -14,10 +14,10 @@ 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-lg border-2 p-4 text-left transition-colors', 'flex flex-col items-start gap-1 rounded-xl border-2 p-4 text-left transition-all',
selected selected
? 'border-primary bg-primary/10' ? 'border-primary bg-primary/10 shadow-md'
: 'border-outline bg-surface-container hover:border-primary hover:bg-surface', : 'border-outline bg-surface-container shadow hover:border-primary hover:bg-surface hover:shadow-md',
].join(' ')} ].join(' ')}
{...rest} {...rest}
> >
@@ -6,6 +6,7 @@ import { useWizard } from '../../store/context';
import type { BackendType } from '../../store/types'; import type { BackendType } from '../../store/types';
import { BACKEND_REGISTRY } from '../../schemas/registry'; import { BACKEND_REGISTRY } from '../../schemas/registry';
import { BackendCard } from '../ui/BackendCard'; import { BackendCard } from '../ui/BackendCard';
import { MD3_BTN_FILLED } from '../../styles/md3-buttons';
const remoteNameSchema = z.object({ const remoteNameSchema = z.object({
name: z name: z
@@ -71,6 +72,11 @@ export function BackendSelectionStep() {
/> />
))} ))}
</div> </div>
<div className="flex gap-3 mt-6">
<button type="submit" className={MD3_BTN_FILLED}>
Next
</button>
</div>
</form> </form>
</div> </div>
); );
+3 -2
View File
@@ -3,6 +3,7 @@
// Dispatches SET_DEPLOYMENT live on every control change (no submit needed for deployment options). // Dispatches SET_DEPLOYMENT live on every control change (no submit needed for deployment options).
import { useWizard } from '../../store/context'; import { useWizard } from '../../store/context';
import { MD3_BTN_FILLED, MD3_BTN_OUTLINED } from '../../styles/md3-buttons';
export function DeploymentStep() { export function DeploymentStep() {
const { state, dispatch } = useWizard(); const { state, dispatch } = useWizard();
@@ -91,14 +92,14 @@ export function DeploymentStep() {
<button <button
type="button" type="button"
onClick={() => dispatch({ type: 'SET_STEP', payload: 1 })} onClick={() => dispatch({ type: 'SET_STEP', payload: 1 })}
className="px-4 py-2 text-sm border border-outline rounded-md hover:bg-surface" className={MD3_BTN_OUTLINED}
> >
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="px-4 py-2 text-sm bg-primary text-on-primary rounded-md hover:bg-primary" className={MD3_BTN_FILLED}
> >
Next / Review Next / Review
</button> </button>
+6 -3
View File
@@ -3,6 +3,7 @@
// disabled prop gates both actions (SECU-01 security acknowledgement gate). // disabled prop gates both actions (SECU-01 security acknowledgement gate).
import { useState } from 'react'; import { useState } from 'react';
import { downloadFile } from '../../utils/downloadFile'; import { downloadFile } from '../../utils/downloadFile';
import { MD3_BTN_OUTLINED } from '../../styles/md3-buttons';
export interface OutputBlockProps { export interface OutputBlockProps {
label: string; label: string;
@@ -20,6 +21,8 @@ export function OutputBlock({ label, content, filename, disabled = false }: Outp
setTimeout(() => setCopied(false), 2000); setTimeout(() => setCopied(false), 2000);
} }
const smallBtn = `${MD3_BTN_OUTLINED} !text-xs !px-3 !py-1.5`;
return ( return (
<div className="mb-6"> <div className="mb-6">
<div className="flex items-center justify-between mb-1"> <div className="flex items-center justify-between mb-1">
@@ -29,7 +32,7 @@ export function OutputBlock({ label, content, filename, disabled = false }: Outp
type="button" type="button"
disabled={disabled} disabled={disabled}
onClick={handleCopy} onClick={handleCopy}
className="text-xs px-2 py-1 rounded border border-outline disabled:opacity-40" className={smallBtn}
> >
{copied ? 'Copied!' : 'Copy'} {copied ? 'Copied!' : 'Copy'}
</button> </button>
@@ -38,14 +41,14 @@ export function OutputBlock({ label, content, filename, disabled = false }: Outp
type="button" type="button"
disabled={disabled} disabled={disabled}
onClick={() => downloadFile(content, filename)} onClick={() => downloadFile(content, filename)}
className="text-xs px-2 py-1 rounded border border-outline disabled:opacity-40" className={smallBtn}
> >
Download Download
</button> </button>
)} )}
</div> </div>
</div> </div>
<pre className="bg-surface-variant text-on-surface-variant rounded p-4 text-xs overflow-x-auto whitespace-pre-wrap"> <pre className="bg-surface-variant text-on-surface-variant rounded-xl shadow-sm p-4 text-xs overflow-x-auto whitespace-pre-wrap">
<code>{content}</code> <code>{content}</code>
</pre> </pre>
</div> </div>
+3 -2
View File
@@ -11,6 +11,7 @@ import { FieldRenderer } from '../ui/FieldRenderer';
import { AzureAuthToggle } from './AzureAuthToggle'; import { AzureAuthToggle } from './AzureAuthToggle';
import { SftpAuthToggle } from './SftpAuthToggle'; import { SftpAuthToggle } from './SftpAuthToggle';
import type { FieldError } from 'react-hook-form'; import type { FieldError } from 'react-hook-form';
import { MD3_BTN_FILLED, MD3_BTN_OUTLINED } from '../../styles/md3-buttons';
export function RemoteConfigStep() { export function RemoteConfigStep() {
const { state, dispatch } = useWizard(); const { state, dispatch } = useWizard();
@@ -110,13 +111,13 @@ export function RemoteConfigStep() {
<button <button
type="button" type="button"
onClick={() => dispatch({ type: 'SET_STEP', payload: 0 })} onClick={() => dispatch({ type: 'SET_STEP', payload: 0 })}
className="px-4 py-2 text-sm border border-outline rounded-md hover:bg-surface" className={MD3_BTN_OUTLINED}
> >
Back Back
</button> </button>
<button <button
type="submit" type="submit"
className="px-4 py-2 text-sm bg-primary text-on-primary rounded-md hover:bg-primary" className={MD3_BTN_FILLED}
> >
Next Next
</button> </button>
+3 -2
View File
@@ -3,6 +3,7 @@
// Covers CONF-02, CONF-03, DOWN-01DOWN-06, SECU-01, SECU-02. // Covers CONF-02, CONF-03, DOWN-01DOWN-06, SECU-01, SECU-02.
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { useWizard } from '../../store/context'; import { useWizard } from '../../store/context';
import { MD3_BTN_FILLED, MD3_BTN_OUTLINED } from '../../styles/md3-buttons';
import { import {
buildRcloneConf, buildRcloneConf,
buildIntuneInstall, buildIntuneInstall,
@@ -128,7 +129,7 @@ export function ReviewStep() {
<button <button
type="button" type="button"
onClick={() => dispatch({ type: 'SET_STEP', payload: 2 })} onClick={() => dispatch({ type: 'SET_STEP', payload: 2 })}
className="px-4 py-2 text-sm border border-outline rounded-md hover:bg-surface" className={MD3_BTN_OUTLINED}
> >
Back Back
</button> </button>
@@ -139,7 +140,7 @@ export function ReviewStep() {
type="button" type="button"
disabled={!acknowledged} disabled={!acknowledged}
onClick={handleDownloadZip} onClick={handleDownloadZip}
className="w-full py-2 px-4 bg-primary text-on-primary rounded font-medium disabled:opacity-40 disabled:cursor-not-allowed hover:bg-primary" className={`w-full mt-4 ${MD3_BTN_FILLED}`}
> >
Download All (ZIP) Download All (ZIP)
</button> </button>