ui: default TextField copy affordance to clipboard (#12714)
This commit is contained in:
@@ -420,7 +420,14 @@ export function SessionHeader() {
|
||||
}
|
||||
>
|
||||
<div class="flex flex-col gap-2">
|
||||
<TextField value={shareUrl() ?? ""} readOnly copyable tabIndex={-1} class="w-full" />
|
||||
<TextField
|
||||
value={shareUrl() ?? ""}
|
||||
readOnly
|
||||
copyable
|
||||
copyKind="link"
|
||||
tabIndex={-1}
|
||||
class="w-full"
|
||||
/>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<Button
|
||||
size="large"
|
||||
|
||||
@@ -6,7 +6,8 @@ import { IconButton } from "./icon-button"
|
||||
import { Tooltip } from "./tooltip"
|
||||
|
||||
export interface TextFieldProps
|
||||
extends ComponentProps<typeof Kobalte.Input>,
|
||||
extends
|
||||
ComponentProps<typeof Kobalte.Input>,
|
||||
Partial<
|
||||
Pick<
|
||||
ComponentProps<typeof Kobalte>,
|
||||
@@ -27,6 +28,7 @@ export interface TextFieldProps
|
||||
error?: string
|
||||
variant?: "normal" | "ghost"
|
||||
copyable?: boolean
|
||||
copyKind?: "clipboard" | "link"
|
||||
multiline?: boolean
|
||||
}
|
||||
|
||||
@@ -49,10 +51,23 @@ export function TextField(props: TextFieldProps) {
|
||||
"error",
|
||||
"variant",
|
||||
"copyable",
|
||||
"copyKind",
|
||||
"multiline",
|
||||
])
|
||||
const [copied, setCopied] = createSignal(false)
|
||||
|
||||
const label = () => {
|
||||
if (copied()) return i18n.t("ui.textField.copied")
|
||||
if (local.copyKind === "link") return i18n.t("ui.textField.copyLink")
|
||||
return i18n.t("ui.textField.copyToClipboard")
|
||||
}
|
||||
|
||||
const icon = () => {
|
||||
if (copied()) return "check"
|
||||
if (local.copyKind === "link") return "link"
|
||||
return "copy"
|
||||
}
|
||||
|
||||
async function handleCopy() {
|
||||
const value = local.value ?? local.defaultValue ?? ""
|
||||
await navigator.clipboard.writeText(value)
|
||||
@@ -92,21 +107,15 @@ export function TextField(props: TextFieldProps) {
|
||||
<Kobalte.TextArea {...others} autoResize data-slot="input-input" class={local.class} />
|
||||
</Show>
|
||||
<Show when={local.copyable}>
|
||||
<Tooltip
|
||||
value={copied() ? i18n.t("ui.textField.copied") : i18n.t("ui.textField.copyLink")}
|
||||
placement="top"
|
||||
gutter={4}
|
||||
forceOpen={copied()}
|
||||
skipDelayDuration={0}
|
||||
>
|
||||
<Tooltip value={label()} placement="top" gutter={4} forceOpen={copied()} skipDelayDuration={0}>
|
||||
<IconButton
|
||||
type="button"
|
||||
icon={copied() ? "check" : "link"}
|
||||
icon={icon()}
|
||||
variant="ghost"
|
||||
onClick={handleCopy}
|
||||
tabIndex={-1}
|
||||
data-slot="input-copy-button"
|
||||
aria-label={copied() ? i18n.t("ui.textField.copied") : i18n.t("ui.textField.copyLink")}
|
||||
aria-label={label()}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Show>
|
||||
|
||||
Reference in New Issue
Block a user