gov-uk-dashboards 21.2.2__py3-none-any.whl → 26.26.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. gov_uk_dashboards/__init__.py +1 -1
  2. gov_uk_dashboards/assets/__init__.py +1 -0
  3. gov_uk_dashboards/assets/dashboard.css +177 -0
  4. gov_uk_dashboards/assets/download-map.js +39 -0
  5. gov_uk_dashboards/assets/get_assets_folder.py +1 -0
  6. gov_uk_dashboards/assets/images/CHASE_icon.svg +17 -0
  7. gov_uk_dashboards/assets/images/explore_data_logo.svg +87 -0
  8. gov_uk_dashboards/assets/index.html +3 -0
  9. gov_uk_dashboards/assets/register_maps +15 -0
  10. gov_uk_dashboards/assets/scripts.js +4 -0
  11. gov_uk_dashboards/colours.py +23 -0
  12. gov_uk_dashboards/components/__init__.py +1 -0
  13. gov_uk_dashboards/components/dash/__init__.py +1 -3
  14. gov_uk_dashboards/components/dash/apply_and_reset_filters_buttons.py +1 -0
  15. gov_uk_dashboards/components/dash/banners.py +21 -0
  16. gov_uk_dashboards/components/dash/card.py +1 -0
  17. gov_uk_dashboards/components/dash/card_full_width.py +1 -0
  18. gov_uk_dashboards/components/dash/collapsible_panel.py +1 -0
  19. gov_uk_dashboards/components/dash/comparison_la_filter_button.py +1 -0
  20. gov_uk_dashboards/components/dash/context_banner.py +2 -1
  21. gov_uk_dashboards/components/dash/context_card.py +978 -0
  22. gov_uk_dashboards/components/dash/data_quality_banner.py +91 -0
  23. gov_uk_dashboards/components/dash/details.py +1 -0
  24. gov_uk_dashboards/components/dash/download_button.py +22 -36
  25. gov_uk_dashboards/components/dash/filter_panel.py +1 -0
  26. gov_uk_dashboards/components/dash/footer.py +81 -27
  27. gov_uk_dashboards/components/dash/graph.py +1 -0
  28. gov_uk_dashboards/components/dash/green_button.py +25 -0
  29. gov_uk_dashboards/components/dash/header.py +62 -9
  30. gov_uk_dashboards/components/dash/heading.py +8 -5
  31. gov_uk_dashboards/components/dash/home_page_link_button.py +9 -8
  32. gov_uk_dashboards/components/dash/html_list.py +1 -0
  33. gov_uk_dashboards/components/dash/key_value_pair.py +1 -0
  34. gov_uk_dashboards/components/dash/main_content.py +25 -2
  35. gov_uk_dashboards/components/dash/notification_banner.py +9 -5
  36. gov_uk_dashboards/components/dash/paragraph.py +1 -0
  37. gov_uk_dashboards/components/dash/phase_banner.py +7 -4
  38. gov_uk_dashboards/components/dash/row_component.py +1 -0
  39. gov_uk_dashboards/components/dash/table.py +62 -124
  40. gov_uk_dashboards/components/dash/tooltip.py +2 -1
  41. gov_uk_dashboards/components/dash/tooltip_title.py +2 -1
  42. gov_uk_dashboards/components/dash/visualisation_commentary.py +1 -0
  43. gov_uk_dashboards/components/dash/visualisation_title.py +1 -0
  44. gov_uk_dashboards/components/dash/warning_text.py +1 -0
  45. gov_uk_dashboards/components/helpers/display_chart_or_table_with_header.py +61 -12
  46. gov_uk_dashboards/components/helpers/get_chart_for_download.py +18 -15
  47. gov_uk_dashboards/components/helpers/plotting_helper_functions.py +0 -1
  48. gov_uk_dashboards/components/leaflet/leaflet_choropleth_map.py +108 -31
  49. gov_uk_dashboards/components/plotly/captioned_figure.py +6 -3
  50. gov_uk_dashboards/components/plotly/enums.py +2 -0
  51. gov_uk_dashboards/components/plotly/stacked_barchart.py +166 -73
  52. gov_uk_dashboards/components/plotly/time_series_chart.py +159 -20
  53. gov_uk_dashboards/constants.py +35 -1
  54. gov_uk_dashboards/figures/__init__.py +4 -2
  55. gov_uk_dashboards/figures/enums/__init__.py +1 -0
  56. gov_uk_dashboards/figures/enums/dash_patterns.py +1 -0
  57. gov_uk_dashboards/figures/line_chart.py +71 -71
  58. gov_uk_dashboards/figures/styles/__init__.py +1 -0
  59. gov_uk_dashboards/figures/styles/line_style.py +1 -0
  60. gov_uk_dashboards/formatting/human_readable.py +1 -0
  61. gov_uk_dashboards/formatting/number_formatting.py +14 -0
  62. gov_uk_dashboards/formatting/round_and_add_prefix_and_suffix.py +1 -0
  63. gov_uk_dashboards/formatting/text_functions.py +11 -0
  64. gov_uk_dashboards/lib/dap/dap_deployment.py +1 -0
  65. gov_uk_dashboards/lib/dap/get_dataframe_from_cds.py +96 -95
  66. gov_uk_dashboards/lib/datetime_functions/datetime_functions.py +118 -0
  67. gov_uk_dashboards/lib/download_functions/download_csv_with_headers.py +106 -83
  68. gov_uk_dashboards/lib/http_headers.py +10 -2
  69. gov_uk_dashboards/lib/logging.py +1 -0
  70. gov_uk_dashboards/lib/testing_functions/__init__.py +0 -0
  71. gov_uk_dashboards/lib/testing_functions/barchart_data_test_assertions.py +48 -0
  72. gov_uk_dashboards/lib/testing_functions/data_test_assertions.py +124 -0
  73. gov_uk_dashboards/lib/testing_functions/data_test_helper_functions.py +257 -0
  74. gov_uk_dashboards/lib/testing_functions/timeseries_data_test_assertions.py +29 -0
  75. gov_uk_dashboards/lib/warning_text_sensitive.py +44 -0
  76. gov_uk_dashboards/log_kpi.py +37 -0
  77. gov_uk_dashboards/symbols.py +1 -0
  78. gov_uk_dashboards/template.html +37 -0
  79. gov_uk_dashboards/template.py +14 -3
  80. {gov_uk_dashboards-21.2.2.dist-info → gov_uk_dashboards-26.26.0.dist-info}/METADATA +6 -7
  81. gov_uk_dashboards-26.26.0.dist-info/RECORD +128 -0
  82. {gov_uk_dashboards-21.2.2.dist-info → gov_uk_dashboards-26.26.0.dist-info}/WHEEL +1 -1
  83. gov_uk_dashboards/axes.py +0 -21
  84. gov_uk_dashboards/figures/chart_data.py +0 -24
  85. gov_uk_dashboards-21.2.2.dist-info/RECORD +0 -113
  86. {gov_uk_dashboards-21.2.2.dist-info → gov_uk_dashboards-26.26.0.dist-info}/licenses/LICENSE +0 -0
  87. {gov_uk_dashboards-21.2.2.dist-info → gov_uk_dashboards-26.26.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,91 @@
1
+ """data_quality_banner"""
2
+
3
+ from enum import Enum
4
+ from dataclasses import dataclass
5
+ from dash import html
6
+ from gov_uk_dashboards.components.dash.notification_banner import notification_banner
7
+ from gov_uk_dashboards.formatting.text_functions import create_id_from_string
8
+ from gov_uk_dashboards.constants import (
9
+ NOTIFICATION_STYLE_GREEN,
10
+ NOTIFICATION_STYLE_ORANGE,
11
+ NOTIFICATION_STYLE_RED,
12
+ NOTIFICATION_STYLE_YELLOW,
13
+ )
14
+
15
+
16
+ @dataclass
17
+ class DataQualityConfig:
18
+ """
19
+ Configuration class for defining the display and linking details of a data quality metric.
20
+
21
+ Attributes:
22
+ title (str): The title of the data quality metric.
23
+ text (str): Descriptive text or explanation of the metric.
24
+ style (str): The visual style or format for displaying the metric.
25
+ title_color (str, optional): Optional color to use for the title. Defaults to None.
26
+ glossary_url (str, optional): Optional URL linking to a glossary entry for this metric.
27
+ If not provided, a URL is automatically generated based on the title.
28
+
29
+ Methods:
30
+ __post_init__(): Automatically generates a glossary URL if none is provided.
31
+ """
32
+
33
+ title: str
34
+ text: str
35
+ style: str
36
+ title_color: str = None
37
+ glossary_url: str = None
38
+
39
+ def __post_init__(self):
40
+ if not self.glossary_url:
41
+ slug = create_id_from_string(self.title)
42
+ self.glossary_url = f"/glossary#data-quality-{slug}"
43
+
44
+
45
+ class DataQualityLabels(Enum):
46
+ """Enumeration of standard labels used to categorize or describe data quality."""
47
+
48
+ OFFICIAL = DataQualityConfig(
49
+ title="OFFICIAL public data",
50
+ text="Use with confidence.",
51
+ style=NOTIFICATION_STYLE_GREEN,
52
+ )
53
+ MI = DataQualityConfig(
54
+ title="Management information",
55
+ text="Use for early insights, but with caution.",
56
+ style=NOTIFICATION_STYLE_YELLOW,
57
+ title_color="black",
58
+ )
59
+ EXPERIMENTAL_MI = DataQualityConfig(
60
+ title="Experimental management information",
61
+ text="Indicative only, requires expert guidance on use.",
62
+ style=NOTIFICATION_STYLE_ORANGE,
63
+ title_color="black",
64
+ )
65
+ OPERATIONAL = DataQualityConfig(
66
+ title="Operational data",
67
+ text="Never use in isolation, always verify independently.",
68
+ style=NOTIFICATION_STYLE_RED,
69
+ )
70
+
71
+
72
+ def data_quality_notification_banner(label: DataQualityLabels):
73
+ """Return data quality notification banner based on Gov UK Design component notification
74
+ banner component."""
75
+ config = label.value
76
+ text = [
77
+ f"{config.text} Read more in our ",
78
+ html.A(
79
+ "glossary",
80
+ href=config.glossary_url,
81
+ target="_blank",
82
+ rel="noopener noreferrer",
83
+ ),
84
+ ".",
85
+ ]
86
+ return notification_banner(
87
+ title=config.title,
88
+ text=text,
89
+ style=config.style,
90
+ title_color=config.title_color,
91
+ )
@@ -1,4 +1,5 @@
1
1
  """details"""
2
+
2
3
  from dash import html
3
4
 
4
5
 
@@ -1,60 +1,46 @@
1
1
  """download_button"""
2
- import warnings
2
+
3
+ from typing import Union
3
4
  from dash import html
4
5
 
5
6
  from gov_uk_dashboards.constants import DOWNLOAD_BUTTON_CLASSES
6
7
 
7
8
 
8
- def download_button(button_text: str, button_id: str = "download-button"):
9
- """
10
- Return a download button which is aligned to the right
11
-
12
- Args:
13
- button_text (str): The text to display on the button.
14
- button_id: (str, Optional) = id for dropdown, default to "download-button"
15
- """
16
- warnings.warn(
17
- "Note there is an alternative function to download_button() called "
18
- "create_download_button_with_icon() which includes a download icon and improved styling.",
19
- Warning,
20
- stacklevel=2,
21
- )
22
-
23
- return html.Div(
24
- [
25
- html.Button(
26
- button_text,
27
- id=button_id,
28
- n_clicks=0,
29
- className="govuk-button govuk-button--secondary",
30
- ),
31
- ],
32
- className="govuk-button-group",
33
- style={"float": "right"},
34
- )
35
-
36
-
37
9
  def create_download_button_with_icon(
38
- button_text: str, button_id_name: str
10
+ button_text: str,
11
+ button_id_name: str,
12
+ instance: Union[str, int] = None,
13
+ download_type: str = None,
39
14
  ) -> html.Button:
40
15
  """Create a download button with icon, aligned to the left.
41
16
 
42
17
  Parameters:
18
+ - button_text (str): Text to display on button.
43
19
  - button_id_name (str): A unique identifier for the button.
20
+ - instance (Union[int,str]): Optional additional id parameter for when button_text is
21
+ "Download map".
44
22
 
45
23
  Returns:
46
24
  - html.Button: Download button.
47
25
  """
48
- download_type = button_text.lower().replace(" ", "-")
26
+ if download_type:
27
+ download_type = f"download-{download_type}"
28
+ else:
29
+ download_type = button_text.lower().replace(" ", "-")
30
+ if button_text == "Download map":
31
+ id_dict = {
32
+ "download-type": download_type,
33
+ "name": button_id_name,
34
+ "instance": instance,
35
+ }
36
+ else:
37
+ id_dict = {"download-type": download_type, "name": button_id_name}
49
38
  return html.Button(
50
39
  [
51
40
  html.Div("", className="download-icon"),
52
41
  button_text,
53
42
  ],
54
- id={
55
- "download-type": download_type,
56
- "name": button_id_name,
57
- },
43
+ id=id_dict,
58
44
  n_clicks=0,
59
45
  className=DOWNLOAD_BUTTON_CLASSES,
60
46
  type="submit",
@@ -1,4 +1,5 @@
1
1
  """filter_panel"""
2
+
2
3
  from typing import Optional
3
4
  from dash import html
4
5
 
@@ -1,9 +1,10 @@
1
1
  """footer"""
2
+
2
3
  from typing import Optional
3
4
  from dash import html
4
5
 
5
6
 
6
- def footer(footer_links: Optional[list[any]]):
7
+ def footer(footer_links: Optional[list[any]], include_logos: bool = False):
7
8
  """
8
9
  HTML component for a Gov.UK standard footer.
9
10
 
@@ -22,34 +23,87 @@ def footer(footer_links: Optional[list[any]]):
22
23
  [
23
24
  html.Div(
24
25
  [
25
- html.H2("Support Links", className="govuk-visually-hidden")
26
- if footer_links
27
- else None,
28
- html.Ul(
29
- children=[
30
- html.Li(
31
- item, className="govuk-footer__inline-list-item"
32
- )
33
- for item in footer_links
34
- ],
35
- className="govuk-footer__inline-list govuk-!-display-none-print",
36
- )
37
- if footer_links
38
- else None,
39
- html.Span(
26
+ (
27
+ html.H2(
28
+ "Support Links", className="govuk-visually-hidden"
29
+ )
30
+ if footer_links
31
+ else None
32
+ ),
33
+ html.Div(
40
34
  [
41
- "All content is available under the ",
42
- html.A(
43
- "Open Government Licence v3.0",
44
- rel="license",
45
- href="https://www.nationalarchives.gov.uk/doc/"
46
- "open-government-licence/version/3/",
47
- className="govuk-footer__link",
48
- target="_blank",
35
+ (
36
+ html.Ul(
37
+ children=[
38
+ html.Li(
39
+ item,
40
+ className="govuk-footer__inline-list-item",
41
+ )
42
+ for item in footer_links
43
+ ],
44
+ className=(
45
+ "govuk-footer__inline-list "
46
+ "govuk-!-display-none-print"
47
+ ),
48
+ )
49
+ if footer_links
50
+ else None
51
+ ),
52
+ html.Span(
53
+ [
54
+ "All content is available under the ",
55
+ html.A(
56
+ "Open Government Licence v3.0",
57
+ rel="license",
58
+ href="https://www.nationalarchives.gov.uk/doc/"
59
+ "open-government-licence/version/3/",
60
+ className="govuk-footer__link",
61
+ target="_blank",
62
+ ),
63
+ ", except where otherwise stated",
64
+ ],
65
+ className="govuk-footer__licence-description",
66
+ ),
67
+ (
68
+ (
69
+ html.Div(
70
+ [
71
+ html.Img(
72
+ src="assets\\images\\CHASE_icon.svg",
73
+ className="header-image",
74
+ style={"maxWidth": "100px"},
75
+ ),
76
+ html.Div(
77
+ [
78
+ html.B(
79
+ "CHASE",
80
+ style={
81
+ "font-size": "36px"
82
+ },
83
+ ),
84
+ ],
85
+ style={
86
+ "display": "flex",
87
+ "flex-direction": "column",
88
+ "align-items": "left",
89
+ "color": "#707070",
90
+ "maxWidth": "200px",
91
+ "padding-bottom": "10px",
92
+ },
93
+ ),
94
+ ],
95
+ style={
96
+ "display": "flex",
97
+ "flex-direction": "row",
98
+ "align-items": "center",
99
+ "padding-top": "30px",
100
+ },
101
+ )
102
+ )
103
+ if include_logos
104
+ else None
49
105
  ),
50
- ", except where otherwise stated",
51
- ],
52
- className="govuk-footer__licence-description",
106
+ ]
53
107
  ),
54
108
  ],
55
109
  className="govuk-footer__meta-item govuk-footer__meta-item--grow",
@@ -1,4 +1,5 @@
1
1
  """Create a graph"""
2
+
2
3
  import warnings
3
4
  from dash import dcc
4
5
 
@@ -0,0 +1,25 @@
1
+ """green_button"""
2
+
3
+ from dash import html
4
+
5
+
6
+ def green_button(button_text: str, button_id: str):
7
+ """
8
+ Return a green button which is aligned to the right
9
+
10
+ Args:
11
+ button_text (str): The text to display on the button.
12
+ button_id: (str) = id for button
13
+ """
14
+
15
+ return html.Div(
16
+ [
17
+ html.Button(
18
+ button_text,
19
+ id=button_id,
20
+ n_clicks=0,
21
+ className="govuk-button",
22
+ ),
23
+ ],
24
+ className="govuk-button-group",
25
+ )
@@ -3,7 +3,12 @@
3
3
  from dash import html
4
4
 
5
5
 
6
- def header(title: str, strong_class: str = "", background_colour: str = None):
6
+ def header(
7
+ title: str,
8
+ strong_class: str = "",
9
+ background_colour: str = None,
10
+ show_mobile_menu_button: bool = True,
11
+ ):
7
12
  """
8
13
  The header component, shared across all dashboard views. Includes optional strong_class
9
14
  parameter to provide extra styling in the form of a class.
@@ -28,7 +33,7 @@ def header(title: str, strong_class: str = "", background_colour: str = None):
28
33
  ),
29
34
  html.Div(
30
35
  ["Ministry of Housing, Communities & Local Government"],
31
- style={"font-size": "20px", "font-weight": "200px"},
36
+ style={"fontSize": "20px", "fontWeight": "200px"},
32
37
  ),
33
38
  html.A(
34
39
  title,
@@ -47,25 +52,73 @@ def header(title: str, strong_class: str = "", background_colour: str = None):
47
52
  "OFFICIAL",
48
53
  className="govuk-tag protective-marking",
49
54
  id="protective-marking",
50
- style={"background-color": "#000000"},
55
+ style={"backgroundColor": "#000000"},
51
56
  )
52
57
  ],
