Commit 24196763 authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch '38239-update-toggle-design' into 'master'

Update feature toggle design to use icons and make it i18n friendly

Closes #38239

See merge request gitlab-org/gitlab-ce!15904
parents 627a9687 d0edbf6d
<script> <script>
import { s__ } from '../../locale';
import icon from './icon.vue';
import loadingIcon from './loading_icon.vue'; import loadingIcon from './loading_icon.vue';
const ICON_ON = 'status_success_borderless';
const ICON_OFF = 'status_failed_borderless';
const LABEL_ON = s__('ToggleButton|Toggle Status: ON');
const LABEL_OFF = s__('ToggleButton|Toggle Status: OFF');
export default { export default {
props: { props: {
name: { name: {
...@@ -22,19 +29,10 @@ ...@@ -22,19 +29,10 @@
required: false, required: false,
default: false, default: false,
}, },
enabledText: {
type: String,
required: false,
default: 'Enabled',
},
disabledText: {
type: String,
required: false,
default: 'Disabled',
},
}, },
components: { components: {
icon,
loadingIcon, loadingIcon,
}, },
...@@ -43,6 +41,15 @@ ...@@ -43,6 +41,15 @@
event: 'change', event: 'change',
}, },
computed: {
toggleIcon() {
return this.value ? ICON_ON : ICON_OFF;
},
ariaLabel() {
return this.value ? LABEL_ON : LABEL_OFF;
},
},
methods: { methods: {
toggleFeature() { toggleFeature() {
if (!this.disabledInput) this.$emit('change', !this.value); if (!this.disabledInput) this.$emit('change', !this.value);
...@@ -60,10 +67,8 @@ ...@@ -60,10 +67,8 @@
/> />
<button <button
type="button" type="button"
aria-label="Toggle"
class="project-feature-toggle" class="project-feature-toggle"
:data-enabled-text="enabledText" :aria-label="ariaLabel"
:data-disabled-text="disabledText"
:class="{ :class="{
'is-checked': value, 'is-checked': value,
'is-disabled': disabledInput, 'is-disabled': disabledInput,
...@@ -72,6 +77,11 @@ ...@@ -72,6 +77,11 @@
@click="toggleFeature" @click="toggleFeature"
> >
<loadingIcon class="loading-icon" /> <loadingIcon class="loading-icon" />
<span class="toggle-icon">
<icon
css-classes="toggle-icon-svg"
:name="toggleIcon"/>
</span>
</button> </button>
</label> </label>
</template> </template>
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
border: 0; border: 0;
outline: 0; outline: 0;
display: block; display: block;
width: 100px; width: 50px;
height: 24px; height: 24px;
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
...@@ -42,31 +42,31 @@ ...@@ -42,31 +42,31 @@
background: none; background: none;
} }
&::before { .toggle-icon {
color: $feature-toggle-text-color;
font-size: 12px;
line-height: 24px;
position: absolute;
top: 0;
left: 25px;
right: 5px;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
animation: animate-disabled .2s ease-in;
content: attr(data-disabled-text);
}
&::after {
position: relative; position: relative;
display: block; display: block;
content: "";
width: 22px;
height: 18px;
left: 0; left: 0;
border-radius: 9px; border-radius: 9px;
background: $feature-toggle-color; background: $feature-toggle-color;
transition: all .2s ease; transition: all .2s ease;
&,
.toggle-icon-svg {
width: 18px;
height: 18px;
}
.toggle-icon-svg {
fill: $feature-toggle-color-disabled;
}
.toggle-status-checked {
display: none;
}
.toggle-status-unchecked {
display: inline;
}
} }
.loading-icon { .loading-icon {
...@@ -77,11 +77,10 @@ ...@@ -77,11 +77,10 @@
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
&.is-loading { &.is-loading {
&::before { .toggle-icon {
display: none; display: none;
} }
...@@ -100,15 +99,20 @@ ...@@ -100,15 +99,20 @@
&.is-checked { &.is-checked {
background: $feature-toggle-color-enabled; background: $feature-toggle-color-enabled;
&::before { .toggle-icon {
left: 5px; left: calc(100% - 18px);
right: 25px;
animation: animate-enabled .2s ease-in;
content: attr(data-enabled-text);
}
&::after { .toggle-icon-svg {
left: calc(100% - 22px); fill: $feature-toggle-color-enabled;
}
.toggle-status-checked {
display: inline;
}
.toggle-status-unchecked {
display: none;
}
} }
} }
......
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
class: "js-toggle-cluster-list project-feature-toggle #{'is-checked' if cluster.enabled?} #{'is-disabled' if !cluster.can_toggle_cluster?}", class: "js-toggle-cluster-list project-feature-toggle #{'is-checked' if cluster.enabled?} #{'is-disabled' if !cluster.can_toggle_cluster?}",
"aria-label": s_("ClusterIntegration|Toggle Cluster"), "aria-label": s_("ClusterIntegration|Toggle Cluster"),
disabled: !cluster.can_toggle_cluster?, disabled: !cluster.can_toggle_cluster?,
data: { "enabled-text": s_("ClusterIntegration|Active"), data: { endpoint: namespace_project_cluster_path(@project.namespace, @project, cluster, format: :json) } }
"disabled-text": s_("ClusterIntegration|Inactive"),
endpoint: namespace_project_cluster_path(@project.namespace, @project, cluster, format: :json) } }
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
%span.toggle-icon
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
= sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
...@@ -7,8 +7,10 @@ ...@@ -7,8 +7,10 @@
%button{ type: 'button', %button{ type: 'button',
class: "js-toggle-cluster project-feature-toggle #{'is-checked' unless !@cluster.enabled?} #{'is-disabled' unless can?(current_user, :update_cluster, @cluster)}", class: "js-toggle-cluster project-feature-toggle #{'is-checked' unless !@cluster.enabled?} #{'is-disabled' unless can?(current_user, :update_cluster, @cluster)}",
"aria-label": s_("ClusterIntegration|Toggle Cluster"), "aria-label": s_("ClusterIntegration|Toggle Cluster"),
disabled: !can?(current_user, :update_cluster, @cluster), disabled: !can?(current_user, :update_cluster, @cluster) }
data: { "enabled-text": s_("ClusterIntegration|Active"), "disabled-text": s_("ClusterIntegration|Inactive"), } } %span.toggle-icon
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
= sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
- if can?(current_user, :update_cluster, @cluster) - if can?(current_user, :update_cluster, @cluster)
.form-group .form-group
......
---
title: Update feature toggle design to use icons and make it i18n friendly
merge_request: 15904
author:
type: changed
...@@ -30,9 +30,9 @@ describe('Toggle Button', () => { ...@@ -30,9 +30,9 @@ describe('Toggle Button', () => {
expect(vm.$el.querySelector('input').getAttribute('value')).toEqual('true'); expect(vm.$el.querySelector('input').getAttribute('value')).toEqual('true');
}); });
it('renders Enabled and Disabled text data attributes', () => { it('renders input status icon', () => {
expect(vm.$el.querySelector('button').getAttribute('data-enabled-text')).toEqual('Enabled'); expect(vm.$el.querySelectorAll('span.toggle-icon').length).toEqual(1);
expect(vm.$el.querySelector('button').getAttribute('data-disabled-text')).toEqual('Disabled'); expect(vm.$el.querySelectorAll('svg.s16.toggle-icon-svg').length).toEqual(1);
}); });
}); });
...@@ -49,6 +49,14 @@ describe('Toggle Button', () => { ...@@ -49,6 +49,14 @@ describe('Toggle Button', () => {
expect(vm.$el.querySelector('button').classList.contains('is-checked')).toEqual(true); expect(vm.$el.querySelector('button').classList.contains('is-checked')).toEqual(true);
}); });
it('sets aria-label representing toggle state', () => {
vm.value = true;
expect(vm.ariaLabel).toEqual('Toggle Status: ON');
vm.value = false;
expect(vm.ariaLabel).toEqual('Toggle Status: OFF');
});
it('emits change event when clicked', () => { it('emits change event when clicked', () => {
vm.$el.querySelector('button').click(); vm.$el.querySelector('button').click();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment