diff --git a/package.json b/package.json
index d2d00eac..d85285e5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@soramitsu/soramitsu-js-ui",
- "version": "0.4.1",
+ "version": "0.4.3",
"private": false,
"publishConfig": {
"registry": "https://nexus.iroha.tech/repository/npm-soramitsu-private/"
diff --git a/src/components/Radio/SRadio.vue b/src/components/Radio/SRadio.vue
index a1bbe20d..d30b2246 100644
--- a/src/components/Radio/SRadio.vue
+++ b/src/components/Radio/SRadio.vue
@@ -1,5 +1,15 @@
-
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Radio/index.ts b/src/components/Radio/index.ts
index ec804fcd..9392d611 100644
--- a/src/components/Radio/index.ts
+++ b/src/components/Radio/index.ts
@@ -1,4 +1,5 @@
import SRadio from './SRadio.vue'
+import SRadioGroup from './SRadioGroup.vue'
import { RadioSize } from './consts'
-export { SRadio, RadioSize }
+export { SRadio, SRadioGroup, RadioSize }
diff --git a/src/components/Slider/SSlider.vue b/src/components/Slider/SSlider.vue
new file mode 100644
index 00000000..53a018bb
--- /dev/null
+++ b/src/components/Slider/SSlider.vue
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
diff --git a/src/components/Slider/consts.ts b/src/components/Slider/consts.ts
new file mode 100644
index 00000000..3e4ca1e0
--- /dev/null
+++ b/src/components/Slider/consts.ts
@@ -0,0 +1,6 @@
+export enum SliderInputSize {
+ BIG = 'big',
+ MEDIUM = 'medium',
+ SMALL = 'small',
+ MINI = 'mini'
+}
diff --git a/src/components/Slider/index.ts b/src/components/Slider/index.ts
new file mode 100644
index 00000000..67073618
--- /dev/null
+++ b/src/components/Slider/index.ts
@@ -0,0 +1,4 @@
+import SSlider from './SSlider.vue'
+import { SliderInputSize } from './consts'
+
+export { SSlider, SliderInputSize }
diff --git a/src/components/Switch/SSwitch.vue b/src/components/Switch/SSwitch.vue
new file mode 100644
index 00000000..e8b85bc4
--- /dev/null
+++ b/src/components/Switch/SSwitch.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
diff --git a/src/components/Switch/index.ts b/src/components/Switch/index.ts
new file mode 100644
index 00000000..2040039d
--- /dev/null
+++ b/src/components/Switch/index.ts
@@ -0,0 +1,3 @@
+import SSwitch from './SSwitch.vue'
+
+export { SSwitch }
diff --git a/src/components/index.ts b/src/components/index.ts
index 573e5ba2..6e2a173a 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -23,7 +23,9 @@ import { SInput, SJsonInput } from './Input'
import { SMain } from './Layout/Main'
import { SMenu, SMenuItem, SMenuItemGroup, SSubmenu } from './Menu'
import { SPagination } from './Pagination'
-import { SRadio } from './Radio'
+import { SSlider } from './Slider'
+import { SSwitch } from './Switch'
+import { SRadio, SRadioGroup } from './Radio'
import { SRow } from './Layout/Row'
import { SScrollSectionItem, SScrollSections } from './ScrollSections'
import { SSelect, SOption, SOptionGroup } from './Select'
@@ -64,11 +66,14 @@ export {
SOptionGroup,
SPagination,
SRadio,
+ SRadioGroup,
SRow,
SScrollSectionItem,
SScrollSections,
SSelect,
+ SSlider,
SSubmenu,
+ SSwitch,
STab,
STabs,
STable,
diff --git a/src/index.ts b/src/index.ts
index ba537aae..68a17fe3 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -33,11 +33,14 @@ import {
SOptionGroup,
SPagination,
SRadio,
+ SRadioGroup,
SRow,
SScrollSectionItem,
SScrollSections,
SSelect,
+ SSlider,
SSubmenu,
+ SSwitch,
STab,
STabs,
STable,
@@ -82,11 +85,14 @@ const components = [
{ component: SOptionGroup, name: Components.SOptionGroup },
{ component: SPagination, name: Components.SPagination },
{ component: SRadio, name: Components.SRadio },
+ { component: SRadioGroup, name: Components.SRadioGroup },
{ component: SRow, name: Components.SRow },
{ component: SScrollSectionItem, name: Components.SScrollSectionItem },
{ component: SScrollSections, name: Components.SScrollSections },
{ component: SSelect, name: Components.SSelect },
+ { component: SSlider, name: Components.SSlider },
{ component: SSubmenu, name: Components.SSubmenu },
+ { component: SSwitch, name: Components.SSwitch },
{ component: STab, name: Components.STab },
{ component: STabs, name: Components.STabs },
{ component: STable, name: Components.STable },
@@ -147,11 +153,14 @@ export {
SOption,
SOptionGroup,
SRadio,
+ SRadioGroup,
SRow,
SScrollSectionItem,
SScrollSections,
SSelect,
+ SSlider,
SSubmenu,
+ SSwitch,
STab,
STabs,
STable,
diff --git a/src/stories/SRadio.stories.ts b/src/stories/SRadio.stories.ts
index 0b693797..15a21449 100644
--- a/src/stories/SRadio.stories.ts
+++ b/src/stories/SRadio.stories.ts
@@ -1,6 +1,6 @@
import { withKnobs, select, boolean } from '@storybook/addon-knobs'
-import { SRadio, SRow, SCol } from '../components'
+import { SRadio, SRadioGroup, SRow, SCol } from '../components'
import { RadioSize } from '../components/Radio'
export default {
@@ -18,22 +18,22 @@ export const radioData = [
export const configurable = () => ({
components: { SRadio, SRow, SCol },
template: `
-
- changeValue = value"
- >
- {{ item.title }}
-
-
-
- v-model="{{ vModelValue }}", @change="{{ changeValue }}"
-
- `,
+
+ changeValue = value"
+ >
+ {{ item.title }}
+
+
+
+ v-model="{{ vModelValue }}", @change="{{ changeValue }}"
+
+ `,
data: () => ({
vModelValue: 'first',
changeValue: '',
@@ -55,16 +55,16 @@ export const configurable = () => ({
export const disabled = () => ({
components: { SRadio, SRow },
template: `
-
- {{ item.title }}
-
- `,
+
+ {{ item.title }}
+
+ `,
data: () => ({
model: 'first',
items: radioData
@@ -74,18 +74,51 @@ export const disabled = () => ({
export const withBorders = () => ({
components: { SRadio, SRow },
template: `
-
- {{ item.title }}
-
- `,
+
+ {{ item.title }}
+
+ `,
data: () => ({
model: 'first',
items: radioData
})
})
+
+export const radioButtonGroup = () => ({
+ components: { SRadio, SRadioGroup, SRow },
+ template: `
+
+
+ {{ item.title }}
+
+
+
+ v-model="{{ model }}"
+
+ `,
+ data: () => ({
+ model: 'first',
+ items: radioData
+ }),
+ props: {
+ size: {
+ default: select('Size', Object.values(RadioSize), RadioSize.MEDIUM)
+ },
+ disabled: {
+ default: boolean('Disabled', false)
+ }
+ }
+})
diff --git a/src/stories/SSlider.stories.ts b/src/stories/SSlider.stories.ts
new file mode 100644
index 00000000..57dd9b62
--- /dev/null
+++ b/src/stories/SSlider.stories.ts
@@ -0,0 +1,178 @@
+import { text, number, boolean, select, object, withKnobs } from '@storybook/addon-knobs'
+
+import { SSlider, SliderInputSize } from '../components/Slider'
+
+export default {
+ component: SSlider,
+ title: 'Design System/Components/Slider',
+ decorators: [withKnobs],
+ excludeStories: /.*Data$/
+}
+
+export const configurable = () => ({
+ components: { SSlider },
+ template: `
+ changeValue = value"
+ />
+
+ v-model="{{ modelValue }}", @change="{{ changeValue }}"
+
+
`,
+ data: () => ({
+ modelValue: 0,
+ changeValue: 0
+ }),
+ props: {
+ min: {
+ default: number('Minimum value', 0)
+ },
+ max: {
+ default: number('Maximum value', 100)
+ },
+ showTooltip: {
+ default: boolean('Show Tooltip', true)
+ },
+ step: {
+ default: number('Step size', 1)
+ },
+ showStops: {
+ default: boolean('Show Stops', false)
+ },
+ disabled: {
+ default: boolean('Disabled', false)
+ }
+ }
+})
+
+export const withCustomLabelAttribute = () => ({
+ components: { SSlider },
+ template: `
+ changeValue = value"
+ />
+
+ v-model="{{ modelValue }}", @change="{{ changeValue }}", label="{{ label }}"
+
+
`,
+ data: () => ({
+ modelValue: 0,
+ changeValue: 0,
+ label: 'Custom slider label value'
+ })
+})
+
+export const withInitValue = () => ({
+ components: { SSlider },
+ template: `
+ changeValue = value"
+ />
+
+ v-model="{{ modelValue }}", @change="{{ changeValue }}"
+
+
`,
+ data: () => ({
+ modelValue: 50,
+ changeValue: 0
+ })
+})
+
+export const withInput = () => ({
+ components: { SSlider },
+ template: `
+ changeValue = value"
+ />
+
+ v-model="{{ modelValue }}", @change="{{ changeValue }}"
+
+
`,
+ data: () => ({
+ modelValue: 0,
+ changeValue: 0
+ }),
+ props: {
+ showInput: {
+ default: boolean('Show Input', true)
+ },
+ showInputControls: {
+ default: boolean('Show Input Controls', true)
+ },
+ inputSize: {
+ default: select('Size of the input box', Object.values(SliderInputSize), SliderInputSize.SMALL)
+ },
+ debounce: {
+ default: number('Debounce delay when typing (in milliseconds)', 300)
+ }
+ }
+})
+
+export const withRange = () => ({
+ components: { SSlider },
+ template: `
+ changeValue = value"
+ />
+
+ v-model="{{ modelValue }}", @change="{{ changeValue }}"
+
+
`,
+ data: () => ({
+ modelValue: [0, 0],
+ changeValue: [0, 0]
+ }),
+ props: {
+ range: {
+ default: boolean('Range', true)
+ },
+ marks: {
+ default: object('Marks', {
+ 0: '0°C',
+ 8: '8°C',
+ 37: '37°C'
+ })
+ }
+ }
+})
+
+export const verticalMode = () => ({
+ components: { SSlider },
+ template: `
+ changeValue = value"
+ />
+
+ v-model="{{ modelValue }}", @change="{{ changeValue }}"
+
+
`,
+ data: () => ({
+ modelValue: 0,
+ changeValue: 0
+ }),
+ props: {
+ height: {
+ default: text('Height', '200px')
+ }
+ }
+})
diff --git a/src/stories/SSwitch.stories.ts b/src/stories/SSwitch.stories.ts
new file mode 100644
index 00000000..62c76629
--- /dev/null
+++ b/src/stories/SSwitch.stories.ts
@@ -0,0 +1,53 @@
+import { text, number, boolean, withKnobs } from '@storybook/addon-knobs'
+
+import { SSwitch } from '../components/Switch'
+
+export default {
+ component: SSwitch,
+ title: 'Design System/Components/Switch',
+ decorators: [withKnobs],
+ excludeStories: /.*Data$/
+}
+
+export const configurable = () => ({
+ components: { SSwitch },
+ template: `
+ changeValue = value"
+ />
+
+ v-model="{{ modelValue }}", @change="{{ changeValue }}"
+
+
`,
+ data: () => ({
+ modelValue: true,
+ changeValue: true
+ }),
+ props: {
+ activeText: {
+ default: text('Active Text', '')
+ },
+ inactiveText: {
+ default: text('Inactive Text', '')
+ },
+ activeValue: {
+ default: text('Active Value', 'Active Value')
+ },
+ inactiveValue: {
+ default: text('Inactive Value', 'Inactive Value')
+ },
+ width: {
+ default: number('Width', 40)
+ },
+ disabled: {
+ default: boolean('Disabled', false)
+ }
+ }
+})
diff --git a/src/styles/index.scss b/src/styles/index.scss
index 9b2002d7..ae273633 100644
--- a/src/styles/index.scss
+++ b/src/styles/index.scss
@@ -18,6 +18,8 @@
@import "./radio";
@import "./scroll-sections";
@import "./select";
+@import "./slider";
+@import "./switch";
@import "./tabs";
@import "./table";
@import "./tooltip";
diff --git a/src/styles/radio.scss b/src/styles/radio.scss
index f7a0079d..8b92601b 100644
--- a/src/styles/radio.scss
+++ b/src/styles/radio.scss
@@ -1,6 +1,29 @@
@import "./variables";
@import "./common";
+$radio-button-class: ".el-radio-button";
+$radio-button-border-width: 1px;
+$radio-button-border-color: var(--s-color-main-brand);
+
+@mixin radio-button-size(
+ $modifier: "small",
+ $size: $s-size-small,
+ $font-size: $s-font-size-small
+) {
+ $radio-button-vertical-padding: #{($size - $font-size) / 2 - $radio-button-border-width};
+ #{$radio-button-class} {
+ &--#{$modifier} {
+ height: $size;
+ line-height: $size;
+ #{$radio-button-class}__inner {
+ padding-top: $radio-button-vertical-padding;
+ padding-bottom: $radio-button-vertical-padding;
+ font-size: $font-size;
+ }
+ }
+ }
+}
+
.el-radio {
color: var(--s-color-basic-black);
&.s-big {
@@ -98,4 +121,91 @@
}
}
}
+ &-button {
+ &:hover {
+ #{$radio-button-class}__inner {
+ border-color: $radio-button-border-color;
+ color: var(--s-color-main-brand);
+ }
+ &:not(:first-child):not(.is-disabled) {
+ #{$radio-button-class}__inner {
+ &:before {
+ opacity: 1;
+ }
+ }
+ }
+ }
+ &:not(:first-child):not(.is-disabled) {
+ #{$radio-button-class}__inner {
+ position: relative;
+ &:before {
+ content: "";
+ position: absolute;
+ display: block;
+ opacity: 0;
+ background-color: $radio-button-border-color;
+ height: calc(100% + #{$radio-button-border-width * 2});
+ width: $radio-button-border-width;
+ left: -#{$radio-button-border-width};
+ top: -#{$radio-button-border-width};
+ transition: inherit;
+ transition-property: opacity;
+ }
+ }
+ }
+ &.is-disabled {
+ #{$radio-button-class}__inner {
+ color: var(--s-color-neutral-inactive);
+ }
+ }
+ &.is-disabled,
+ &.is-disabled:hover {
+ #{$radio-button-class}__inner {
+ border-color: var(--s-color-neutral-border);
+ }
+ }
+ &.is-active {
+ &:hover {
+ #{$radio-button-class}__inner {
+ background-color: var(--s-color-main-hover);
+ border-color: var(--s-color-main-hover);
+ }
+ }
+ &.is-disabled {
+ #{$radio-button-class}__inner {
+ color: var(--s-color-basic-white);
+ }
+ }
+ &.is-disabled,
+ &.is-disabled:hover {
+ #{$radio-button-class}__inner {
+ background-color: var(--s-color-main-inactive);
+ border-color: var(--s-color-main-inactive);
+ }
+ }
+ }
+ }
+ &-group {
+ @include radio-button-size;
+ @include radio-button-size("medium", $s-size-medium, $s-font-size-big);
+ @include radio-button-size("big", $s-size-big, $s-font-size-big);
+ #{$radio-button-class} {
+ &__inner {
+ background-color: var(--s-color-basic-white);
+ border-color: var(--s-color-neutral-border);
+ color: var(--s-color-basic-black);
+ }
+ #{$radio-button-class}__inner {
+ box-shadow: none;
+ }
+ }
+ .is-disabled #{$radio-button-class}__inner {
+ background-color: var(--s-color-basic-white);
+ }
+ .is-active #{$radio-button-class}__inner {
+ background-color: var(--s-color-main-brand);
+ border-color: var(--s-color-main-brand);
+ color: var(--s-color-basic-white);
+ }
+ }
}
diff --git a/src/styles/slider.scss b/src/styles/slider.scss
new file mode 100644
index 00000000..7940b83e
--- /dev/null
+++ b/src/styles/slider.scss
@@ -0,0 +1,100 @@
+@import "./variables";
+
+@mixin slider-colors(
+ $background-color: --s-color-main-brand,
+ $border-color: $background-color,
+ $color: false
+) {
+ background-color: var($background-color);
+ border-color: var($border-color);
+
+ @if $color != false {
+ color: var($color);
+ }
+}
+
+@mixin slider-input-size($modifier: "mini", $size: $s-size-mini) {
+ .el-input-number--#{$modifier} {
+ line-height: $size;
+ .el-input__inner {
+ height: $size;
+ line-height: $size;
+ }
+ }
+}
+
+.s-slider {
+ .el-slider__runway,
+ .disabled .el-slider__runway {
+ background-color: var(--s-color-neutral-placeholder);
+ }
+ .el-slider {
+ &__button {
+ @include slider-colors;
+ }
+ &__marks-text {
+ color: var(--s-color-basic-black);
+ }
+ &__bar {
+ background-color: var(--s-color-main-brand);
+ }
+ }
+ .disabled {
+ .el-slider__bar {
+ background-color: var(--s-color-neutral-border);
+ }
+ .el-slider__button {
+ @include slider-colors(--s-color-neutral-border);
+ }
+ }
+ .el-input {
+ &__inner {
+ @include slider-colors(--s-color-neutral-placeholder);
+ &:hover:not([disabled]):not(:focus) {
+ @include slider-colors(--s-color-neutral-hover);
+ }
+ &:focus {
+ @include slider-colors(--s-color-basic-white, --s-color-neutral-border);
+ }
+ }
+ &-number {
+ &__decrease,
+ &__increase {
+ height: 100%;
+ top: 0;
+ color: var(--s-color-basic-white);
+ @include slider-colors($color: --s-color-basic-white);
+ &:hover:not(.is-disabled)
+ ~ .el-input
+ .el-input__inner:not(.is-disabled) {
+ border-color: var(--s-color-neutral-hover);
+ }
+ &.is-disabled {
+ @include slider-colors(
+ $background-color: --s-color-main-inactive,
+ $color: --s-color-basic-white
+ );
+ }
+ }
+ &__decrease {
+ left: 0;
+ }
+ &__increase {
+ right: 0;
+ }
+ &.is-disabled {
+ .el-input-number__decrease,
+ .el-input-number__increase {
+ @include slider-colors(
+ $background-color: --s-color-main-inactive,
+ $color: --s-color-basic-white
+ );
+ }
+ }
+ }
+ }
+ @include slider-input-size;
+ @include slider-input-size("small", $s-size-small);
+ @include slider-input-size("medium", $s-size-medium);
+ @include slider-input-size("big", $s-size-big);
+}
diff --git a/src/styles/switch.scss b/src/styles/switch.scss
new file mode 100644
index 00000000..ef8f32d1
--- /dev/null
+++ b/src/styles/switch.scss
@@ -0,0 +1,47 @@
+@import "./variables";
+
+$switch-class: ".el-switch";
+
+.s-switch {
+ #{$switch-class} {
+ &__label {
+ color: var(--s-color-basic-black);
+ &.is-active {
+ color: var(--s-color-main-brand);
+ }
+ }
+ &__core {
+ border-color: var(--s-color-neutral-border);
+ background-color: var(--s-color-neutral-border);
+ &:after {
+ background-color: var(--s-color-basic-white);
+ }
+ }
+ &:hover,
+ &.is-checked:hover {
+ #{$switch-class}__core {
+ background-color: var(--s-color-main-hover);
+ border-color: var(--s-color-main-hover);
+ }
+ }
+ &.is-disabled {
+ opacity: 1;
+ #{$switch-class}__core {
+ background-color: var(--s-color-neutral-placeholder);
+ border-color: var(--s-color-neutral-placeholder);
+ }
+ }
+ &.is-checked {
+ #{$switch-class}__core {
+ background-color: var(--s-color-main-brand);
+ border-color: var(--s-color-main-brand);
+ }
+ &.is-disabled {
+ #{$switch-class}__core {
+ background-color: var(--s-color-main-inactive);
+ border-color: var(--s-color-main-inactive);
+ }
+ }
+ }
+ }
+}
diff --git a/src/styles/variables.scss b/src/styles/variables.scss
index 238ae45c..4d403700 100644
--- a/src/styles/variables.scss
+++ b/src/styles/variables.scss
@@ -21,11 +21,16 @@ $s-color-basic-white: #FFF !default;
$s-size-big: 56px !default;
$s-size-medium: 40px !default;
$s-size-small: 32px !default;
+$s-size-mini: 24px !default;
$s-border-radius-default: 4px !default;
// Fonts
$font-family-default: 'Sora', sans-serif !important;
$font-family-mono: 'JetBrainsMono', monospace !important;
+// Font sizes
+$s-font-size-big: 14px !default;
+$s-font-size-small: 12px !default;
+
// Responsive
$--sm: 640px !default;
$--md: 1024px !default;
diff --git a/src/types/components.ts b/src/types/components.ts
index 3c4d1a20..2f3923f9 100644
--- a/src/types/components.ts
+++ b/src/types/components.ts
@@ -31,11 +31,14 @@ export enum Components {
SOptionGroup = 'SOptionGroup',
SPagination = 'SPagination',
SRadio = 'SRadio',
+ SRadioGroup = 'SRadioGroup',
SRow = 'SRow',
SScrollSectionItem = 'SScrollSectionItem',
SScrollSections = 'SScrollSections',
SSelect = 'SSelect',
+ SSlider = 'SSlider',
SSubmenu = 'SSubmenu',
+ SSwitch = 'SSwitch',
STab = 'STab',
STabs = 'STabs',
STable = 'STable',