Skip to content

Commit f74d4ad

Browse files
maxnoyMaksim Noy
authored and
Maksim Noy
committed
Checkbox descriptions are clickable and on the right, improved spacing for radios and descriptions
1 parent 386ae4d commit f74d4ad

File tree

3 files changed

+75
-10
lines changed

3 files changed

+75
-10
lines changed

ipywidgets/widgets/widget_bool.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,12 @@ class Checkbox(_Bool):
3838
value of the checkbox: True-checked, False-unchecked
3939
description : str
4040
description displayed next to the checkbox
41+
indent : {True,False}
42+
indent the control to align with other controls with a description
4143
"""
4244
_view_name = Unicode('CheckboxView').tag(sync=True)
4345
_model_name = Unicode('CheckboxModel').tag(sync=True)
46+
indent = Bool(True, help="Indent the control to align with other controls with a description").tag(sync=True)
4447

4548

4649
@register

jupyter-js-widgets/css/widgets-base.css

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
--jp-widgets-progress-thickness: 20px;
3131
--jp-widgets-container-padding: 15px;
3232
--jp-widgets-input-padding: 4px;
33+
--jp-widgets-radio-item-height-adjustment: 8px;
34+
--jp-widgets-radio-item-height: calc(var(--jp-widgets-inline-height) - var(--jp-widgets-radio-item-height-adjustment));
3335
--jp-widgets-slider-track-thickness: 4px;
3436
--jp-widgets-slider-border-width: var(--jp-widgets-border-width);
3537
--jp-widgets-slider-handle-size: 16px;
@@ -243,6 +245,16 @@
243245

244246
/* Widget Label Styling */
245247

248+
.widget-label-basic {
249+
/* Basic Label */
250+
color: var(--jp-widgets-label-color);
251+
font-size: var(--jp-widgets-font-size);
252+
overflow: hidden;
253+
text-overflow: ellipsis;
254+
white-space: nowrap;
255+
line-height: var(--jp-widgets-inline-height);
256+
}
257+
246258
.widget-label {
247259
/* Label */
248260
color: var(--jp-widgets-label-color);
@@ -258,7 +270,7 @@
258270
/* Horizontal Widget Label */
259271
color: var(--jp-widgets-label-color);
260272
text-align: right;
261-
margin-right: var(--jp-widgets-inline-margin);
273+
margin-right: calc( var(--jp-widgets-inline-margin) * 2 );
262274
max-width: var(--jp-widgets-inline-label-max-width);
263275
min-width: var(--jp-widgets-inline-label-min-width);
264276
flex-shrink: 0;
@@ -320,14 +332,13 @@
320332
/* Widget Checkbox Styling */
321333

322334
.widget-checkbox {
323-
width: var(--jp-widgets-inline-width-short);
335+
width: var(--jp-widgets-inline-width);
324336
height: var(--jp-widgets-inline-height);
325337
line-height: var(--jp-widgets-inline-height);
326-
justify-content: space-between;
327338
}
328339

329340
.widget-checkbox input[type="checkbox"] {
330-
margin: 0px var(--jp-widgets-inline-margin) 0px var(--jp-widgets-inline-margin);
341+
margin: 0px calc( var(--jp-widgets-inline-margin) * 2 ) 0px 0px;
331342
line-height: var(--jp-widgets-inline-height);
332343
font-size: large;
333344
flex-grow: 1;
@@ -713,18 +724,19 @@
713724
align-items: stretch;
714725
box-sizing: border-box;
715726
flex-grow: 1;
727+
margin-bottom: var(--jp-widgets-radio-item-height-adjustment);
716728
}
717729

718730
.widget-radio-box label {
719-
height: var(--jp-widgets-inline-height);
720-
line-height: var(--jp-widgets-inline-height);
731+
height: var(--jp-widgets-radio-item-height);
732+
line-height: var(--jp-widgets-radio-item-height);
721733
font-size: var(--jp-widgets-font-size);
722734
}
723735

724736
.widget-radio-box input {
725-
height: var(--jp-widgets-inline-height);
726-
line-height: var(--jp-widgets-inline-height);
727-
margin: 0 var(--jp-widgets-input-padding) 0 var(--jp-widgets-input-padding);
737+
height: var(--jp-widgets-radio-item-height);
738+
line-height: var(--jp-widgets-radio-item-height);
739+
margin: 0 calc( var(--jp-widgets-input-padding) * 2 ) 0 1px;
728740
float: left;
729741
}
730742

jupyter-js-widgets/src/widget_bool.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export
2727
class CheckboxModel extends CoreLabeledDOMWidgetModel {
2828
defaults() {
2929
return _.extend(super.defaults(), {
30+
indent: true,
3031
_view_name: 'CheckboxView',
3132
_model_name: 'CheckboxModel'
3233
});
@@ -44,11 +45,57 @@ class CheckboxView extends LabeledDOMWidgetView {
4445
this.el.classList.add('widget-inline-hbox');
4546
this.el.classList.add('widget-checkbox');
4647

48+
// adding a zero-width space to the label to help
49+
// the browser set the baseline correctly
50+
this.label.innerHTML = '​'
51+
52+
// label containing the checkbox and description span
53+
this.checkboxLabel = document.createElement('label');
54+
this.checkboxLabel.classList.add('widget-label-basic');
55+
this.el.appendChild(this.checkboxLabel);
56+
57+
// checkbox
4758
this.checkbox = document.createElement('input');
4859
this.checkbox.setAttribute('type', 'checkbox');
49-
this.el.appendChild(this.checkbox);
60+
this.checkboxLabel.appendChild(this.checkbox);
61+
62+
// span to the right of the checkbox that will render the description
63+
this.descriptionSpan = document.createElement('span');
64+
this.checkboxLabel.appendChild(this.descriptionSpan);
65+
66+
this.listenTo(this.model, 'change:indent', this.updateIndent);
5067

5168
this.update(); // Set defaults.
69+
this.updateDescription();
70+
this.updateIndent();
71+
}
72+
73+
/**
74+
* Overriden from super class
75+
*
76+
* Update the description span (rather than the label) since
77+
* we want the description to the right of the checkbox.
78+
*/
79+
updateDescription() {
80+
// can be called before the view is fully initialized
81+
if (this.checkboxLabel == null)
82+
return;
83+
84+
let description = this.model.get('description');
85+
this.descriptionSpan.innerHTML = description;
86+
this.typeset(this.descriptionSpan);
87+
this.descriptionSpan.title = description;
88+
this.checkbox.title = description;
89+
}
90+
91+
/**
92+
* Update the visibility of the label in the super class
93+
* to provide the optional indent.
94+
*/
95+
updateIndent() {
96+
console.log('updating indent');
97+
let indent = this.model.get('indent');
98+
this.label.style.display = indent ? '' : 'none';
5299
}
53100

54101
events(): {[e: string]: string} {
@@ -83,7 +130,10 @@ class CheckboxView extends LabeledDOMWidgetView {
83130
}
84131
return super.update();
85132
}
133+
86134
checkbox: HTMLInputElement;
135+
checkboxLabel: HTMLLabelElement;
136+
descriptionSpan: HTMLSpanElement;
87137
}
88138

89139

0 commit comments

Comments
 (0)