Skip to content

Commit 9c7206f

Browse files
authored
Merge branch 'snehilvj:master' into add-type-simplegrid
2 parents 7398676 + 3124e27 commit 9c7206f

File tree

10 files changed

+202
-10
lines changed

10 files changed

+202
-10
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@
66
- Added `disabled` prop to `Radio` #425 by @namakshenas
77
- Added `type` prop to `SimpleGrid` #433 by @namakshenas
88

9+
- Added the `add_figure_templates()` function which creates Mantine-styled Plotly figure templates for
10+
both light and dark modes using the default Mantine theme. It registers the templates with plotly.io.templates as
11+
"mantine_light" and "mantine_dark", and optionally sets one of the themes as a default. #431 by @AnnMarie
12+
13+
- Added various props: `acceptValueOnBlur` to `TagsInput`, `gradient` to `LineChart`, `hideWithOnePage` to `Pagination`, `name` to `Avatar`, and `disabled` to `NumberInput`. #440 by @AnnMarieW
14+
15+
- Added `SemiCircleProgress` component #434 by @AnnMarieW
16+
17+
918
### Fixed
1019
- Fixed closing of Popovers when clicking outside. #423 by @magicmq
1120

dash_mantine_components/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from ._imports_ import *
1313
from ._imports_ import __all__
1414
from .theme import DEFAULT_THEME
15+
from .figure_templates import add_figure_templates
1516

1617
if not hasattr(_dash, "__plotly_dash") and not hasattr(_dash, "development"):
1718
print(
@@ -64,4 +65,4 @@
6465
setattr(locals()[_component], "_css_dist", _css_dist)
6566

6667

67-
__all__ += [DEFAULT_THEME, styles]
68+
__all__ += [DEFAULT_THEME, styles, add_figure_templates]
+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
from .theme import DEFAULT_THEME
2+
import plotly.graph_objects as go
3+
import plotly.io as pio
4+
import copy
5+
6+
7+
def add_figure_templates(default=None):
8+
9+
"""
10+
Create and register Plotly figure templates styled to match the Mantine default theme.
11+
12+
This function generates two custom Plotly templates:
13+
- "mantine_light" for light mode
14+
- "mantine_dark" for dark mode
15+
16+
Templates are registered with `plotly.io.templates`, allowing you to apply them to Plotly figures
17+
using the template names "mantine_light" or "mantine_dark". These templates include Mantine-inspired
18+
color palettes, background colors, and other layout customizations.
19+
20+
Parameters:
21+
- default (str): The default template to apply globally. Must be either "mantine_light" or "mantine_dark".
22+
If not set, the default Plotly template remains unchanged.
23+
24+
Returns:
25+
- None: The templates are registered and optionally set as the default, but no value is returned.
26+
27+
"""
28+
29+
colors = DEFAULT_THEME["colors"]
30+
font_family = DEFAULT_THEME["fontFamily"]
31+
# pallet generated from https://www.learnui.design/tools/data-color-picker.html#palette
32+
custom_colorscale = [
33+
"#1864ab", # blue[9]
34+
"#7065b9",
35+
"#af61b7",
36+
"#e35ea5",
37+
"#ff6587",
38+
"#ff7c63",
39+
"#ff9e3d",
40+
"#fcc419", # yellow[5]
41+
]
42+
43+
# Default theme configurations
44+
default_themes = {
45+
"light": {
46+
"colorway": [
47+
colors[color][6]
48+
for color in ["blue", "red", "green", "violet", "orange", "cyan", "pink", "yellow"]
49+
],
50+
"paper_bgcolor": "#ffffff", # mantine background color
51+
"plot_bgcolor": "#ffffff",
52+
"gridcolor": "#dee2e6",
53+
},
54+
"dark": {
55+
"colorway": [
56+
colors[color][8]
57+
for color in ["blue", "red", "green", "violet", "orange", "cyan", "pink", "yellow"]
58+
],
59+
"paper_bgcolor": colors["dark"][7], # mantine background color
60+
"plot_bgcolor": colors["dark"][7],
61+
"gridcolor": "#343a40",
62+
}
63+
}
64+
65+
def make_template(name):
66+
#Start with either a light or dark Plotly template
67+
base = "plotly_white" if name == "light" else "plotly_dark"
68+
template = copy.deepcopy(pio.templates[base])
69+
70+
layout = template.layout
71+
theme_config = default_themes[name]
72+
73+
# Apply theme settings
74+
layout.colorway = theme_config["colorway"]
75+
layout.colorscale.sequential = custom_colorscale
76+
layout.piecolorway = theme_config["colorway"]
77+
layout.paper_bgcolor = theme_config["paper_bgcolor"]
78+
layout.plot_bgcolor = theme_config["plot_bgcolor"]
79+
layout.font.family = font_family
80+
81+
# Grid settings
82+
for axis in (layout.xaxis, layout.yaxis):
83+
axis.gridcolor = theme_config["gridcolor"]
84+
axis.gridwidth = 0.5
85+
axis.zerolinecolor = theme_config["gridcolor"]
86+
87+
# Geo settings
88+
layout.geo.bgcolor = theme_config["plot_bgcolor"]
89+
layout.geo.lakecolor = theme_config["plot_bgcolor"]
90+
layout.geo.landcolor = theme_config["plot_bgcolor"]
91+
92+
# Hover label settings
93+
layout.hoverlabel.font.family = font_family
94+
95+
# Scatter plot settings
96+
template.data.scatter = (go.Scatter(marker_line_color=theme_config["plot_bgcolor"]),)
97+
template.data.scattergl = (go.Scattergl(marker_line_color=theme_config["plot_bgcolor"]),)
98+
99+
return template
100+
101+
102+
# #register templates
103+
pio.templates["mantine_light"] = make_template("light")
104+
pio.templates["mantine_dark"] = make_template("dark")
105+
106+
# set the default
107+
if default in ["mantine_light", "mantine_dark"]:
108+
pio.templates.default = default
109+
elif default:
110+
raise ValueError(f"unrecognized {default=}, allowed values are 'mantine_light' and 'mantine_dark'")
111+
112+
return None

src/ts/components/charts/LineChart.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { LineChart as MantineLineChart } from "@mantine/charts";
22
import {
33
LineChartCurveType,
44
LineChartSeries,
5+
LineChartGradientStop,
6+
LineChartType,
57
} from "@mantine/charts/lib/LineChart/LineChart";
68
import { BoxProps } from "props/box";
79
import { GridChartBaseProps } from "props/charts";
@@ -52,10 +54,13 @@ interface Props
5254
highlightHover?: boolean
5355
/** Determines whether each point should have associated label, False by default */
5456
withPointLabels?: boolean;
55-
57+
/** Data used to generate gradient stops, [{ offset: 0, color: 'red' }, { offset: 100, color: 'blue' }] by default */
58+
gradientStops?: LineChartGradientStop[];
59+
/** Controls styles of the line 'default' | 'gradient'. 'default' by default */
60+
type?: LineChartType;
5661
}
5762