53
58
  className=f"{strong_class}",
54
59
  ),
55
- html.Button(
56
- "Menu ▼",
57
- id="mobile-menu-btn",
58
- className="mobile-menu-button govuk-button",
60
+ (
61
+ html.Button(
62
+ "Menu ▼",
63
+ id="mobile-menu-btn",
64
+ className="mobile-menu-button govuk-button",
65
+ )
66
+ if show_mobile_menu_button
67
+ else None
59
68
  ),
60
69
  ],
61
70
  className="govuk-header__content",
62
71
  ),
63
72
  className="govuk-header__container govuk-width-container",
64
- style={"border-bottom": "10px solid #000000"},
73
+ style={"borderBottom": "10px solid #000000"},
65
74
  ),
66
75
  className="govuk-header",
67
76
  role="banner",
68
77
  style=header_style
69
- | {"border-color": "#000000", "background-color": "rgb(0,98,94)"},
78
+ | {"borderColor": "#000000", "backgroundColor": "rgb(0,98,94)"},
70
79
  **{"data-module": "govuk-header"},
71
80
  )
81
+
82
+
83
+ def logo_header():
84
+ """
85
+ Create and return the application header containing the Explore Data logo.
86
+
87
+ This component renders a GOV.UK–styled header with an SVG logo.
88
+ The logo is loaded from the Dash assets directory and constrained
89
+ to a maximum height for consistent layout.
90
+
91
+ Returns
92
+ -------
93
+ dash.html.Header
94
+ A Dash Header component containing the styled logo container.
95
+ """
96
+ return html.Header(
97
+ html.Div(
98
+ html.Div(
99
+ [
100
+ html.Div(
101
+ [
102
+ html.Img(
103
+ src="/assets/images/explore_data_logo.svg",
104
+ className="header-image",
105
+ style={"maxHeight": "100px"},
106
+ ),
107
+ ],
108
+ style={
109
+ "display": "flex",
110
+ "flexDirection": "column",
111
+ "color": "#00625e",
112
+ "alignItems": "center",
113
+ "paddingBottom": "2px",
114
+ },
115
+ ),
116
+ ],
117
+ className="govuk-header__content",
118
+ ),
119
+ style={"borderBottom": "0px solid #000000", "borderColor": "#f3f2f1"},
120
+ className="govuk-header__container govuk-width-container",
121
+ ),
122
+ className="govuk-header",
123
+ style={"backgroundColor": "#f3f2f1", "borderColor": "#f3f2f1"},
124
+ )
@@ -1,7 +1,9 @@
1
1
  """heading components"""
