Skip to content

Commit 365ec84

Browse files
authored
Merge pull request #704 from devforth/feature/AdminForth/1823/update-blur-cell-renderer
feat: enhance SensitiveBlurCell with eye button for toggling blur effect
2 parents 77a0099 + b314796 commit 365ec84

2 files changed

Lines changed: 41 additions & 8 deletions

File tree

adminforth/documentation/docs/tutorial/03-Customization/02-customFieldRendering.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ For fields containing sensitive data (like passwords, API keys, tokens, or other
605605
606606
The renderer wraps the standard value output and adds a click-to-reveal blur effect. Clicking again hides the value.
607607
608-
For long values (like API keys) you can enable compact mode by passing `compact: true` via `meta`. When set, the value is shortened the same way as the `CompactUUID` renderer (first 4 + `...` + last 4 characters). In compact mode you can additionally pass `copy: true` to render a copy-to-clipboard button next to the value. The copy button is only shown once the value is revealed (blur removed):
608+
For long values (like API keys) you can enable compact mode by passing `compact: true` via `meta`. When set, the value is shortened the same way as the `CompactUUID` renderer (first 4 + `...` + last 4 characters). You can additionally pass `copy: true` to render a copy-to-clipboard button next to the value, and `eyeButton: true` to render an eye icon that also toggles the blur. `compact`, `copy` and `eyeButton` are independent of each other and can be combined in any way:
609609
610610
```ts title='./resources/anyResource.ts'
611611
columns: [
@@ -617,13 +617,13 @@ For long values (like API keys) you can enable compact mode by passing `compact:
617617
//diff-add
618618
file: '@/renderers/SensitiveBlurCell.vue',
619619
//diff-add
620-
meta: { compact: true, copy: true },
620+
meta: { compact: true, copy: true, eyeButton: true },
621621
},
622622
list: {
623623
//diff-add
624624
file: '@/renderers/SensitiveBlurCell.vue',
625625
//diff-add
626-
meta: { compact: true, copy: true },
626+
meta: { compact: true, copy: true, eyeButton: true },
627627
},
628628
},
629629
...

adminforth/spa/src/renderers/SensitiveBlurCell.vue

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div class="inline-flex items-center gap-1">
3-
<Tooltip>
3+
<Tooltip v-if="tooltipText">
44
<div
55
class="overflow-hidden max-h-[20px] rounded-default"
66
:class="{ 'shrink-0 w-[90px]': compact }"
@@ -21,10 +21,39 @@
2121
<span class="whitespace-nowrap">{{ tooltipText }}</span>
2222
</template>
2323
</Tooltip>
24+
<div
25+
v-else
26+
class="overflow-hidden max-h-[20px] rounded-default"
27+
:class="{ 'shrink-0 w-[90px]': compact }"
28+
@click="toggle"
29+
>
30+
<span
31+
class="cursor-pointer select-none transition-all duration-200 text-lightListTableText dark:text-darkListTableText"
32+
:class="{
33+
'block truncate': compact,
34+
'blur-[7px] hover:blur-[5px] brightness-50 dark:brightness-150': !show,
35+
}"
36+
>
37+
<template v-if="compact">{{ visualValue }}</template>
38+
<ValueRenderer v-else :column="column" :record="record" />
39+
</span>
40+
</div>
41+
42+
<span v-if="eyeButton" class="shrink-0 w-5 h-5">
43+
<IconEyeSolid
44+
v-if="!show"
45+
@click.stop="toggle"
46+
class="w-5 h-5 cursor-pointer text-lightPrimary dark:text-darkPrimary"
47+
/>
48+
<IconEyeSlashSolid
49+
v-else
50+
@click.stop="toggle"
51+
class="w-5 h-5 cursor-pointer text-lightPrimary dark:text-darkPrimary"
52+
/>
53+
</span>
2454

2555
<span v-if="showCopy && rawValue" class="shrink-0 w-5 h-5">
2656
<IconFileCopyAltSolid
27-
v-if="show"
2857
@click.stop="copyToCB"
2958
class="w-5 h-5 cursor-pointer text-lightPrimary dark:text-darkPrimary"
3059
/>
@@ -35,7 +64,7 @@
3564
<script setup lang="ts">
3665
import { ref, computed } from 'vue';
3766
import { useI18n } from 'vue-i18n';
38-
import { IconFileCopyAltSolid } from '@iconify-prerendered/vue-flowbite';
67+
import { IconFileCopyAltSolid, IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
3968
import ValueRenderer from '@/components/ValueRenderer.vue';
4069
import Tooltip from '@/afcl/Tooltip.vue';
4170
import { useAdminforth } from '@/adminforth';
@@ -44,7 +73,7 @@ import type { AdminForthResourceColumnCommon, AdminForthResourceCommon, AdminUse
4473
const props = defineProps<{
4574
column: AdminForthResourceColumnCommon;
4675
record: any;
47-
meta: { compact?: boolean; copy?: boolean } | any;
76+
meta: { compact?: boolean; copy?: boolean; eyeButton?: boolean } | any;
4877
resource: AdminForthResourceCommon;
4978
adminUser: AdminUser;
5079
}>();
@@ -57,7 +86,8 @@ const show = ref(false);
5786
const rawValue = computed(() => props.record[props.column.name]);
5887
5988
const compact = computed(() => props.meta?.compact);
60-
const showCopy = computed(() => compact.value && props.meta?.copy);
89+
const showCopy = computed(() => props.meta?.copy);
90+
const eyeButton = computed(() => props.meta?.eyeButton);
6191
const visualValue = computed(() => {
6292
const val = rawValue.value;
6393
if (val && String(val).length > 8) {
@@ -71,6 +101,9 @@ const tooltipText = computed(() => {
71101
if (compact.value && show.value) {
72102
return rawValue.value;
73103
}
104+
if (eyeButton.value) {
105+
return '';
106+
}
74107
return show.value ? t('Click to hide') : t('Click to show');
75108
});
76109

0 commit comments

Comments
 (0)