diff --git a/src/components/DesignSystem/SDesignSystemProvider.vue b/src/components/DesignSystem/SDesignSystemProvider.vue index 7cfca97f..c9584290 100644 --- a/src/components/DesignSystem/SDesignSystemProvider.vue +++ b/src/components/DesignSystem/SDesignSystemProvider.vue @@ -14,3 +14,10 @@ export default class SDesignSystemProvider extends Vue { @Provide(DesignSystemProvideKey) designSystem = this } + + diff --git a/src/components/Input/SInput.vue b/src/components/Input/SInput.vue index e80d1ffd..9efb076e 100644 --- a/src/components/Input/SInput.vue +++ b/src/components/Input/SInput.vue @@ -3,40 +3,51 @@ class="s-input" :class="computedClasses" > - {{ placeholder }} - - - - + + +
+ + +
+ {{ placeholder }} + + + + +
+ +
+ + @@ -46,13 +57,14 @@ import { ElInput } from 'element-ui/types/input' import { ElForm } from 'element-ui/types/form' import { SIcon } from '../Icon' +import { DesignSystemInject } from '../DesignSystem' import BorderRadiusMixin from '../../mixins/BorderRadiusMixin' import { Autocomplete, InputSize, InputType } from './consts' @Component({ components: { SIcon } }) -export default class SInput extends Mixins(BorderRadiusMixin) { +export default class SInput extends Mixins(BorderRadiusMixin, DesignSystemInject) { readonly InputType = InputType readonly emptyValue = null /** @@ -170,6 +182,9 @@ export default class SInput extends Mixins(BorderRadiusMixin) { get computedClasses (): Array { const cssClasses: Array = [] + if (this.designSystemClass) { + cssClasses.push(this.designSystemClass) + } if (this.focused) { cssClasses.push('s-focused') } @@ -191,6 +206,12 @@ export default class SInput extends Mixins(BorderRadiusMixin) { if (this.size) { cssClasses.push(this.sizeClass) } + if (this.prefix) { + cssClasses.push('s-input--prefix') + } + if (this.suffix) { + cssClasses.push('s-input--suffix') + } return cssClasses } diff --git a/src/stories/SFloatInput.stories.ts b/src/stories/SFloatInput.stories.ts index 7c0234d8..e27ac49d 100644 --- a/src/stories/SFloatInput.stories.ts +++ b/src/stories/SFloatInput.stories.ts @@ -1,6 +1,7 @@ -import { number, text, boolean, object, withKnobs } from '@storybook/addon-knobs' +import { number, text, boolean, object, select, withKnobs } from '@storybook/addon-knobs' -import { SFloatInput, SRow } from '../components' +import { SFloatInput, SRow, SDesignSystemProvider } from '../components' +import { DesignSystemTypes } from '../components/DesignSystem' export default { component: SFloatInput, @@ -9,8 +10,10 @@ export default { } export const configurable = () => ({ - components: { SFloatInput, SRow }, - template: ` + components: { SFloatInput, SRow, SDesignSystemProvider }, + template: ` + + ({ :delimiters="delimiters" :max="max" /> - `, + + `, data: () => ({ model: '' }), props: { + designSystem: { + default: select('Design System', Object.values(DesignSystemTypes), DesignSystemTypes.DEFAULT) + }, decimals: { default: number('Decimals', 18) }, diff --git a/src/stories/SInput.stories.ts b/src/stories/SInput.stories.ts index 8e394b96..ff4267a3 100644 --- a/src/stories/SInput.stories.ts +++ b/src/stories/SInput.stories.ts @@ -1,8 +1,9 @@ import { text, boolean, withKnobs, number, select } from '@storybook/addon-knobs' -import { SInput, SRow, SCol } from '../components' +import { SInput, SRow, SCol, SDesignSystemProvider } from '../components' import { BorderRadius } from '../types' import { InputType, InputSize } from '../components/Input' +import { DesignSystemTypes } from '../components/DesignSystem' export default { component: SInput, @@ -12,8 +13,10 @@ export default { } export const configurable = () => ({ - components: { SInput }, - template: ` + ({ :size="size" :prefix="prefix" :suffix="suffix" - />`, + > +
{{ top }}
+
{{ bottom }}
+
{{ left }}
+
{{ right }}
+
+ `, data: () => ({ input: '' }), props: { + designSystem: { + default: select('Design System', Object.values(DesignSystemTypes), DesignSystemTypes.DEFAULT) + }, + top: { + default: text('Top slot content', '') + }, + bottom: { + default: text('Bottom slot content', '') + }, + left: { + default: text('Left slot content', '') + }, + right: { + default: text('Right slot content', '') + }, type: { default: select('Type', Object.values(InputType), InputType.TEXT) }, diff --git a/src/styles/input.scss b/src/styles/input.scss index 35cf091b..626971f0 100644 --- a/src/styles/input.scss +++ b/src/styles/input.scss @@ -4,117 +4,157 @@ ) { &.s-border-radius { &-#{$suffix} { - border-radius: 0; - .s-placeholder { - border-top-left-radius: $border-radius; - } - .el-input, - .el-textarea { - > input, - > textarea { - border-radius: $border-radius; - } - } + border-radius: $border-radius; } } } +$input-icon-width: 18px; +$input-border-width: 1px; +$input-padding-top: $s-padding-input / 2 - $input-border-width; +$input-padding-left: $s-padding-input - $input-border-width; + .s-input { + display: flex; + flex-direction: column; + justify-content: center; + + background-color: var(--s-color-base-background); + border-color: var(--s-color-base-background); + border-style: solid; + border-width: $input-border-width; font-family: $s-font-family-default; - width: 100%; min-height: $s-size-big; + padding: $input-padding-top $input-padding-left; position: relative; + width: 100%; + @include input-border-radius; @include input-border-radius("medium", var(--s-border-radius-medium)); @include input-border-radius("small", var(--s-border-radius-small)); @include input-border-radius("mini", var(--s-border-radius-mini)); - .el-input__suffix { - z-index: 1; + + &__content { + display: flex; + align-items: center; + width: 100%; } + + &__input { + flex: 1; + position: relative; + } + + &.s-size-medium { + min-height: $s-size-medium; + } + .s-placeholder { // TODO: add default animation from material-ui color: var(--s-color-base-content-tertiary); text-align: left; font-size: var(--s-font-size-mini); - padding: 0 15px; - padding-top: 5px; - top: 1px; - left: 1px; - position: absolute; + line-height: 1.5; z-index: 1; - width: calc(100% - 15px); - background-color: var(--s-color-base-background); pointer-events: none; - } - .el-input, - .el-textarea { - height: 100%; - > input, - > textarea { - height: $s-size-big; - border: 1px solid var(--s-color-base-background); - background-color: var(--s-color-base-background); - &::placeholder { - color: var(--s-color-base-content-tertiary); - opacity: 1; // Firefox + position: absolute; + top: -3px; + + & + .el-input, & + .el-textarea { + padding-top: $s-padding-input; + + .el-input__validateIcon { + padding-top: 11px; } } - > textarea { - padding-top: 12px; - } - [class^="el-input__count"] { - background-color: transparent; - } } + &:hover { - .s-placeholder, - .el-input > input, - .el-textarea > textarea { - background-color: var(--s-color-base-background-hover); - } - .el-input > input, - .el-textarea > textarea { - border-color: var(--s-color-base-background-hover); - } + background-color: var(--s-color-base-background-hover); + border-color: var(--s-color-base-background-hover); } - &.s-size-medium { - min-height: $s-size-medium; - .el-input, - .el-textarea { - height: 100%; - > input, - > textarea { - height: $s-size-medium; - } - } - } &.s-focused { - .s-placeholder, - .el-input > input, - .el-textarea > textarea { - background-color: var(--s-color-utility-surface); - } - .el-input > input, - .el-textarea > textarea { - border-color: var(--s-color-base-border-primary); - } + background-color: var(--s-color-utility-surface); + border-color: var(--s-color-base-border-primary); } + &.s-disabled { - .s-placeholder, - .el-input > input, - .el-textarea > textarea { + color: var(--s-color-base-content-quaternary); + background-color: var(--s-color-base-disabled); + border-color: var(--s-color-base-disabled); + + .s-placeholder { color: var(--s-color-base-content-quaternary); - background-color: var(--s-color-base-disabled); } - .el-input > input, - .el-textarea > textarea { - border-color: var(--s-color-base-disabled); + } + + &--prefix:not(.s-textarea) { + .s-placeholder { + padding-left: $input-icon-width + $s-padding-input / 2; } } - &:not(.s-textarea) { + + &--suffix:not(.s-textarea) { .s-placeholder { - background-color: transparent !important; + padding-right: $input-icon-width + $s-padding-input / 2; + } + } + + .el-input, .el-textarea { + font-size: inherit; + position: unset; + + [class^="el-input__count"] { + background-color: transparent; + } + + &.is-disabled { + .el-input__inner { + background-color: transparent; + color: inherit; + } + } + + &__inner { + height: auto; + line-height: 1.5; + border: none; + border-radius: 0; + background-color: transparent; + padding: 0; + text-align: left; + + &::placeholder { + color: var(--s-color-base-content-tertiary); + opacity: 1; // Firefox + } + } + + &__icon { + line-height: 1; + width: $input-icon-width; + } + + &__prefix { + z-index: 1; + left: 0; + } + + &__suffix { + z-index: 1; + right: 0; + } + + &--prefix { + .el-input__inner { + padding-left: $input-icon-width + $s-padding-input / 2; + } + } + &--suffix { + .el-input__inner { + padding-right: $input-icon-width + $s-padding-input / 2; + } } } .el-input > input { @@ -132,27 +172,17 @@ animation-name: onAutoFillCancel; } } - .s-placeholder + .el-input { - > input { - padding-top: 12px; - } - .el-input__validateIcon { - padding-top: 11px; - } - } - .s-placeholder + .el-textarea > textarea { - padding-top: 24px; - } + &.s-text-file { .el-input > input { padding-right: 56px; } .s-icon-file-file-upload-24 { - top: 16px; - right: 16px; + right: 0; font-size: var(--s-icon-font-size-big); - z-index: 1; + z-index: 2; position: absolute; + cursor: pointer; + input { cursor: pointer; position: absolute; @@ -161,7 +191,7 @@ right: 0; width: 56px; height: 100%; - z-index: 2; + z-index: 1; } } } diff --git a/src/styles/neumorphism/index.scss b/src/styles/neumorphism/index.scss index 68b676ec..6f709c44 100644 --- a/src/styles/neumorphism/index.scss +++ b/src/styles/neumorphism/index.scss @@ -1,2 +1,3 @@ @import "./variables"; @import "./button.scss"; +@import "./input.scss"; diff --git a/src/styles/neumorphism/input.scss b/src/styles/neumorphism/input.scss new file mode 100644 index 00000000..ae590da6 --- /dev/null +++ b/src/styles/neumorphism/input.scss @@ -0,0 +1,49 @@ +$neu-input-border-width: 0 !default; +$neu-input-background: var(--neu-color-base-background) !default; +$neu-input-box-shadow: -1px -1px 1px rgba(0, 0, 0, 0.02), 1px 1px 3px rgba(0, 0, 0, 0.1), inset 1px 1px 2px rgba(255, 255, 255, 0.8) !default; +$neu-input-box-shadow-active: 1px 1px 2px #FFFFFF, inset 1px 1px 2px rgba(0, 0, 0, 0.1) !default; +$neu-input-color: var(--neu-color-base-content-primary) !default; +$neu-input-color-disabled: var(--neu-color-base-content-secondary) !default; +$neu-input-placeholder-color: var(--neu-color-base-content-secondary) !default; +$neu-input-placeholder-offset: -2px !default; +$neu-input-padding: 8px 16px !default; + +.s-input.neumorphic { + border-width: $neu-input-border-width; + box-shadow: $neu-input-box-shadow; + color: $neu-input-color; + padding: $neu-input-padding; + + .el-input, .el-textarea { + &__inner { + color: $neu-input-color; + } + + &.is-disabled { + .el-input__inner { + background-color: transparent; + } + } + } + + & .s-placeholder { + color: $neu-input-placeholder-color; + top: $neu-input-placeholder-offset; + } + + &, &:hover, &.s-focused, &.s-disabled { + background: $neu-input-background; + } + + &.s-focused, &.s-disabled { + box-shadow: $neu-input-box-shadow-active; + } + + &.s-disabled { + color: $neu-input-color-disabled; + + .s-placeholder { + color: $neu-input-placeholder-color; + } + } +}