Skip to content

Commit

Permalink
feat(kcopy): support truncationLimit auto [khcp-11256] (#2106)
Browse files Browse the repository at this point in the history
Update `KCopy` to support truncation while expanding to fill the space if it's available by specifying `'auto'` for the `truncationLimit`.
Part of [KHCP-11256](https://konghq.atlassian.net/browse/KHCP-11256).
  • Loading branch information
kaiarrowood authored Apr 1, 2024
1 parent 6490e05 commit 26c4365
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 13 deletions.
60 changes: 56 additions & 4 deletions docs/components/copy.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,22 +151,59 @@ Number of characters to truncate at. Defaults to `8`.
/>
```

If you specify `'auto'` for the `truncationLimit` the text will only truncate if there is not enough space for it to be fully displayed.

<KCard class="copy-flexed">
<KCopy
badge
badge-label="Truncated(auto):"
truncate
:text="longUrl"
truncation-limit="auto"
/>
<KCopy
badge
badge-label="Truncated(20ch):"
truncate
:text="longUrl"
:truncation-limit="20"
/>
</KCard>

```html
<KCopy
badge
badge-label="Truncated(auto):"
truncate
:text="longUrl"
truncation-limit="auto"
/>

<KCopy
badge
badge-label="Truncated(20ch):"
truncate
:text="longUrl"
:truncation-limit="20"
/>
```

### copyTooltip

Tooltip text displayed on hover copy button.
Tooltip text displayed on hover copy button.
If the `badgeLabel` prop has a value, then the copy tooltip text is `Copy {badgeLabel}` and the trailing colon from label if one exists will be stripped; otherwise the copy tooltip text is `Copy`.

<KCopy
:text="text"
badge
badge
badge-label="Service ID:"
copy-tooltip="Copy to clipboard"
/>

```html
<KCopy
:text="text"
badge
badge
badge-label="Service ID:"
copy-tooltip="Copy to clipboard"
/>
Expand Down Expand Up @@ -238,10 +275,25 @@ const onButtonClick = (): void => {
import { ref } from 'vue'

const text = '12345-6789-ABCD-EFGH-PQRSTUV-WXYZ'
const longUrl = 'http://i.can.haz.cookies/chocolate/chocolate-chip?best=true&ref=a24Sfsdjh382-3hhdsu3-dsda'

const kCopyElement = ref<InstanceType<typeof KCopy> | null>(null)

const onButtonClick = (): void => {
kCopyElement.value?.copy()
}
</script>
</script>

<style lang="scss" scoped>
.copy-flexed {
display: flex;
flex-wrap: wrap;
gap: $kui-space-70;

/** Resizable */
max-width: 90%;
min-width: 250px;
overflow-x: auto;
resize: horizontal;
}
</style>
51 changes: 42 additions & 9 deletions src/components/KCopy/KCopy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
position-fixed
:text="textTooltipLabel"
>
<span
<div
ref="copyTextElement"
class="copy-text"
:class="{ 'monospace': monospace || !badge }"
>
{{ textFormat }}
</span>
</div>
</KTooltip>

<KTooltip
Expand Down Expand Up @@ -54,12 +55,13 @@

<script setup lang="ts">
import type { PropType } from 'vue'
import { computed, ref, watch } from 'vue'
import { computed, ref, watch, onMounted, onUnmounted } from 'vue'
import { v4 as uuid4 } from 'uuid'
import { ResizeObserverHelper } from '@/utilities/resizeObserverHelper'
import { CopyIcon } from '@kong/icons'
import KClipboardProvider from '@/components/KClipboardProvider'
import KTooltip from '@/components/KTooltip/KTooltip.vue'
import { KUI_ICON_SIZE_30 } from '@kong/design-tokens'
import { v4 as uuid4 } from 'uuid'
const props = defineProps({
/**
Expand Down Expand Up @@ -132,7 +134,7 @@ const props = defineProps({
* Number of characters to truncate at
*/
truncationLimit: {
type: Number,
type: [Number, String],
default: 8,
},
})
Expand All @@ -153,12 +155,10 @@ watch(nonSuccessText, (value: string): void => {
tooltipText.value = value
}, { immediate: true })
const truncateLimitText = computed((): string | null => props.truncate ? `${String(props.text || '').substring(0, props.truncationLimit) + '...'}` : null)
// Computed for dynamic classes
const textTooltipClasses = computed((): string => {
const tooltipWrapperClass = 'copy-tooltip-wrapper' // this selector is referenced in vars.scss - do not update without checking for usage in there first
return `${tooltipWrapperClass} ${props.truncate || props.badge ? 'truncate-content' : ''}`
return `${tooltipWrapperClass} ${(props.truncate && isTruncated.value) || props.badge ? 'truncate-content' : ''}`
})
const textFormat = computed(() => {
Expand All @@ -178,7 +178,7 @@ const textTooltipLabel = computed((): string | undefined => {
}
// don't show text tooltip if text is redacted or not truncated
if (props.format === 'redacted' || !truncateLimitText.value) {
if (props.format === 'redacted' || !isTruncated.value) {
return undefined
}
Expand Down Expand Up @@ -211,6 +211,34 @@ const copy = () => {
defineExpose({
copy,
})
const copyTextElement = ref<HTMLDivElement>()
const resizeObserver = ref<ResizeObserverHelper>()
const truncateLimitText = computed((): string | null => props.truncate && typeof props.truncationLimit === 'number' ? `${String(props.text || '').substring(0, props.truncationLimit) + '...'}` : null)
const isTruncated = ref<boolean>(false)
const setTruncation = (): void => {
if (!props.truncate) {
return
}
if (props.truncationLimit !== 'auto' && truncateLimitText.value) {
isTruncated.value = true
} else if (props.truncationLimit === 'auto' && copyTextElement.value) {
isTruncated.value = copyTextElement.value.offsetWidth < copyTextElement.value.scrollWidth
}
}
onMounted(() => {
resizeObserver.value = ResizeObserverHelper.create(setTruncation)
resizeObserver.value.observe(copyTextElement.value as HTMLDivElement)
})
onUnmounted(() => {
if (resizeObserver.value) {
resizeObserver.value.unobserve(copyTextElement.value as HTMLDivElement)
}
})
</script>

<style lang="scss" scoped>
Expand All @@ -219,6 +247,7 @@ defineExpose({
.k-copy {
align-items: center;
display: flex;
max-width: 100%; /** necessary for truncation */
.copy-element {
align-items: center;
Expand All @@ -227,6 +256,10 @@ defineExpose({
text-overflow: ellipsis;
white-space: nowrap;
.copy-text {
@include truncate;
}
.truncate-content {
display: inline-block;
overflow: hidden;
Expand Down

0 comments on commit 26c4365

Please sign in to comment.