FancyTextarea.vue 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <template>
  2. <div class='fancy_textarea'>
  3. <div
  4. class='fancy_textarea__error'
  5. :class='{"fancy_textarea__error--show": error}'
  6. >
  7. {{error}}
  8. </div>
  9. <div
  10. class='fancy_textarea__placeholder'
  11. :class='{"fancy_textarea__placeholder--active": active || value.length}'
  12. >
  13. {{placeholder}}
  14. </div>
  15. <textarea
  16. class='input fancy_textarea__textarea'
  17. v-bind:value='value'
  18. v-bind:style='{width: width || "10rem"}'
  19. v-on:input='updateValue($event.target.value)'
  20. @focus='addActive'
  21. @blur='removeActive'
  22. >
  23. </textarea>
  24. </div>
  25. </template>
  26. <script>
  27. export default {
  28. name: 'FancyTextarea',
  29. props: ['value', 'placeholder', 'width', 'error'],
  30. data () {
  31. return {
  32. active: false
  33. }
  34. },
  35. methods: {
  36. updateValue (val) {
  37. this.$emit('input', val);
  38. },
  39. addActive () {
  40. this.active = true;
  41. },
  42. removeActive () {
  43. this.active = false;
  44. }
  45. }
  46. }
  47. </script>
  48. <style lang='scss' scoped>
  49. @import '../assets/scss/variables.scss';
  50. .fancy_textarea {
  51. position: relative;
  52. margin-top: 0.25rem;
  53. margin-bottom: 0.5rem;
  54. @at-root #{&}__textarea {
  55. height: 5rem;
  56. }
  57. @at-root #{&}__placeholder {
  58. position: absolute;
  59. top: 0.35rem;
  60. background-color: #fff;
  61. left: 0.35rem;
  62. color: $color__gray--darkest;
  63. pointer-events: none;
  64. transition: top 0.2s, font-size 0.2s;
  65. @at-root #{&}--active {
  66. top: -0.5rem;
  67. font-size: 0.75rem;
  68. transition: top 0.2s, font-size 0.2s;
  69. }
  70. }
  71. @at-root #{&}__error {
  72. position: absolute;
  73. background-color: #ffeff1;
  74. border: 0.125rem solid #D32F2F;
  75. max-width: 100%;
  76. font-size: 0.9rem;
  77. padding: 0.1rem 0.25rem;
  78. top: -1.75rem;
  79. right: 0;
  80. &:first-letter{ text-transform: capitalize; }
  81. opacity: 0;
  82. pointer-events: 0;
  83. margin-top: -1rem;
  84. transition: opacity 0.2s, margin-top 0.2s;
  85. @at-root #{&}--show {
  86. opacity: 1;
  87. pointer-events: all;
  88. margin-top: 0;
  89. transition: opacity 0.2s, margin-top 0.2s;
  90. }
  91. &::after {
  92. content: '';
  93. position: relative;
  94. width: 0;
  95. height: 0;
  96. display: inline-block;
  97. bottom: -0.65rem;
  98. border-left: 0.3rem solid transparent;
  99. border-right: 0.3rem solid transparent;
  100. border-top: 0.3rem solid #D32F2F;
  101. }
  102. }
  103. }
  104. </style>