2
+
2
3
  from enum import Enum
3
4
 
4
5
  from dash import html
6
+ from gov_uk_dashboards.formatting.text_functions import create_id_from_string
5
7
 
6
8
 
7
9
  class HeadingSizes(str, Enum):
@@ -15,16 +17,17 @@ class HeadingSizes(str, Enum):
15
17
 
16
18
  def heading1(text: str, size: HeadingSizes = HeadingSizes.LARGE) -> html.H1:
17
19
  """Return a H1 dash component"""
18
- return html.H1(text, className=size)
20
+ heading_id = f"heading1-{create_id_from_string(text)}"
21
+ return html.H1(text, className=size, id=heading_id)
19
22
 
20
23
 
21
24
  def heading2(text: str, size: HeadingSizes = HeadingSizes.MEDIUM) -> html.H2:
22
25
  """Return a H2 dash component"""
23
-
24
- return html.H2(text, className=size)
26
+ heading_id = f"heading2-{create_id_from_string(text)}"
27
+ return html.H2(text, className=size, id=heading_id)
25
28
 
26
29
 
27
30
  def heading3(text: str, size: HeadingSizes = HeadingSizes.SMALL) -> html.H3:
28
31
  """Return a H3 dash component"""
29
-
30
- return html.H3(text, className=size)
32
+ heading_id = f"heading3-{create_id_from_string(text)}"
33
+ return html.H3(text, className=size, id=heading_id)
@@ -1,4 +1,5 @@
1
1
  """home_page_link_button"""
