From 53959073d76617f012c2cf607ce3c2c16622ef5f Mon Sep 17 00:00:00 2001 From: Maksym Portianoi Date: Tue, 9 Jan 2024 12:16:20 -0500 Subject: [PATCH] feat(kcopy): reskin component [KHCP-9663] (#1925) * chore(sandbox): setup component sandbox [KHCP-9663] * feat(kcopy): reskin component [KHCP-9663] * fix(kcard): add comment [KHCP-9663] * chore(kcopy): sandbox tweaks [KHCP-9663] * fix(kcopy): address PR feedback [KHCP-9663] * fix(kcopy): address PR feedback [KHCP-9663] * fix(kcopy): address Pr feedback [KHCP-9663] * fix(kcopy): address PR feedback [KHCP-9663] * fix(kcopy): minor tweak [KHCP-9663] * chore(sandbox): minor fix [KHCP-9663] --- docs/components/copy.md | 132 ++++++++++++++++++------------- sandbox/index.ts | 1 + sandbox/pages/SandboxCopy.vue | 106 +++++++++++++++++++++++++ sandbox/router/sandbox-routes.ts | 6 ++ src/components/KBadge/KBadge.vue | 50 ++++-------- src/components/KCopy/KCopy.vue | 85 ++++++++++++-------- src/styles/_vars.scss | 5 ++ src/styles/mixins/_badges.scss | 26 ++++++ 8 files changed, 288 insertions(+), 123 deletions(-) create mode 100644 sandbox/pages/SandboxCopy.vue diff --git a/docs/components/copy.md b/docs/components/copy.md index 31bdd95348..906741f76c 100644 --- a/docs/components/copy.md +++ b/docs/components/copy.md @@ -14,6 +14,73 @@ KCopy is a component that displays provided text and allows a user to copy it to The copyable text. +### format + +Determines the display format of the copyable text. The component can take the following `format` values: + +- `default` +- `hidden` +- `redacted` +- `deleted` + +#### default + +Displays regular copyable text. + + + +```html + +``` + +#### hidden + +Displays just a copy button without text. + + + +```html + +``` + +#### redacted + +Displays `*****`. + + + +```html + +``` + +#### deleted + +Displays `*`. + + + +```html + +``` + ### badge Whether or not to display as a badge. Defaults to `false`. @@ -38,14 +105,14 @@ Text displayed before the copyable text when `badge` is true. ```html ``` @@ -92,14 +159,16 @@ If the `badgeLabel` prop has a value, then the copy tooltip text is `Copy {badge ```html ``` @@ -127,61 +196,12 @@ Tooltip text displayed on successful copy. Defaults to `Copied!`. ### monospace -An indicator of whether the copyable text has `JetBrains Mono` font or not. Defaults to `true`, but `false` if `badge` is `true`. - -### format - -Determines the display format of the copyable text. The component can take the following `format` values: +When `badge` is `true`, use this prop to control whether the copyable text has `JetBrains Mono` font or not. Defaults to `false`. -- `default`: displays regular copyable text -- `hidden`: displays just a copy button without text -- `redacted`: displays `*****` -- `deleted`: displays `*` - -#### default - + ```html - -``` - -#### hidden - - -```html - -``` - -#### redacted - - -```html - -``` - -#### deleted - - -```html - + ``` diff --git a/sandbox/router/sandbox-routes.ts b/sandbox/router/sandbox-routes.ts index 2cbb5e7740..1258b051a1 100644 --- a/sandbox/router/sandbox-routes.ts +++ b/sandbox/router/sandbox-routes.ts @@ -44,6 +44,12 @@ const componentRoutes: RouteRecordRaw[] = [ meta: { title: 'Checkbox Sandbox' }, component: () => import('../pages/SandboxCheckbox.vue'), }, + { + path: '/copy', + name: 'copy', + meta: { title: 'Copy Sandbox' }, + component: () => import('../pages/SandboxCopy.vue'), + }, { path: '/dropdown', name: 'dropdown', diff --git a/src/components/KBadge/KBadge.vue b/src/components/KBadge/KBadge.vue index d2c6cf7a9a..b7f866aaa3 100644 --- a/src/components/KBadge/KBadge.vue +++ b/src/components/KBadge/KBadge.vue @@ -136,25 +136,11 @@ onUnmounted(() => { $kBadgeMethodWidth: 85px; -/* Component mixins */ - -// uses info badge appearance colors as default -@mixin kBadgeAppearance($bgColor: var(--kui-color-background-primary-weakest, $kui-color-background-primary-weakest), $textColor: var(--kui-color-text-primary, $kui-color-text-primary), $hoverColor: var(--kui-color-text-primary-strong, $kui-color-text-primary-strong)) { - background-color: $bgColor; - color: $textColor; - - :deep([role="button"]):not([disabled]) { - &:hover, &:focus { - color: $hoverColor !important; - } - } -} - /* Component styles */ .k-badge { // apply info appearance by default (in case of invalid appearance) - @include kBadgeAppearance; + @include badgeAppearance; @include badgeWrapper; .badge-content { @@ -201,96 +187,94 @@ $kBadgeMethodWidth: 85px; /* Appearances */ &.info { - @include kBadgeAppearance; + @include badgeAppearance; } &.success { - @include kBadgeAppearance(var(--kui-color-background-success-weakest, $kui-color-background-success-weakest), + @include badgeAppearance(var(--kui-color-background-success-weakest, $kui-color-background-success-weakest), var(--kui-color-text-success, $kui-color-text-success), var(--kui-color-text-success-strong, $kui-color-text-success-strong)); } &.warning { - @include kBadgeAppearance(var(--kui-color-background-warning-weakest, $kui-color-background-warning-weakest), + @include badgeAppearance(var(--kui-color-background-warning-weakest, $kui-color-background-warning-weakest), var(--kui-color-text-warning, $kui-color-text-warning), var(--kui-color-text-warning-strong, $kui-color-text-warning-strong)); } &.danger { - @include kBadgeAppearance(var(--kui-color-background-danger-weakest, $kui-color-background-danger-weakest), + @include badgeAppearance(var(--kui-color-background-danger-weakest, $kui-color-background-danger-weakest), var(--kui-color-text-danger, $kui-color-text-danger), var(--kui-color-text-danger-strong, $kui-color-text-danger-strong)); } &.decorative { - @include kBadgeAppearance(var(--kui-color-background-decorative-purple-weakest, $kui-color-background-decorative-purple-weakest), - var(--kui-color-text-decorative-purple, $kui-color-text-decorative-purple), - var(--kui-color-text-decorative-purple-strong, $kui-color-text-decorative-purple-strong)); + @include decorativeBadgeAppearance; } &.neutral { - @include kBadgeAppearance(var(--kui-color-background-neutral-weaker, $kui-color-background-neutral-weaker), + @include badgeAppearance(var(--kui-color-background-neutral-weaker, $kui-color-background-neutral-weaker), var(--kui-color-text-neutral-strong, $kui-color-text-neutral-strong), var(--kui-color-text-neutral-stronger, $kui-color-text-neutral-stronger)); } // methods &.connect { - @include kBadgeAppearance(var(--kui-method-color-background-connect, $kui-method-color-background-connect), + @include badgeAppearance(var(--kui-method-color-background-connect, $kui-method-color-background-connect), var(--kui-method-color-text-connect, $kui-method-color-text-connect), var(--kui-method-color-text-connect-strong, $kui-method-color-text-connect-strong)); } &.custom { - @include kBadgeAppearance(var(--kui-color-background-neutral-weak, $kui-color-background-neutral-weak), + @include badgeAppearance(var(--kui-color-background-neutral-weak, $kui-color-background-neutral-weak), var(--kui-color-text, $kui-color-text), var(--kui-color-text-neutral-stronger, $kui-color-text-neutral-stronger)); } &.delete { - @include kBadgeAppearance(var(--kui-method-color-background-delete, $kui-method-color-background-delete), + @include badgeAppearance(var(--kui-method-color-background-delete, $kui-method-color-background-delete), var(--kui-method-color-text-delete, $kui-method-color-text-delete), var(--kui-method-color-text-delete-strong, $kui-method-color-text-delete-strong)); } &.get { - @include kBadgeAppearance(var(--kui-method-color-background-get, $kui-method-color-background-get), + @include badgeAppearance(var(--kui-method-color-background-get, $kui-method-color-background-get), var(--kui-method-color-text-get, $kui-method-color-text-get), var(--kui-method-color-text-get-strong, $kui-method-color-text-get-strong)); } &.head { - @include kBadgeAppearance(var(--kui-method-color-background-head, $kui-method-color-background-head), + @include badgeAppearance(var(--kui-method-color-background-head, $kui-method-color-background-head), var(--kui-method-color-text-head, $kui-method-color-text-head), var(--kui-method-color-text-head-strong, $kui-method-color-text-head-strong)); } &.options { - @include kBadgeAppearance(var(--kui-method-color-background-options, $kui-method-color-background-options), + @include badgeAppearance(var(--kui-method-color-background-options, $kui-method-color-background-options), var(--kui-method-color-text-options, $kui-method-color-text-options), var(--kui-method-color-text-options-strong, $kui-method-color-text-options-strong)); } &.patch { - @include kBadgeAppearance(var(--kui-method-color-background-patch, $kui-method-color-background-patch), + @include badgeAppearance(var(--kui-method-color-background-patch, $kui-method-color-background-patch), var(--kui-method-color-text-patch, $kui-method-color-text-patch), var(--kui-method-color-text-patch-strong, $kui-method-color-text-patch-strong)); } &.post { - @include kBadgeAppearance(var(--kui-method-color-background-post, $kui-method-color-background-post), + @include badgeAppearance(var(--kui-method-color-background-post, $kui-method-color-background-post), var(--kui-method-color-text-post, $kui-method-color-text-post), var(--kui-method-color-text-post-strong, $kui-method-color-text-post-strong)); } &.put { - @include kBadgeAppearance(var(--kui-method-color-background-put, $kui-method-color-background-put), + @include badgeAppearance(var(--kui-method-color-background-put, $kui-method-color-background-put), var(--kui-method-color-text-put, $kui-method-color-text-put), var(--kui-method-color-text-put-strong, $kui-method-color-text-put-strong)); } &.trace { - @include kBadgeAppearance(var(--kui-method-color-background-trace, $kui-method-color-background-trace), + @include badgeAppearance(var(--kui-method-color-background-trace, $kui-method-color-background-trace), var(--kui-method-color-text-trace, $kui-method-color-text-trace), var(--kui-method-color-text-trace-strong, $kui-method-color-text-trace-strong)); } diff --git a/src/components/KCopy/KCopy.vue b/src/components/KCopy/KCopy.vue index 011d16519f..1554ece75c 100644 --- a/src/components/KCopy/KCopy.vue +++ b/src/components/KCopy/KCopy.vue @@ -7,22 +7,21 @@ {{ badgeLabel }}
- {{ textFormat }} + {{ textFormat }} @@ -54,7 +53,7 @@ import { computed, ref, watch } from 'vue' import { CopyIcon } from '@kong/icons' import KClipboardProvider from '@/components/KClipboardProvider' import KTooltip from '@/components/KTooltip/KTooltip.vue' -import { KUI_ICON_SIZE_40 } from '@kong/design-tokens' +import { KUI_ICON_SIZE_30 } from '@kong/design-tokens' const props = defineProps({ /** @@ -103,11 +102,11 @@ const props = defineProps({ default: false, }, /** - * False if `badge` is true + * Whether or not to use monospace font */ monospace: { type: Boolean, - default: true, + default: false, }, /** * Whether or not the text should be truncated @@ -132,7 +131,7 @@ const props = defineProps({ }, }) -const tooltipText = ref('') +const tooltipText = ref('') const nonSuccessText = computed((): string => { if (!props.badgeLabel || props.copyTooltip) { return props.copyTooltip || 'Copy' @@ -148,11 +147,11 @@ watch(nonSuccessText, (value: string): void => { const truncateLimitText = computed((): string | null => props.truncate ? `${props.text.substring(0, props.truncationLimit) + '...'}` : null) -// Computed for all dynamic classes -const truncateStyles = computed((): string | null => props.truncate || props.badge ? 'copy-element' : null) -const badgeStyles = computed((): string | null => props.badge ? 'badge-styles' : null) -const truncateContent = computed((): string | null => props.truncate || props.badge ? 'truncate-content' : null) -const useMono = computed((): string | null => props.badge ? null : 'monospace') +// 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' : ''}` +}) const textFormat = computed(() => { if (props.format === 'redacted') { @@ -160,10 +159,24 @@ const textFormat = computed(() => { } else if (props.format === 'deleted') { return `*${props.text.substring(0, 5)}` } + // This regex will only remove the quotes if they are the first and last characters of the string (truncateLimitText) return (props.truncate && props.truncationLimit && truncateLimitText.value) ? truncateLimitText.value.replace(/^"(.*)"$/, '$1') : props.text }) +const textTooltipLabel = computed((): string | undefined => { + if (props.textTooltip) { + return props.textTooltip + } + + // don't show text tooltip if text is redacted or not truncated + if (props.format === 'redacted' || !truncateLimitText.value) { + return undefined + } + + return props.text +}) + const updateTooltipText = (msg?: string): void => { tooltipText.value = msg || props.successTooltip setTimeout(() => { @@ -183,6 +196,8 @@ const copyIdToClipboard = (executeCopy: (prop: string) => boolean) => { diff --git a/src/styles/_vars.scss b/src/styles/_vars.scss index c1a7628f8f..dd12e38b51 100644 --- a/src/styles/_vars.scss +++ b/src/styles/_vars.scss @@ -9,3 +9,8 @@ $kongponentsKongIconSelector: ".kui-icon"; // transition duration and transition timing function $kongponentsTransitionDurTimingFunc: var(--kui-animation-duration-20, $kui-animation-duration-20) ease-in-out; + +// KCopy tooltip selector +// when KCopy is truncated, it's wrapped by a tooltip which automatically adds a attribute that applies unwanted styles +// so we need this selector to exclude those styles (check KBadge component) +$kongponentsKCopyTooltipWrapperSelector: ".copy-tooltip-wrapper"; diff --git a/src/styles/mixins/_badges.scss b/src/styles/mixins/_badges.scss index dc50e72623..37b9a622aa 100644 --- a/src/styles/mixins/_badges.scss +++ b/src/styles/mixins/_badges.scss @@ -16,3 +16,29 @@ display: inline-flex; gap: var(--kui-space-40, $kui-space-40); } + +// uses info badge appearance colors as default +@mixin badgeAppearance( + $bgColor: var(--kui-color-background-primary-weakest, $kui-color-background-primary-weakest), + $textColor: var(--kui-color-text-primary, $kui-color-text-primary), + $hoverColor: var(--kui-color-text-primary-strong, $kui-color-text-primary-strong) +) { + background-color: $bgColor; + color: $textColor; + + /* stylelint-disable-next-line selector-pseudo-class-no-unknown */ + :deep([role="button"]):not([disabled]):not(#{$kongponentsKCopyTooltipWrapperSelector}) { + &:hover, + &:focus { + color: $hoverColor !important; + } + } +} + +@mixin decorativeBadgeAppearance { + @include badgeAppearance( + var(--kui-color-background-decorative-purple-weakest, $kui-color-background-decorative-purple-weakest), + var(--kui-color-text-decorative-purple, $kui-color-text-decorative-purple), + var(--kui-color-text-decorative-purple-strong, $kui-color-text-decorative-purple-strong) + ); +}