Skip to content

Commit

Permalink
Add an optional button to copy the value of ipl-data-row
Browse files Browse the repository at this point in the history
  • Loading branch information
inkfarer committed Jan 12, 2024
1 parent 5906227 commit fc946c0
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
- SSR support
- Provide separate ESM and UMD builds
- `color` and `without-content-background` props to ipl-expanding-space
- Added `copiable` to ipl-data-row
# 2.10.1
Expand Down
7 changes: 7 additions & 0 deletions docs/examples/DataRowExample.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<ipl-data-row
:label="label"
:value="value"
:copiable="copiable"
/>
<!-- #endregion example -->
</div>
Expand All @@ -18,14 +19,20 @@
name="value"
label="Value"
/>
<ipl-checkbox
v-model="copiable"
label="Copiable"
/>
</div>
</template>

<script setup lang="ts">
import IplDataRow from '../../src/components/iplDataRow.vue';
import { ref } from 'vue';
import IplInput from '../../src/components/iplInput.vue';
import IplCheckbox from '../../src/components/iplCheckbox.vue';
const label = ref('Data Row');
const value = ref('text content');
const copiable = ref(false);
</script>
23 changes: 23 additions & 0 deletions src/components/__tests__/iplDataRow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,27 @@ describe('IplDataRow', () => {

expect(wrapper.get('.value').text()).toEqual('Value!');
});

it('does not show copy button by default', () => {
const wrapper = mount(IplDataRow, { props: { label: 'Label!', value: 'Value!' } });

expect(wrapper.find('.copy-button').exists()).toEqual(false);
});

it('shows copy button when enabled', () => {
const wrapper = mount(IplDataRow, { props: { label: 'Label!', value: 'Value!', copiable: true } });

expect(wrapper.find('.copy-button').exists()).toEqual(true);
});

it('copies value on copy button click', async () => {
const wrapper = mount(IplDataRow, { props: { label: 'Label!', value: 'Value!', copiable: true } });
Object.defineProperty(navigator, 'clipboard', {
value: { writeText: jest.fn().mockResolvedValue(undefined) }
});

await wrapper.get('.copy-button').trigger('click');

expect(navigator.clipboard.writeText).toHaveBeenCalledWith('Value!');
});
});
70 changes: 66 additions & 4 deletions src/components/iplDataRow.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,65 @@
<template>
<div class="ipl-data-row">
<ipl-label>{{ label }}</ipl-label>
<div class="value">{{ value ?? '―' }}</div>
<div class="value">
{{ isBlank(value) ? '―' : value }}
<button
v-if="copiable"
class="copy-button"
@click="onCopy"
>
<font-awesome-icon icon="copy" />
</button>
</div>
</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, PropType } from 'vue';
import IplLabel from './iplLabel.vue';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { library } from '@fortawesome/fontawesome-svg-core';
import { faCopy } from '@fortawesome/free-solid-svg-icons/faCopy';
import { isBlank } from '../helpers/stringHelper';
library.add(faCopy);
export default defineComponent({
name: 'IplDataRow',
components: { IplLabel },
components: { IplLabel, FontAwesomeIcon },
props: {
label: {
type: String,
required: true
},
value: {
type: String,
type: [String, null] as PropType<string | undefined | null>,
default: null
},
copiable: {
type: Boolean,
default: false
}
},
setup(props) {
return {
onCopy() {
navigator.clipboard.writeText(props.value ?? '').catch(e => {
console.error('Failed to copy value', e);
});
},
isBlank
};
}
});
</script>

<style lang="scss" scoped>
@use 'src/styles/constants';
.ipl-data-row {
display: flex;
flex-direction: row;
Expand All @@ -46,5 +80,33 @@ export default defineComponent({
text-align: right;
overflow-wrap: anywhere;
}
.copy-button {
font-size: 0.9em;
margin-left: 2px;
padding: 0 2px;
border: 0;
background-color: transparent;
color: var(--ipl-text-button-color);
cursor: default;
border-radius: constants.$border-radius-inner;
text-align: center;
transition-property: color, background-color;
transition-duration: constants.$transition-duration-low;
&:hover {
color: var(--ipl-text-button-color-hover);
background-color: var(--ipl-hover-overlay-color);
}
&:active {
color: var(--ipl-text-button-color-active);
background-color: var(--ipl-active-overlay-color);
}
&:focus-visible {
outline: var(--ipl-focus-outline-color) solid 2px;
}
}
}
</style>
6 changes: 5 additions & 1 deletion src/components/iplMessage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,20 @@ export default defineComponent({
height: 1.1em;
border: 0;
background-color: transparent;
color: var(--ipl-body-text-color);
color: var(--ipl-text-button-color);
cursor: default;
border-radius: constants.$border-radius-inner;
text-align: center;
transition-property: color, background-color;
transition-duration: constants.$transition-duration-low;
&:hover {
color: var(--ipl-text-button-color-hover);
background-color: var(--ipl-hover-overlay-color);
}
&:active {
color: var(--ipl-text-button-color-active);
background-color: var(--ipl-active-overlay-color);
}
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/stringHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ export function formatNumber(value: number): string {
}

export function isBlank(value?: string | null): boolean {
return value === null || value === undefined || value.trim() === '';
return value === null || value === undefined || String(value).trim() === '';
}
3 changes: 3 additions & 0 deletions src/styles/variables-light.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ html.light {

--ipl-body-text-color: #3C3C43;
--ipl-disabled-body-text-color: #9494A0;
--ipl-text-button-color: rgba(60, 60, 67, 0.5);
--ipl-text-button-color-hover: rgba(60, 60, 67, 0.75);
--ipl-text-button-color-active: rgba(60, 60, 67, 0.9);

--ipl-bg-primary: #FFFFFF;
--ipl-bg-primary-hover: #F2F2F2;
Expand Down
3 changes: 3 additions & 0 deletions src/styles/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ html {

--ipl-body-text-color: #FFFFFF;
--ipl-disabled-body-text-color: #A9AAA9;
--ipl-text-button-color: rgba(255, 255, 255, 0.5);
--ipl-text-button-color-hover: rgba(255, 255, 255, 0.75);
--ipl-text-button-color-active: rgba(255, 255, 255, 0.9);

--ipl-bg-primary: #262F40;
--ipl-bg-primary-hover: #222a39;
Expand Down

0 comments on commit fc946c0

Please sign in to comment.