2
+
2
3
  from typing import Optional
3
4
  from dash import html
4
5
 
@@ -43,9 +44,9 @@ def home_page_link_button(
43
44
  [
44
45
  html.Div(
45
46
  [title],
46
- className="govuk-heading-l"
47
- if info is not None
48
- else None,
47
+ className=(
48
+ "govuk-heading-l" if info is not None else None
49
+ ),
49
50
  ),
50
51
  (
51
52
  html.Div(
@@ -56,17 +57,17 @@ def home_page_link_button(
56
57
  ),
57
58
  ],
58
59
  style={
59
- "text-align": "left",
60
- "text-decoration": "none",
61
- "padding-left": "5%",
60
+ "textAlign": "left",
61
+ "textDecoration": "none",
62
+ "paddingLeft": "5%",
62
63
  },
63
64
  ),
64
65
  html.Img(src=image_path, style={"width": "100%"}),
65
66
  ],
66
67
  style={
67
68
  "display": "grid",
68
- "grid-template-columns": "5fr 1fr",
69
- "align-items": "center",
69
+ "gridTemplateColumns": "5fr 1fr",
70
+ "alignItems": "center",
70
71
  },
71
72
  )
72
73
  ],
@@ -1,4 +1,5 @@
1
1
  """html list component"""
