Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 5 additions & 15 deletions docs/components_page/components/button_group.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,36 +29,26 @@ Stack buttons in the `ButtonGroup` vertically by setting `vertical=True`.

## RadioItems as ButtonGroup

Sometimes you might like to use a `ButtonGroup` to let the user choose from a set of options, where the currently chosen option is indicated by that button being marked as "active". Since this requires that buttons respond to other buttons in the group being clicked on, it can be a little awkward to achieve when each button is a separate Dash component. Instead it is easier to use `RadioItems` and do some customisation of the styling. Most of the customisation is achieved with the `label_class_name` and `label_checked_class_name` props of the `RadioItems` component, though some additional CSS is required (see below).

{{example:components/button_group/radios.py:button_group}}
Sometimes you might like to use a `ButtonGroup` to let the user choose from a set of options, where the currently chosen option is indicated by that button being marked as "active". Since this requires that buttons respond to other buttons in the group being clicked on, it can be a little awkward to achieve when each button is a separate Dash component. Instead it is easier to use `RadioItems` and do some customisation of the styling. Most of the customisation is achieved with the `input_class_name`, `label_class_name` and `label_checked_class_name` props of the `RadioItems` component, though some additional CSS is required (see below).

```css
/* Turn off existing buttons */
.radio-group .custom-control-input ~ .custom-control-label::before {
content: none;
}

.radio-group .custom-radio .custom-control-input ~ .custom-control-label::after {
content: none;
}

/* restyle radio items */
.radio-group .custom-control {
.radio-group .form-check {
padding-left: 0;
}

.radio-group .btn-group > .custom-control:not(:last-child) > .btn {
.radio-group .btn-group > .form-check:not(:last-child) > .btn {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}

.radio-group .btn-group > .custom-control:not(:first-child) > .btn {
.radio-group .btn-group > .form-check:not(:first-child) > .btn {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
margin-left: -1px;
}
```

{{example:components/button_group/radios.py:button_group}}

