Skip to content
22 changes: 22 additions & 0 deletions docs/pages/ktextbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
{ text: 'Text area', href: '#textarea' },
{ text: 'Clearable', href: '#clearable' },
{ text: 'Validation text', href: '#invalidtext' },
{ text: 'Prepend and append content', href: '#prepend-append' },
]"
/>

Expand Down Expand Up @@ -168,6 +169,27 @@
exampleId="ktextbox-invalidtext"
block
/>

<h3>
Prepend and append content
<DocsAnchorTarget anchor="#prepend-append" />
</h3>
<p>
Use the <code>outerBefore</code>, <code>innerBefore</code>, <code>innerAfter</code>, and
<code>outerAfter</code> slots to prepend or append content inside or outside the input area.
</p>

<DocsExample
loadExample="KTextbox/OuterBeforeInnerAfter.vue"
exampleId="ktextbox-outer-before-inner-after"
block
/>

<DocsExample
loadExample="KTextbox/InnerBeforeOuterAfter.vue"
exampleId="ktextbox-inner-before-outer-after"
block
/>
</DocsPageSection>
</DocsPageTemplate>

Expand Down
2 changes: 1 addition & 1 deletion examples/KTextbox/CharacterLimit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<KTextbox
label="Input with maximum 20 characters"
maxlength="20"
:maxlength="20"
/>

</template>
93 changes: 93 additions & 0 deletions examples/KTextbox/Combined.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<template>

<KTextbox
v-model="searchString"
label="Search for resources..."
clearable
invalid
invalidText="Error message"
:maxlength="20"
:showInvalidText="true"
>
<template #innerBefore>
<KIcon
class="search-icon"
icon="search"
:color="$themeTokens.annotation"
/>
</template>

<template #innerAfter>
<KIconButton
class="copy-btn"
icon="copy"
/>
</template>

<template #outerBefore>
<div class="warning-icon-wrapper">
<KIcon
class="warning-icon"
icon="warning"
:color="$themePalette.yellow.v_500"
/>
</div>
</template>

<template #outerAfter>
<div class="help-btn-wrapper">
<KIconButton
class="help-btn"
icon="helpOutline"
:color="$themePalette.blue.v_500"
/>
</div>
</template>
</KTextbox>

</template>


<script>

export default {
data() {
return {
searchString: 'video',
};
},
};

</script>


<style scoped>

.warning-icon-wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding: 0 6px 8px;
}

.warning-icon {
font-size: 24px;
}

.search-icon {
position: relative;
left: 4px;
margin: 4px;
font-size: 24px;
}

.help-btn-wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding: 0 6px 18px;
}

</style>
73 changes: 73 additions & 0 deletions examples/KTextbox/InnerBeforeOuterAfter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<template>

<div>
<KTextbox
v-model="searchString"
label="Search for resources..."
>
<template #innerBefore>
<KIcon
class="search-icon"
icon="search"
:color="$themeTokens.annotation"
/>
</template>

<template #outerAfter>
<div class="help-btn-wrapper">
<KIconButton
class="help-btn"
icon="helpOutline"
tooltip="Show help"
:color="$themePalette.blue.v_500"
@click="showModal = true"
/>
</div>
</template>
</KTextbox>

<KModal
v-if="showModal"
title="Modal title"
cancelText="Close"
@cancel="showModal = false"
>
Help text
</KModal>
</div>

</template>


<script>

export default {
data() {
return {
searchString: '',
showModal: false,
};
},
};

</script>


<style scoped>

.search-icon {
position: relative;
left: 4px;
margin: 4px;
font-size: 24px;
}

.help-btn-wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding: 0 6px 18px;
}

</style>
73 changes: 73 additions & 0 deletions examples/KTextbox/OuterBeforeInnerAfter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<template>

<KTextbox
v-model="token"
label="Token"
readonly
>
<template #outerBefore>
<div class="warning-icon-wrapper">
<KIcon
class="warning-icon"
icon="warning"
:color="$themePalette.yellow.v_500"
/>
</div>
</template>

<template #innerAfter>
<KIconButton
class="copy-btn"
icon="copy"
tooltip="Copy token"
@click="copyToClipboard"
/>
</template>
</KTextbox>

</template>


<script>

export default {
data() {
return {
token: '123456789',
};
},
methods: {
copyToClipboard() {
if (navigator.clipboard) {
navigator.clipboard.writeText(this.token).then(() => {
alert('Copied to clipboard');
});
}
},
},
};

</script>


<style scoped>

.warning-icon-wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding: 0 6px 8px;
}

.warning-icon {
font-size: 24px;
}

.copy-btn {
position: relative;
right: 6px;
bottom: 6px;
}

</style>
18 changes: 18 additions & 0 deletions lib/KTextbox/__tests__/components/KTextboxVisualTest.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@
width="400px"
loadExample="KTextbox/InvalidText.vue"
/>

<VisualTestExample
title="Outer before and inner afterslots"
width="400px"
loadExample="KTextbox/OuterBeforeInnerAfter.vue"
/>

<VisualTestExample
title="Inner before and outer after slots"
width="400px"
loadExample="KTextbox/InnerBeforeOuterAfter.vue"
/>

<VisualTestExample
title="Combination of several features"
width="400px"
loadExample="KTextbox/Combined.vue"
/>
</VisualTestLayout>

</template>
19 changes: 18 additions & 1 deletion lib/KTextbox/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,24 @@
@keydown="emitKeydown"
@focus="emitFocus"
@blur="emitBlur"
/>
>
<template #outerBefore>
<!--@slot Places content before the input area-->
<slot name="outerBefore"></slot>
</template>
<template #innerBefore>
<!--@slot Places content before the input's inner content -->
<slot name="innerBefore"></slot>
</template>
<template #innerAfter>
<!--@slot Places content after the input's inner content -->
<slot name="innerAfter"></slot>
</template>
<template #outerAfter>
<!--@slot Places content after the input area-->
<slot name="outerAfter"></slot>
</template>
</UiTextbox>
</div>

</template>
Expand Down
Loading