2
+
2
3
  from dash import html
3
4
 
4
5
 
@@ -1,4 +1,5 @@
1
1
  """key_value_pair"""
2
+
2
3
  import numpy as np
3
4
  from dash import html
4
5
 
@@ -1,8 +1,11 @@
1
1
  """main_content"""
2
+
3
+ import warnings
4
+ import re
2
5
  from dash import html
3
6
 
4
7
 
5
- def main_content(children):
8
+ def main_content(children, id_fragment=None, include_feedback_banner_div: bool = False):
6
9
  """
7
10
  Wrapper for the main content of the dashboard, containing visualisations.
8
11
 
@@ -13,4 +16,24 @@ def main_content(children):
13
16
 
14
17
  See https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML for more guidance.
15
18
  """
16
- return html.Main(children, className="main", id="main-content", role="main")
19
+ if id_fragment:
20
+ parts = re.split(r"\W+", id_fragment.lower())
21
+ slug = "main-content-" + "-".join(filter(None, parts))
22
+ else:
23
+ slug = ""
24
+ warnings.warn(
25
+ "WARNING: No id_fragment provided to main_content(). This is usually the page heading "
26
+ "and helps create a unique and consistent id attribute. Providing an id_fragment "
27
+ "improves accessibility, aids automated testing, and prevents issues with duplicate or "
28
+ "missing page headings.",
29
+ UserWarning,
30
+ stacklevel=2,
31
+ )
32
+
33
+ if not isinstance(children, list):
34
+ children = [children]
35
+
36
+ if include_feedback_banner_div:
37
+ children.append(html.Div(id="feedback-banner"))
38
+
39
+ return html.Main(children, className="main", id=slug, role="main")
@@ -1,9 +1,14 @@
1
1
  """notification_banner"""