{{apidoc:src/components/ButtonGroup.js}}
3 changes: 2 additions & 1 deletion docs/components_page/components/button_group/radios.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ button_group <- htmlDiv(
dbcRadioItems(
id = "radios",
class_name = "btn-group",
label_class_name = "btn btn-secondary",
input_class_name="btn-check",
label_class_name = "btn btn-outline-primary",
label_checked_class_name = "active",
options = list(
list(label = "Option 1", value = 1),
Expand Down
3 changes: 2 additions & 1 deletion docs/components_page/components/button_group/radios.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ button_group = html_div(
dbc_radioitems(
id = "radios",
class_name = "btn-group",
label_class_name = "btn btn-secondary",
input_class_name = "btn-check",
label_class_name = "btn btn-outline-primary",
label_checked_class_name = "active",
options = [
Dict("label" => "Option 1", "value" => 1),
Expand Down
3 changes: 2 additions & 1 deletion docs/components_page/components/button_group/radios.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
dbc.RadioItems(
id="radios",
class_name="btn-group",
label_class_name="btn btn-secondary",
input_class_name="btn-check",
label_class_name="btn btn-outline-primary",
label_checked_class_name="active",
options=[
{"label": "Option 1", "value": 1},
Expand Down
16 changes: 3 additions & 13 deletions docs/components_page/components/input.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,7 @@ Set `inline=True` to make the radio items or checklists fit next to each other o

## Checked item styles

Use the `labelCheckedStyle` and `label_checked_class_name` arguments to apply different styles to the labels of checked items. When using custom inputs you can override the styles of the inputs using custom CSS. See the below example.

```css
#checklist-selected-style
.custom-control-input:checked
~ .custom-control-label::before {
background-color: #fa7268;
border-color: #ea6258;
}
```
Use the `input_checked_style`, `input_checked_class_name`, `label_checked_style` and `label_checked_class_name` arguments to apply different styles to the labels of checked items.

{{example:components/input/selected_styles.py:checklist}}

Expand All @@ -98,13 +89,12 @@ When using `Input` with `type="color"`, the user may specify a color, either by

Note that the color picker presentation may vary substantially from one browser and/or platform to another.

As you drag the selector around the color picker, notice that the text color is smoothly updated. While this is a nice feature, it may cause a performance issue in your app, because the callback fires continuously.
As you drag the selector around the color picker, notice that the text color is smoothly updated. While this is a nice feature, it may cause a performance issue in your app, because the callback fires continuously.

This is a great use-case for a [Dash clientside callback](https://dash.plotly.com/clientside-callbacks). This example uses a clientside callback so the callback runs directly in the browser instead of making requests to the Dash server. For your reference, the regular Dash callback is shown as a comment.
This is a great use-case for a [Dash clientside callback](https://dash.plotly.com/clientside-callbacks). This example uses a clientside callback so the callback runs directly in the browser instead of making requests to the Dash server. For your reference, the regular Dash callback is shown as a comment.

{{example:components/input/colorpicker.py:colorpicker}}


{{apidoc:src/components/input/Input.js}}

{{apidoc:src/components/input/Textarea.js}}
Expand Down
36 changes: 28 additions & 8 deletions docs/components_page/components/input/selected_styles.R
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
library(dashBootstrapComponents)
library(dashHtmlComponents)

checklist <- dbcChecklist(
id = "checklist-selected-style",
options = list(
list(label = "Option 1", value = 1),
list(label = "Option 2", value = 2),
list(label = "Option 3", value = 3)
),
labelCheckedStyle = list(color = "red")
checklist <- htmlDiv(
list(
dbcChecklist(
id = "checklist-selected-style",
options = list(
list(label = "Option 1", value = 1),
list(label = "Option 2", value = 2),
list(label = "Option 3", value = 3)
),
label_checked_style=list("color" = "red"),
input_checked_style=list(
"backgroundColor" = "#fa7268",
"borderColor" = "#ea6258"
)
),
htmlHr(),
dbcRadioItems(
id="radio-selected-style",
options = list(
list(label = "Option 1", value = 1),
list(label = "Option 2", value = 2),
list(label = "Option 3", value = 3)
),
label_checked_class_name="text-success",
input_checked_class_name="border border-success bg-success"
)
)
)
36 changes: 27 additions & 9 deletions docs/components_page/components/input/selected_styles.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
using DashBootstrapComponents
using DashHtmlComponents

checklist = dbc_checklist(
id = "checklist-selected-style",
options = [
Dict("label" => "Option 1", "value" => 1),
Dict("label" => "Option 2", "value" => 2),
Dict("label" => "Option 3", "value" => 3),
],
labelCheckedStyle = Dict("color" => "red"),
);
checklist = html_div([
dbc_checklist(
id = "checklist-selected-style",
options = [
Dict("label" => "Option 1", "value" => 1),
Dict("label" => "Option 2", "value" => 2),
Dict("label" => "Option 3", "value" => 3),
],
label_checked_style = Dict("color" => "red"),
input_checked_style = Dict(
"backgroundColor" => "#fa7268",
"borderColor" => "#ea6258",
),
),
html_hr(),
dbc_radioitems(
id = "radio-selected-style",
options = [
Dict("label" => "Option 1", "value" => 1),
Dict("label" => "Option 2", "value" => 2),
Dict("label" => "Option 3", "value" => 3),
],
label_checked_class_name = "text-success",
input_checked_class_name = "border border-success bg-success",
),
]);
36 changes: 28 additions & 8 deletions docs/components_page/components/input/selected_styles.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
import dash_bootstrap_components as dbc
import dash_html_components as html

checklist = dbc.Checklist(
id="checklist-selected-style",
options=[
{"label": "Option 1", "value": 1},
{"label": "Option 2", "value": 2},
{"label": "Option 3", "value": 3},
],
labelCheckedStyle={"color": "red"},
checklist = html.Div(
[
dbc.Checklist(
id="checklist-selected-style",
options=[
{"label": "Option 1", "value": 1},
{"label": "Option 2", "value": 2},
{"label": "Option 3", "value": 3},
],
label_checked_style={"color": "red"},
input_checked_style={
"backgroundColor": "#fa7268",
"borderColor": "#ea6258",
},
),
html.Hr(),
dbc.RadioItems(
id="radio-selected-style",
options=[
{"label": "Option 1", "value": 1},
{"label": "Option 2", "value": 2},
{"label": "Option 3", "value": 3},
],
label_checked_class_name="text-success",
input_checked_class_name="border border-success bg-success",
),
]
)
29 changes: 3 additions & 26 deletions docs/static/docs.css
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,6 @@ span.hljs-meta {
display: none;
}

/* Custom checkbox example CSS */
#checklist-selected-style
.custom-control-input:checked
~ .custom-control-label::before {
background-color: #fa7268;
border-color: #ea6258;
}

/* invalid input styling */
#styled-numeric-input input:invalid {
border-color: #dc3545;
Expand All @@ -152,29 +144,14 @@ span.hljs-meta {
}

/* radio button group example */
.button-group-demo
.radio-group
.custom-control-input
~ .custom-control-label::before {
content: none;
}

.button-group-demo
.radio-group
.custom-radio
.custom-control-input
~ .custom-control-label::after {
content: none;
}

.button-group-demo .radio-group .custom-control {
.button-group-demo .radio-group .form-check {
padding-left: 0;
}

.button-group-demo
.radio-group
.btn-group
> .custom-control:not(:last-child)
> .form-check:not(:last-child)
> .btn {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
Expand All @@ -183,7 +160,7 @@ span.hljs-meta {
.button-group-demo
.radio-group
.btn-group
> .custom-control:not(:first-child)
> .form-check:not(:first-child)
> .btn {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
Expand Down
44 changes: 42 additions & 2 deletions src/components/input/Checklist.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ const Checklist = props => {
id,
inputClassName,
input_class_name,
inputCheckedClassName,
input_checked_class_name,
inputStyle,
input_style,
inputCheckedStyle,
input_checked_style,
labelClassName,
label_class_name,
labelCheckedClassName,
Expand All @@ -45,6 +49,13 @@ const Checklist = props => {

const checked = includes(option.value, value);

const mergedInputStyle = checked
? {
...(input_style || inputStyle),
...(input_checked_style || inputCheckedStyle)
}
: input_style || inputStyle;

const mergedLabelStyle = checked
? {
...(label_style || labelStyle),
Expand All @@ -70,10 +81,11 @@ const Checklist = props => {
checked={checked}
className={classNames(
'form-check-input',
input_class_name || inputClassName
input_class_name || inputClassName,
checked && (input_checked_class_name || inputCheckedClassName)
)}
disabled={Boolean(option.disabled)}
style={input_style || inputStyle}
style={mergedInputStyle}
type="checkbox"
onChange={() => {
let newValue;
Expand Down Expand Up @@ -205,6 +217,20 @@ Checklist.propTypes = {
*/
inputStyle: PropTypes.object,

/**
* Additional inline style arguments to apply to <input> elements on checked
* items.
*/
input_checked_style: PropTypes.object,

/**
* **DEPRECATED** Use `input_checked_style` instead.
*
* Additional inline style arguments to apply to <input> elements on checked
* items.
*/
inputCheckedStyle: PropTypes.object,

/**
* The class of the <input> checkbox element
*/
Expand All @@ -217,6 +243,20 @@ Checklist.propTypes = {
*/
inputClassName: PropTypes.string,

/**
* Additional CSS classes to apply to the <input> element when the
* corresponding checkbox is checked.
*/
input_checked_class_name: PropTypes.string,

/**
* **DEPRECATED** Use `input_checked_class_name` instead.
*
* Additional CSS classes to apply to the <input> element when the
* corresponding checkbox is checked.
*/
inputCheckedClassName: PropTypes.string,

/**
* Inline style arguments to apply to the <label> element for each item.
*/
Expand Down
Loading