diff --git a/package.json b/package.json index bac62cfe..d79b26a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@soramitsu/soramitsu-js-ui", - "version": "1.0.16", + "version": "1.0.17", "private": false, "publishConfig": { "registry": "https://nexus.iroha.tech/repository/npm-soramitsu/" @@ -28,7 +28,7 @@ "dependencies": { "core-js": "^3.6.4", "element-resize-detector": "^1.2.1", - "element-ui": "^2.13.2", + "element-ui": "^2.15.5", "lodash": "^4.17.15", "throttle-debounce": "^1.0.1", "v-jsoneditor": "^1.4.1", diff --git a/src/components/Image/SImage/SImage.vue b/src/components/Image/SImage/SImage.vue new file mode 100644 index 00000000..8ac33fa2 --- /dev/null +++ b/src/components/Image/SImage/SImage.vue @@ -0,0 +1,75 @@ + + + diff --git a/src/components/Image/SImage/index.ts b/src/components/Image/SImage/index.ts new file mode 100644 index 00000000..13a62728 --- /dev/null +++ b/src/components/Image/SImage/index.ts @@ -0,0 +1,11 @@ +import { Components, SFCWithInstall } from '../../../types/components' +import install from '../../../utils/install' + +import _SImage from './SImage.vue' + +const SImage = _SImage as SFCWithInstall + +SImage.install = install(Components.SImage, SImage) + +export { SImage } +export default SImage diff --git a/src/components/Image/consts.ts b/src/components/Image/consts.ts new file mode 100644 index 00000000..d8b95ed4 --- /dev/null +++ b/src/components/Image/consts.ts @@ -0,0 +1,7 @@ +export enum ImageFit { + FILL = 'fill', + CONTAIN = 'contain', + COVER = 'cover', + NONE = 'none', + SCALE_DOWN = 'scale-down' +} diff --git a/src/components/Image/index.ts b/src/components/Image/index.ts new file mode 100644 index 00000000..2641e494 --- /dev/null +++ b/src/components/Image/index.ts @@ -0,0 +1,2 @@ +export { SImage } from './SImage' +export { ImageFit } from './consts' diff --git a/src/components/Skeleton/SSkeleton/SSkeleton.vue b/src/components/Skeleton/SSkeleton/SSkeleton.vue new file mode 100644 index 00000000..53e4e1f0 --- /dev/null +++ b/src/components/Skeleton/SSkeleton/SSkeleton.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/components/Skeleton/SSkeleton/index.ts b/src/components/Skeleton/SSkeleton/index.ts new file mode 100644 index 00000000..9c62e66b --- /dev/null +++ b/src/components/Skeleton/SSkeleton/index.ts @@ -0,0 +1,11 @@ +import { Components, SFCWithInstall } from '../../../types/components' +import install from '../../../utils/install' + +import _SSkeleton from './SSkeleton.vue' + +const SSkeleton = _SSkeleton as SFCWithInstall + +SSkeleton.install = install(Components.SSkeleton, SSkeleton) + +export { SSkeleton } +export default SSkeleton diff --git a/src/components/Skeleton/SSkeletonItem/SSkeletonItem.vue b/src/components/Skeleton/SSkeletonItem/SSkeletonItem.vue new file mode 100644 index 00000000..706253bf --- /dev/null +++ b/src/components/Skeleton/SSkeletonItem/SSkeletonItem.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/components/Skeleton/SSkeletonItem/index.ts b/src/components/Skeleton/SSkeletonItem/index.ts new file mode 100644 index 00000000..a687622c --- /dev/null +++ b/src/components/Skeleton/SSkeletonItem/index.ts @@ -0,0 +1,11 @@ +import { Components, SFCWithInstall } from '../../../types/components' +import install from '../../../utils/install' + +import _SSkeletonItem from './SSkeletonItem.vue' + +const SSkeletonItem = _SSkeletonItem as SFCWithInstall + +SSkeletonItem.install = install(Components.SSkeleton, SSkeletonItem) + +export { SSkeletonItem } +export default SSkeletonItem diff --git a/src/components/Skeleton/consts.ts b/src/components/Skeleton/consts.ts new file mode 100644 index 00000000..214fbeee --- /dev/null +++ b/src/components/Skeleton/consts.ts @@ -0,0 +1,12 @@ +export enum SkeletonItemElement { + P = 'p', + TEXT = 'text', + H1 = 'h1', + H2 = 'h2', + H3 = 'h3', + CAPTION = 'caption', + BUTTON = 'button', + IMAGE = 'image', + CIRCLE = 'circle', + RECT = 'rect' +} diff --git a/src/components/Skeleton/index.ts b/src/components/Skeleton/index.ts new file mode 100644 index 00000000..95e49c76 --- /dev/null +++ b/src/components/Skeleton/index.ts @@ -0,0 +1,3 @@ +export { SSkeleton } from './SSkeleton' +export { SSkeletonItem } from './SSkeletonItem' +export { SkeletonItemElement } from './consts' diff --git a/src/components/index.ts b/src/components/index.ts index dc9f811c..dfa08211 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -16,6 +16,7 @@ export { SFooter } from './Layout/Footer' export { SForm, SFormItem } from './Form' export { SHeader } from './Layout/Header' export { SIcon } from './Icon' +export { SImage } from './Image' export { SInput, SFloatInput, SJsonInput } from './Input' export { SMain } from './Layout/Main' export { SMenu, SMenuItem, SMenuItemGroup, SSubmenu } from './Menu' @@ -27,6 +28,7 @@ export { SRow } from './Layout/Row' export { SScrollbar } from './Scrollbar' export { SScrollSectionItem, SScrollSections } from './ScrollSections' export { SSelect, SOption, SOptionGroup } from './Select' +export { SSkeleton, SSkeletonItem } from './Skeleton' export { STab, STabs } from './Tab' export { STable, SHierarchicalTable, STableColumn } from './Table' export { STooltip } from './Tooltip' diff --git a/src/index.ts b/src/index.ts index 25db3641..62348afe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,6 +24,7 @@ import { SFormItem, SHeader, SIcon, + SImage, SInput, SFloatInput, SJsonInput, @@ -41,6 +42,8 @@ import { SScrollSectionItem, SScrollSections, SSelect, + SSkeleton, + SSkeletonItem, SSlider, SSubmenu, SSwitch, @@ -92,6 +95,7 @@ const SoramitsuElements = { vue.use(SFormItem) vue.use(SHeader) vue.use(SIcon) + vue.use(SImage) vue.use(SInput) vue.use(SFloatInput) vue.use(SJsonInput) @@ -109,6 +113,8 @@ const SoramitsuElements = { vue.use(SScrollSectionItem) vue.use(SScrollSections) vue.use(SSelect) + vue.use(SSkeleton) + vue.use(SSkeletonItem) vue.use(SSlider) vue.use(SSubmenu) vue.use(SSwitch) @@ -162,6 +168,7 @@ export { SFormItem, SHeader, SIcon, + SImage, SInput, SFloatInput, SJsonInput, @@ -179,6 +186,8 @@ export { SScrollSectionItem, SScrollSections, SSelect, + SSkeleton, + SSkeletonItem, SSlider, SSubmenu, SSwitch, diff --git a/src/stories/SButton.stories.ts b/src/stories/SButton.stories.ts index 43af470d..53ee092d 100644 --- a/src/stories/SButton.stories.ts +++ b/src/stories/SButton.stories.ts @@ -181,7 +181,7 @@ export const loading = () => ({ :type="item.type" :tooltip="item.tooltip" :icon="item.icon" - :loading="true" + loading > {{ item.label }} diff --git a/src/stories/SImage.stories.ts b/src/stories/SImage.stories.ts new file mode 100644 index 00000000..d1436374 --- /dev/null +++ b/src/stories/SImage.stories.ts @@ -0,0 +1,75 @@ +import { text, boolean, number, select, withKnobs } from '@storybook/addon-knobs' + +import { SImage, ImageFit } from '../components/Image' + +export default { + component: SImage, + title: 'Design System/Components/Image', + decorators: [withKnobs] +} + +export const configurable = () => ({ + components: { SImage }, + template: ``, + props: { + src: { + default: text('Src', 'https://picsum.photos/1024') + }, + fit: { + default: select('Fit', Object.values(ImageFit), ImageFit.NONE) + }, + lazy: { + default: boolean('Lazy', true) + }, + alt: { + default: text('Alt', '') + }, + zIndex: { + default: number('Z-index', 0) + }, + hasSkeleton: { + default: boolean('Has Skeleton', true) + }, + animated: { + default: boolean('Skeleton has Animation', true) + } + } +}) + +export const LazyImages = () => ({ + components: { SImage }, + template: `
+ + + + + + + + + + + + + + + +
`, + data: () => ({ + imageSrc: 'https://picsum.photos/1024/300' + }) +}) + +export const FailedImage = () => ({ + components: { SImage }, + template: '' +}) diff --git a/src/stories/SSkeleton.stories.ts b/src/stories/SSkeleton.stories.ts new file mode 100644 index 00000000..38283f69 --- /dev/null +++ b/src/stories/SSkeleton.stories.ts @@ -0,0 +1,82 @@ +import { boolean, number, text, select, withKnobs } from '@storybook/addon-knobs' + +import { SSkeleton, SSkeletonItem, SkeletonItemElement } from '../components/Skeleton' +import { SImage } from '../components/Image' + +export default { + component: SSkeleton, + title: 'Design System/Components/Skeleton', + decorators: [withKnobs], + excludeStories: /.*Data$/ +} + +export const configurable = () => ({ + components: { + SSkeleton, + SSkeletonItem, + SImage + }, + template: `
+ + + + +
`, + props: { + animated: { + default: boolean('Animated', true) + }, + count: { + default: number('Count', 1) + }, + loading: { + default: boolean('Loading', true) + }, + rows: { + default: number('Rows', 4) + }, + throttle: { + default: number('Throttle', 0) + }, + src: { + default: text('Image Src', 'https://picsum.photos/1024') + }, + lazy: { + default: boolean('Image Lazy', true) + } + } +}) + +export const SkeletonItem = () => ({ + components: { + SSkeleton, + SSkeletonItem + }, + template: `
+ + + +
`, + props: { + element: { + default: select('Element', Object.values(SkeletonItemElement), SkeletonItemElement.TEXT) + } + } +}) diff --git a/src/styles/dropdown.scss b/src/styles/dropdown.scss index c9ee8acd..a71874a5 100644 --- a/src/styles/dropdown.scss +++ b/src/styles/dropdown.scss @@ -68,4 +68,10 @@ &.is-disabled { color: var(--s-color-base-content-quaternary); } + &--divided { + border-top-color: var(--s-color-base-border-secondary); + &:before { + background-color: transparent; + } + } } diff --git a/src/styles/image.scss b/src/styles/image.scss new file mode 100644 index 00000000..1445c369 --- /dev/null +++ b/src/styles/image.scss @@ -0,0 +1,18 @@ +.s-image { + width: 100%; + &__container { + overflow-y: auto; + height: auto; + width: 100%; + } + .el-image__error { + height: inherit; + width: 100%;; + background-color: var(--s-color-status-error-background); + color: var(--s-color-status-error); + font-size: var(--s-font-size-medium); + [design-system-theme="dark"] & { + color: var(--s-color-base-on-accent); + } + } +} diff --git a/src/styles/index.scss b/src/styles/index.scss index 58519129..9082eda0 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -13,6 +13,7 @@ @import "./dropdown"; @import "./form"; @import "./icons"; +@import "./image"; @import "./input"; @import "./json-input"; @import "./layout"; @@ -23,6 +24,7 @@ @import "./scrollbar"; @import "./scroll-sections"; @import "./select"; +@import "./skeleton"; @import "./slider"; @import "./switch"; @import "./tabs"; diff --git a/src/styles/skeleton.scss b/src/styles/skeleton.scss new file mode 100644 index 00000000..2b251cc1 --- /dev/null +++ b/src/styles/skeleton.scss @@ -0,0 +1,54 @@ +$s-skeleton-class: '.el-skeleton'; +$s-skeleton-background-color: var(--s-color-base-content-tertiary); + +.s-skeleton { + height: 100%; + #{$s-skeleton-class} { + font-size: 0; + height: 100%; + width: 100%; + &__item { + background-color: $s-skeleton-background-color; + &:not(:last-child) { + margin-bottom: calc(var(--s-basic-spacing) / 2); + } + &:not(#{$s-skeleton-class}__circle) { + border-radius: var(--s-border-radius-mini); + } + } + &__image { + height: 100%; + svg { + height: var(--s-heading2-font-size); + fill: var(--s-color-base-on-accent); + } + } + &__text, &__caption, &__rect { + height: var(--s-font-size-small); + } + &__p { + height: var(--s-size-mini); + } + &__h1 { + height: var(--s-heading1-font-size); + } + &__h2 { + height: var(--s-heading2-font-size); + } + &__h3 { + height: var(--s-heading3-font-size); + } + &__button, &__circle { + height: var(--s-size-medium); + } + &__circle { + width: var(--s-size-medium); + } + &.is-animated { + #{$s-skeleton-class}__item { + background: linear-gradient(90deg, $s-skeleton-background-color 25%, var(--s-color-base-background-hover) 37%, $s-skeleton-background-color 63%); + background-size: 400% 100%; + } + } + } +} diff --git a/src/types/components.ts b/src/types/components.ts index c22836ec..0b7bd361 100644 --- a/src/types/components.ts +++ b/src/types/components.ts @@ -26,6 +26,7 @@ export enum Components { SFormItem = 'SFormItem', SHeader = 'SHeader', SIcon = 'SIcon', + SImage = 'SImage', SInput = 'SInput', SFloatInput = 'SFloatInput', SJsonInput = 'SJsonInput', @@ -43,6 +44,8 @@ export enum Components { SScrollSectionItem = 'SScrollSectionItem', SScrollSections = 'SScrollSections', SSelect = 'SSelect', + SSkeleton = 'SSkeleton', + SSkeletonItem = 'SSkeletonItem', SSlider = 'SSlider', SSubmenu = 'SSubmenu', SSwitch = 'SSwitch', diff --git a/yarn.lock b/yarn.lock index 55866ce1..fb34c304 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6033,10 +6033,10 @@ element-resize-detector@^1.2.1: dependencies: batch-processor "1.0.0" -element-ui@^2.13.2: - version "2.13.2" - resolved "https://registry.yarnpkg.com/element-ui/-/element-ui-2.13.2.tgz#582bf47aaaaaafe23ea1958fae217a687ad06447" - integrity sha512-r761DRPssMPKDiJZWFlG+4e4vr0cRG/atKr3Eqr8Xi0tQMNbtmYU1QXvFnKiFPFFGkgJ6zS6ASkG+sellcoHlQ== +element-ui@^2.15.5: + version "2.15.5" + resolved "https://registry.yarnpkg.com/element-ui/-/element-ui-2.15.5.tgz#dfb376dc5cd60adab21c991bd4fac3e67e5300f4" + integrity sha512-B/YCdz2aRY2WnFXzbTRTHPKZHBD/2KV6u88EBnkaARC/Lyxnap+7vpvrcW5UNTyVwjItS5Fj1eQyRy6236lbXg== dependencies: async-validator "~1.8.1" babel-helper-vue-jsx-merge-props "^2.0.0"