From b90597cc662af8cb461f023d405230f66a30d62f Mon Sep 17 00:00:00 2001 From: PAX-1-2 Date: Sun, 16 Aug 2026 12:26:11 -0400 Subject: [PATCH] feat(pass): allow copying multiple login fields at once Add a multi-copy mode to the login item detail view: a toolbar lets the user enable field selection, pick fields through checkboxes (email, username, password, TOTP token, websites, note and custom fields) and copy them together as "Label: value" entries, separated either by comma and space or by line breaks. --- .../Form/Field/Control/ExtraFieldsControl.tsx | 17 +- .../Form/Field/Control/OTPValueControl.tsx | 3 +- .../Form/Field/Control/UpgradeControl.tsx | 4 +- .../components/Item/Login/Login.content.tsx | 171 ++++++++++++++---- .../components/Item/MultiCopy/MultiCopy.tsx | 158 ++++++++++++++++ 5 files changed, 312 insertions(+), 41 deletions(-) create mode 100644 packages/pass/components/Item/MultiCopy/MultiCopy.tsx diff --git a/packages/pass/components/Form/Field/Control/ExtraFieldsControl.tsx b/packages/pass/components/Form/Field/Control/ExtraFieldsControl.tsx index ba81ff98bd4..9c25d57a5b5 100644 --- a/packages/pass/components/Form/Field/Control/ExtraFieldsControl.tsx +++ b/packages/pass/components/Form/Field/Control/ExtraFieldsControl.tsx @@ -1,7 +1,8 @@ -import type { PropsWithChildren } from 'react'; +import type { PropsWithChildren, ReactElement } from 'react'; import { type FC, useCallback } from 'react'; import { useSelector } from 'react-redux'; +import type { IconName } from '@proton/icons/types'; import { getExtraFieldOption } from '@proton/pass/components/Form/Field/ExtraFieldGroup/ExtraField.utils'; import { FieldsetCluster } from '@proton/pass/components/Form/Field/Layout/FieldsetCluster'; import { TextAreaReadonly } from '@proton/pass/components/Form/legacy/TextAreaReadonly'; @@ -21,6 +22,10 @@ type ExtraFieldsControlProps = { shareId: string; hideIcons?: boolean; onCopy?: () => void; + /** disables per-field click-to-copy (eg: while multi-copy selection is enabled) */ + copyable?: boolean; + /** overrides the field icon - used to render the multi-copy selection checkbox */ + renderIcon?: (key: string) => IconName | ReactElement | undefined; }; export const ExtraFieldsControl: FC> = ({ @@ -30,13 +35,15 @@ export const ExtraFieldsControl: FC> itemId, shareId, onCopy, + copyable = true, + renderIcon, }) => { const { needsUpgrade } = useSelector(selectExtraFieldLimits); const getControlByType = useCallback( ({ fieldName, type, data }: DeobfuscatedItemExtraField, index: number) => { - const icon = hideIcons ? undefined : getExtraFieldOption(type).icon; const key = `${index}-${fieldName}`; + const icon = renderIcon?.(key) ?? (hideIcons ? undefined : getExtraFieldOption(type).icon); if (needsUpgrade) { return ( @@ -62,7 +69,7 @@ export const ExtraFieldsControl: FC> ) : ( > ) : (