Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions frontend/packages/react-form-wizard/src/inputs/Input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export type InputCommonProps<ValueT = any> = {
disabledInEditMode?: boolean
/** When true, this input is omitted from the review step navigation / registry. */
hideFromReviewStep?: boolean
secret?: boolean

inputValueToPathValue?: (inputValue: unknown, pathValue: unknown) => unknown
pathValueToInputValue?: (pathValue: unknown) => unknown
Expand Down Expand Up @@ -179,6 +180,7 @@ export function useInput(props: InputCommonProps, options?: { isArrayInput?: boo
value,
label: props.label,
error: error ?? undefined,
secret: props.secret,
type: isArrayInput ? InputReviewMeta.ARRAY_INPUT : InputReviewMeta.INPUT,
})
bumpReviewDomTree?.()
Expand All @@ -192,6 +194,7 @@ export function useInput(props: InputCommonProps, options?: { isArrayInput?: boo
registrationPath,
value,
props.label,
props.secret,
error,
isArrayInput,
bumpReviewDomTree,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import useResizeObserver from '@react-hook/resize-observer'
export type WizTextAreaProps = InputCommonProps<string> & {
label: string
placeholder?: string
secret?: boolean
canPaste?: boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { WizFormGroup } from './WizFormGroup'

export type WizTextInputProps = InputCommonProps<string> & {
placeholder?: string
secret?: boolean
canPaste?: boolean
}

Expand Down
17 changes: 15 additions & 2 deletions frontend/packages/react-form-wizard/src/review/ReviewStep.css
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@
gap: var(--pf-t--global--spacer--xs, 0.25rem);
}

/* Value text grows so trailing controls (reveal / pen / YAML) stay on the right. */
.wizard-review-inline-value-body {
flex: 1 1 auto;
min-width: 0;
}

/* Full width of the value cell so pen controls can sit at the far right. */
.wizard-review-pen-hover-zone.wizard-review-inline-value,
.wizard-review-pen-hover-zone--dl-group-row .wizard-review-inline-value {
Expand All @@ -138,9 +144,14 @@
min-width: 0;
}

/* Match description-list term baseline; keep reveal + pen + arrow on one typographic line. */
.wizard-review-pen-hover-zone--dl-group-row .wizard-review-inline-value {
align-items: baseline;
}

.wizard-review-pen-controls {
display: inline-flex;
align-items: center;
align-items: baseline;
flex-shrink: 0;
margin-left: auto;
gap: var(--pf-t--global--spacer--xs, 0.25rem);
Expand Down Expand Up @@ -189,7 +200,9 @@

/* One flex child so .wizard-review-inline-value gap does not sit between each match span */
.wizard-review-inline-value > .wizard-review-find-inline-body,
.wizard-review-inline-value > .wizard-review-find-value-with-trailing-icon {
.wizard-review-inline-value > .wizard-review-find-value-with-trailing-icon,
.wizard-review-inline-value-body > .wizard-review-find-inline-body,
.wizard-review-inline-value-body > .wizard-review-find-value-with-trailing-icon {
flex: 1 1 auto;
min-width: 0;
}
Expand Down
98 changes: 85 additions & 13 deletions frontend/packages/react-form-wizard/src/review/ReviewStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import {
Alert,
Badge,
Button,
DescriptionList,
DescriptionListDescription,
DescriptionListGroup,
Expand All @@ -18,7 +19,7 @@ import {
} from '@patternfly/react-core'
import { css } from '@patternfly/react-styles'
import titleStyles from '@patternfly/react-styles/css/components/Title/title'
import { CheckIcon, ExclamationCircleIcon } from '@patternfly/react-icons'
import { CheckIcon, ExclamationCircleIcon, EyeIcon, EyeSlashIcon } from '@patternfly/react-icons'
import {
Fragment,
type ComponentProps,
Expand Down Expand Up @@ -769,6 +770,62 @@ function renderReviewInputDescriptionContent(node: WizardInputDomNode): ReactNod
return <></>
}

function useReviewSecretMaskState(value: unknown) {
const [showSecrets, setShowSecrets] = useState(() => isReviewValueUnset(value))
const hasValue = !isReviewValueUnset(value)
const masked = !showSecrets && hasValue
const displayContent = formatReviewValue(value)
const maskedText = masked ? '****************' : displayContent
const revealButton = hasValue ? (
<Button
type="button"
className="wizard-review-edit-btn"
icon={showSecrets ? <EyeSlashIcon /> : <EyeIcon />}
variant="plain"
aria-label={showSecrets ? 'Hide secret value' : 'Show secret value'}
Comment thread
jeswanke marked this conversation as resolved.
aria-pressed={showSecrets}
onClick={(e) => {
e.stopPropagation()
setShowSecrets((s) => !s)
}}
/>
Comment thread
jeswanke marked this conversation as resolved.
) : null
return { maskedText, revealButton }
}
Comment thread
jeswanke marked this conversation as resolved.

function ReviewSecretMaskedValue(props: { value: unknown }) {
const { maskedText, revealButton } = useReviewSecretMaskState(props.value)
return (
<Split>
<SplitItem isFilled>{maskedText}</SplitItem>
{revealButton ? <SplitItem>{revealButton}</SplitItem> : null}
</Split>
)
}

function ReviewSecretPenHoverInputRow(props: {
inputNode: WizardInputDomNode
termContent: ReactNode
yamlVisible: boolean
onReviewEdit: OnReviewEditHandler
}) {
const { inputNode, termContent, yamlVisible, onReviewEdit } = props
const { maskedText, revealButton } = useReviewSecretMaskState(inputNode.value)
return (
<ReviewPenHoverZone
ariaLabel="Edit"
descriptionListTerm={termContent}
descriptionListDescriptionId={inputNode.id}
onPenClick={() => onReviewEdit(inputNode, yamlVisible ? 'highlight' : 'navigate')}
onPenIconClick={() => onReviewEdit(inputNode, 'navigate')}
onArrowClick={yamlVisible ? () => onReviewEdit(inputNode, 'highlight') : undefined}
beforePenControls={revealButton}
>
<span style={{ whiteSpace: 'pre-wrap' }}>{maskedText}</span>
</ReviewPenHoverZone>
)
}

/** Base margin 32px; each nested ARRAY_INPUT adds 2px. */
function reviewArrayInstanceMarginLeft(arrayInputNesting: number): number {
return 32 + 2 * arrayInputNesting
Expand Down Expand Up @@ -911,28 +968,43 @@ function renderReviewInputRows(nodes: readonly WizardInputDomNode[], ctx: Review
{renderReviewInputDescriptionContent(inputNode)}
<ExclamationCircleIcon color={REVIEW_ERROR_TEXT_COLOR} />
</span>
) : inputNode.secret ? (
<ReviewSecretMaskedValue value={inputNode.value} />
) : (
renderReviewInputDescriptionContent(inputNode)
)
const yamlVisible = ctx.showYaml !== false
return (
<DescriptionListGroup key={inputNode.path} style={{ marginLeft: ctx.inputGroupMarginLeft }}>
{onReviewEdit != null && !inputNode.nonEditable ? (
<ReviewPenHoverZone
ariaLabel="Edit"
descriptionListTerm={termContent}
descriptionListDescriptionId={inputNode.id}
onPenClick={() => onReviewEdit(inputNode, yamlVisible ? 'highlight' : 'navigate')}
onPenIconClick={() => onReviewEdit(inputNode, 'navigate')}
onArrowClick={yamlVisible ? () => onReviewEdit(inputNode, 'highlight') : undefined}
>
{valueContent}
</ReviewPenHoverZone>
inputNode.secret && !inputNode.error ? (
<ReviewSecretPenHoverInputRow
inputNode={inputNode}
termContent={termContent}
yamlVisible={yamlVisible}
onReviewEdit={onReviewEdit}
/>
) : (
<ReviewPenHoverZone
ariaLabel="Edit"
descriptionListTerm={termContent}
descriptionListDescriptionId={inputNode.id}
onPenClick={() => onReviewEdit(inputNode, yamlVisible ? 'highlight' : 'navigate')}
onPenIconClick={() => onReviewEdit(inputNode, 'navigate')}
onArrowClick={yamlVisible ? () => onReviewEdit(inputNode, 'highlight') : undefined}
>
{valueContent}
</ReviewPenHoverZone>
)
) : (
<>
<DescriptionListTerm>{termContent}</DescriptionListTerm>
<DescriptionListDescription id={inputNode.id ?? ''}>
<span className="wizard-review-inline-value">{valueContent}</span>
<DescriptionListDescription id={inputNode.id ?? ''} style={{ whiteSpace: 'pre-wrap' }}>
{inputNode.secret && !inputNode.error ? (
valueContent
) : (
<span className="wizard-review-inline-value">{valueContent}</span>
)}
</DescriptionListDescription>
</>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export type InputReviewStepMeta =
label?: string
error: string | undefined
type: InputReviewMeta.INPUT
/** When true, review shows a reveal control instead of the raw value. */
secret?: boolean
/** Nearest enclosing wizard step `id` (set when building the review DOM tree). */
stepId?: string
/** When true, the review row omits the edit pen β€” used for computed / read-only values. */
Expand All @@ -41,6 +43,7 @@ export type InputReviewStepMeta =
label?: string
error: string | undefined
type: InputReviewMeta.ARRAY_INPUT
secret?: boolean
}
| {
id: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ export function ReviewStepFindList(props: ReviewStepFindListProps) {
) : (
<>
<DescriptionListTerm>{termBase}</DescriptionListTerm>
<DescriptionListDescription id={row.node.id ?? ''}>
<DescriptionListDescription id={row.node.id ?? ''} style={{ whiteSpace: 'pre-wrap' }}>
<span className="wizard-review-inline-value">{valueContent}</span>
</DescriptionListDescription>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ export function ReviewPenHoverZone({
onArrowClick,
descriptionListTerm,
descriptionListDescriptionId,
/** Rendered inside the trailing control cluster, immediately before the pen / arrow buttons. */
beforePenControls,
zoneClickable = true,
}: {
as?: 'div' | 'span'
Expand All @@ -280,6 +282,7 @@ export function ReviewPenHoverZone({
descriptionListTerm?: ReactNode
/** `id` on the value cell (scroll target); same as non-pen description rows. */
descriptionListDescriptionId?: string
beforePenControls?: ReactNode
/**
* When false, only the pen / arrow buttons activate edit; the wrapper is not clickable.
* Use beside controls that need their own click targets (e.g. an expandable toggle).
Expand Down Expand Up @@ -317,8 +320,8 @@ export function ReviewPenHoverZone({
[onPenClick]
)

const controls = (
<span className="wizard-review-pen-controls">
const editButtons = (
<>
<Button
type="button"
variant="plain"
Expand Down Expand Up @@ -346,6 +349,13 @@ export function ReviewPenHoverZone({
<ArrowRightIcon />
</Button>
) : null}
</>
)

const controls = (
<span className="wizard-review-pen-controls">
{beforePenControls}
{editButtons}
</span>
)

Expand All @@ -359,9 +369,9 @@ export function ReviewPenHoverZone({
onKeyDown={zoneClickable ? onZoneKeyDown : undefined}
>
<DescriptionListTerm>{descriptionListTerm}</DescriptionListTerm>
<DescriptionListDescription id={descriptionListDescriptionId ?? ''}>
<DescriptionListDescription id={descriptionListDescriptionId ?? ''} style={{ whiteSpace: 'pre-wrap' }}>
<span className="wizard-review-inline-value">
{children}
<span className="wizard-review-inline-value-body">{children}</span>
{controls}
</span>
</DescriptionListDescription>
Expand Down
Loading