2
+
2
3
  from dash import html
3
4
 
4
5
 
5
6
  def notification_banner(
6
- text: str, text_class_name: str = "govuk-warning-text__text", style: dict = None
7
+ text: list,
8
+ title: str = "Important",
9
+ text_class_name: str = "govuk-notification-banner__heading",
10
+ style: dict = None,
11
+ title_color: str = None,
7
12
  ):
8
13
  """
9
14
  Return Gov UK Design component notification banner component.
@@ -13,9 +18,10 @@ def notification_banner(
13
18
  html.Div(
14
19
  [
15
20
  html.H2(
16
- ["Important"],
21
+ [title],
17
22
  className="govuk-notification-banner__title",
18
23
  id="govuk-notification-banner-title",
24
+ style={"color": title_color} if title_color else None,
19
25
  )
20
26
  ],
21
27
  className="govuk-notification-banner__header",
@@ -23,9 +29,7 @@ def notification_banner(
23
29
  html.Div(
24
30
  [
25
31
  html.P(
26
- [
27
- text,
28
- ],
32
+ text,
29
33
  className=text_class_name,
30
34
  )
31
35
  ],
@@ -1,4 +1,5 @@
1
1
  """paragraph component"""
2
+
2
3
  from enum import Enum
3
4
  from typing import Union
4
5
 
@@ -1,10 +1,11 @@
1
1
  """phase_banner"""
2
+
2
3
  from dash import html
3
4
 
4
5
 
5
6
  def phase_banner_with_feedback(
6
7
  phase: str,
7
- feedback_link: str,
8
+ feedback_link: str = None,
8
9
  link_id: str = "feedback-link",
9
10
  link_target: str = "_self",
10
11
  ):
@@ -31,9 +32,11 @@ def phase_banner_with_feedback(
31
32
  className="govuk-link",
32
33
  id=link_id,
33
34
  target=link_target,
34
- rel="noopener noreferrer"
35
- if link_target == "_blank"
36
- else "", # conditional attribute for security
35
+ rel=(
36
+ "noopener noreferrer"
37
+ if link_target == "_blank"
38
+ else ""
39
+ ), # conditional attribute for security
37
40
  ),
38
41
  " will help us to improve it.",
39
42
  ],
@@ -1,4 +1,5 @@
1
1
  """row_component"""
2
+
2
3
  from dash import html
3
4
 
4
5