add CheckboxCard, CheckboxIndicator, RadioCard, RadioIndicator #486#509
add CheckboxCard, CheckboxIndicator, RadioCard, RadioIndicator #486#509AnnMarieW merged 10 commits intosnehilvj:masterfrom
Conversation
|
Hi @deadkex This looks awesome! Thanks for the great PR 🚀 Callbacks work perfectly after fixing the typo in the id Try changing dmc.Box(id="output2", children="Output 1:"),To dmc.Box(id="output1", children="Output 1:"),I'll take a closer look at the rest later, but just wanted you to know that the callbacks work 🙂 |
import dash
from dash import Dash, Input, Output, callback
import dash_mantine_components as dmc
dash._dash_renderer._set_react_version('18.2.0') # noqa
app = Dash(external_stylesheets=dmc.styles.ALL)
app.layout = dmc.MantineProvider(
forceColorScheme="dark",
children=dmc.Box([
dmc.CheckboxGroup(
id="cbg",
label="CheckboxCard Group",
children=dmc.Group([
dmc.CheckboxCard(
className="checkboxcardroot",
children=[dmc.Stack([dmc.Text("CheckboxCard 1, no Checkbox", size="xl"),
dmc.Text("description", c="dimmed")])],
value="1"),
dmc.CheckboxCard(
className="checkboxcardroot",
children=dmc.Group(wrap="nowrap", align="flex-start", children=[
dmc.CheckboxIndicator(),
dmc.Stack([dmc.Text("CheckboxCard 2", size="xl"), dmc.Badge("A badge")])]),
value="2"),
dmc.CheckboxCard(
className="customcheckboxcardroot",
children=[dmc.Stack([dmc.Text("Custom CheckboxCard 3", size="xl"),
dmc.Text("description", c="dimmed")])],
value="3"),
],
mt=10,
),
value=["1"],
),
dmc.Box(id="output1", children="Output 1:"),
dmc.Space(h=30),
dmc.Text("Card without styles:"),
dmc.CheckboxCard(
id="cb",
withBorder=True,
children=dmc.Group(wrap="nowrap", align="flex-start", children=[
dmc.CheckboxIndicator(),
dmc.Stack([dmc.Text("CheckboxCard", size="xl"), dmc.Text("description", c="dimmed")])])
),
dmc.Box(id="output2", children="Output 2:"),
],
pt="10px", px="20%"
)
)
@callback(
Output("output1", "children"),
Input("cbg", "value")
)
def on_cbg(event):
if event:
return f"Output 1: {event}"
return "nothing"
@callback(
Output("output2", "children"),
Input("cb", "checked")
)
def on_cb(event):
if event:
return f"Output 2: {event}"
return "nothing"
if __name__ == "__main__":
app.run(debug=True).checkboxcardroot {
position: relative;
padding: var(--mantine-spacing-md);
transition: border-color 150ms ease;
&[data-checked] {
border-color: var(--mantine-primary-color-filled);
}
}
.checkboxcardroot:hover {
background-color: light-dark(
var(--mantine-color-gray-0),
var(--mantine-color-dark-6)
);
}
.customcheckboxcardroot {
position: relative;
padding: var(--mantine-spacing-md);
transition: border-color 150ms ease;
&[data-checked] {
border-color: var(--mantine-primary-color-filled);
}
}
.customcheckboxcardroot::after {
position: absolute;
inset-block-start: 2px;
inset-inline-end: 2px;
width: 0;
height: 0;
opacity: 0;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
border-block-end: 10px solid transparent;
border-inline-start: 10px solid transparent;
border-start-end-radius: 6px;
content: '';
}
.customcheckboxcardroot[data-checked="true"]::after {
opacity: 1;
border: 10px solid #1677ff;
border-block-end: 10px solid transparent;
border-inline-start: 10px solid transparent;
border-start-end-radius: 6px;
} |
import dash
from dash import Dash, Input, Output, callback
import dash_mantine_components as dmc
dash._dash_renderer._set_react_version('18.2.0') # noqa
app = Dash(external_stylesheets=dmc.styles.ALL)
app.layout = dmc.MantineProvider(
forceColorScheme="dark",
children=dmc.Box([
dmc.RadioGroup(
id="rg",
label="RadioCard Group",
children=dmc.Group([
dmc.RadioCard(
className="checkboxcardroot",
children=dmc.Group(wrap="nowrap", align="flex-start", children=[
dmc.RadioIndicator(),
dmc.Stack([dmc.Text("RadioCard 1", size="xl"), dmc.Badge("A badge")])]),
value="1"),
dmc.RadioCard(
className="customcheckboxcardroot",
children=[dmc.Stack([dmc.Text("Custom RadioCard 2", size="xl"),
dmc.Text("description", c="dimmed")])],
value="2"),
dmc.RadioCard(
className="checkboxcardroot",
children=dmc.Group(wrap="nowrap", align="flex-start", children=[
dmc.RadioIndicator(),
dmc.Text("RadioCard 3", size="xl")]),
value="3"),
],
mt=10,
),
value="1",
),
dmc.Box(id="output1", children="Output 1:"),
dmc.Space(h=30),
],
pt="10px", px="35%"
)
)
@callback(
Output("output1", "children"),
Input("rg", "value")
)
def on_rg(event):
if event:
return f"Output 1: {event}"
return "nothing"
if __name__ == "__main__":
app.run(debug=True)
|
|
This looks great and thanks for adding the RadioCard too 🏆 To DO:
Are you familiar with Dash testing? If so, we need to add a couple simple tests for the dash props in Let me know if you run into any issues and I can help with the tests. Before merging, ideally, I'd like to have dash 3.0 and dmc 1,0 released. If this causes a long delay, let's revisit. |
I didn't run the tests locally, maybe they need more adjustments but i think they should work. |
|
Hi @deadkex It looks like the deselectable prop with the radio card doesn't work. Do you think it's because of this line (using input instead of button?) https://github.com/snehilvj/dash-mantine-components/blob/master/src/ts/components/core/radio/RadioGroup.tsx#L43 Did you get an example working locally with the |
Yes just push them.
Seems like it has to do with that but i'm unsure how/what to change to make it work.
Seems like i missed that, nope does not work. |
|
Ok, just the deselectable radio test fails now. I'll leave that in for now in case we come up with a solution, otherwise, we can document this as a limitation. |
|
Hey @deadkex, at @AnnMarieW's request I had a look at making the radioGroupContext interface RadioGroupContextProps {
radioOnClick?: (val?: string) => void;
}radioGroup const handleRadioClick = (val?: string) => {
if (val === value) {
setProps({ value: null });
}
};radio const Radio = (props: Props) => {
const {
setProps,
loading_state,
persistence,
persisted_props,
persistence_type,
value,
...others
} = props;
const { radioOnClick } = React.useContext(RadioGroupContext) || {};
return (
<MantineRadio
data-dash-is-loading={getLoadingState(loading_state) || undefined}
onChange={(ev) => setProps({ checked: ev.currentTarget.checked })}
onClick={radioOnClick ? () => radioOnClick(value) : null}
value={value}
{...others}
/>
);
};radioCard const RadioCard = (props: Props) => {
const {
children,
setProps,
loading_state,
persistence,
persisted_props,
persistence_type,
value,
...others
} = props;
const { radioOnClick } = React.useContext(RadioGroupContext) || {};
return (
<MantineRadioCard
data-dash-is-loading={getLoadingState(loading_state) || undefined}
onClick={radioOnClick ? () => radioOnClick(value) : null}
value={value}
{...others}
>
{children}
</MantineRadioCard>
);
};And remove radioCardGroupContext.tsx and update the context import in radioCard. With this all the radio tests work for me! |
|
@RenaudLN Thank you for the help, i added your proposed changes |
|
PR for the docs: snehilvj/dmc-docs#160 |
alexcjohnson
left a comment
There was a problem hiding this comment.
💃 Nice work @deadkex! Just a couple of small comments on the tests, but this looks great.
|
@deadkex |


Played around with implementing CheckboxCards.
Some help would be appreciated.
See comments for examples.