58-
/** LineChart */
63+
/** Mantine-themed line chart built on top of the Recharts library, */
5964
const LineChart = (props: Props) => {
6065
const { setProps, loading_state, clickData, hoverData, clickSeriesName, hoverSeriesName, series, highlightHover, lineChartProps, activeDotProps, lineProps, ...others } = props;
6166

src/ts/components/core/Pagination.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ interface Props
3838
radius?: MantineRadius;
3939
/** Determines whether active item text color should depend on `background-color` of the indicator. If luminosity of the `color` prop is less than `theme.luminosityThreshold`, then `theme.white` will be used for text color, otherwise `theme.black`. Overrides `theme.autoContrast`. */
4040
autoContrast?: boolean;
41+
/** Determines whether the pagination should be hidden when only one page is available (total=1), False by default */
42+
hideWithOnePage?: boolean;
4143
}
4244

43-
/** Pagination */
45+
/** Use the Pagination component to display active page and navigate between multiple pages */
4446
const Pagination = (props: Props) => {
4547
const {
4648
setProps,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import {
2+
MantineColor,
3+
SemiCircleProgress as MantineSemiCircleProgess,
4+
} from "@mantine/core";
5+
import { BoxProps } from "props/box";
6+
import { DashBaseProps } from "props/dash";
7+
import { StylesApiProps } from "props/styles";
8+
import React from "react";
9+
10+
interface Props extends BoxProps, StylesApiProps, DashBaseProps {
11+
/** Progress value from `0` to `100` */
12+
value: number;
13+
14+
/** Diameter of the svg in px, `200` by default */
15+
size?: number;
16+
17+
/** Circle thickness in px, `12` by default */
18+
thickness?: number;
19+
20+
/** Orientation of the circle, `'up'` by default */
21+
orientation?: 'up' | 'down';
22+
23+
/** Direction from which the circle is filled, `'left-to-right'` by default */
24+
fillDirection?: 'right-to-left' | 'left-to-right';
25+
26+
/** Key of `theme.colors` or any valid CSS color value, `theme.primaryColor` by default */
27+
filledSegmentColor?: MantineColor;
28+
29+
/** Key of `theme.colors` or any valid CSS color value, by default the value is determined based on the color scheme value */
30+
emptySegmentColor?: MantineColor;
31+
32+
/** Transition duration of filled section styles changes in ms, `0` by default */
33+
transitionDuration?: number;
34+
35+
/** Label rendered inside the circle */
36+
label?: React.ReactNode;
37+
38+
/** Label position relative to the circle center, `'bottom'` by default */
39+
labelPosition?: 'center' | 'bottom';
40+
}
41+
42+
/** Use to represent progress with semi circle diagram */
43+
const SemiCircleProgress = (props: Props) => {
44+
const { setProps, loading_state, ...others } = props;
45+
46+
return (
47+
<MantineSemiCircleProgess
48+
{...others}
49+
/>
50+
);
51+
};
52+
53+
SemiCircleProgress.defaultProps = {};
54+
55+
export default SemiCircleProgress;

src/ts/components/core/avatar/Avatar.tsx

+5-3
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ interface Props extends BoxProps, StylesApiProps, DashBaseProps {
1515
size?: MantineSize | (string & {}) | number;
1616
/** Key of `theme.radius` or any valid CSS value to set border-radius, `'100%'` by default */
1717
radius?: MantineRadius;
18-
/** Key of `theme.colors` or any valid CSS color, default value is `theme.primaryColor` */
19-
color?: MantineColor;
18+
/** Key of `theme.colors` or any valid CSS color, default value is `theme.primaryColor`. Set to "initials" to auto generate color based on `name` */
19+
color?: MantineColor | "initials";
2020
/** Gradient configuration used when `variant="gradient"`, default value is `theme.defaultGradient` */
2121
gradient?: MantineGradient;
2222
/** Image url, if the image cannot be loaded or `src={null}`, then placeholder is displayed instead */
@@ -29,9 +29,11 @@ interface Props extends BoxProps, StylesApiProps, DashBaseProps {
2929
children?: React.ReactNode;
3030
/** Determines whether text color with filled variant should depend on `background-color`. If luminosity of the `color` prop is less than `theme.luminosityThreshold`, then `theme.white` will be used for text color, otherwise `theme.black`. Overrides `theme.autoContrast`. */
3131
autoContrast?: boolean;
32+
/** Name of the user. When src is not set, used to display initials and to generate color when color="initials" is set. */
33+
name?: string;
3234
}
3335

34-
/** Avatar */
36+
/** Use the Avatar component to display user profile image, initials or fallback icon */
3537
const Avatar = (props: Props) => {
3638
const { children, setProps, loading_state, ...others } = props;
3739

src/ts/components/core/combobox/TagsInput.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,11 @@ interface Props
4242
hiddenInputValuesDivider?: string;
4343
/** Props passed down to the underlying `ScrollArea` component in the dropdown */
4444
scrollAreaProps?: ScrollAreaProps;
45+
/** Determines whether the value typed in by the user but not submitted should be accepted when the input is blurred, true by default */
46+
acceptValueOnBlur?: boolean;
4547
}
4648

47-
/** TagsInput */
49+
/** TagsInput captures a list of values from user with free input and suggestions */
4850
const TagsInput = (props: Props) => {
4951
const { setProps, loading_state, data, searchValue, value, ...others } =
5052
props;
@@ -80,7 +82,6 @@ const TagsInput = (props: Props) => {
8082
data-dash-is-loading={
8183
(loading_state && loading_state.is_loading) || undefined
8284
}
83-
wrapperProps={{ autoComplete: "off" }}
8485
data={options}
8586
onChange={setSelected}
8687
value={selected}

src/ts/components/core/input/NumberInput.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,12 @@ interface Props
5959
stepHoldDelay?: number;
6060
/** (string; default "off") Enables the browser to attempt autocompletion based on user history. For more information, see: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete */
6161
autoComplete?: string;
62+
/** Sets disabled attribute on the input element */
63+
disabled?: boolean;
64+
6265
}
6366

64-
/** NumberInput */
67+
/** The NumberInput component allows users to input numeric values */
6568
const NumberInput = (props: Props) => {
6669
const {
6770
setProps,

src/ts/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ import ProgressSection from "./components/core/progress/ProgressSection";
112112
import Radio from "./components/core/radio/Radio";
113113
import RadioGroup from "./components/core/radio/RadioGroup";
114114
import RangeSlider from "./components/core/slider/RangeSlider";
115+
import SemiCircleProgress from "./components/core/SemiCircleProgress";
115116
import Slider from "./components/core/slider/Slider";
116117
import Stepper from "./components/core/stepper/Stepper";
117118
import StepperCompleted from "./components/core/stepper/StepperCompleted";
@@ -264,6 +265,7 @@ export {
264265
RangeSlider,
265266
Rating,
266267
RingProgress,
268+
SemiCircleProgress,
267269
ScatterChart,
268270
ScrollArea,
269271
SegmentedControl,

0 commit comments

Comments
 (0)