├── __init__.py
├── pages
├── themes.py
├── authentication.py
├── headers.py
├── leaflet.py
├── app_cards.py
├── buttons.py
├── carousels.py
├── tabs.py
├── menu.py
├── footers.py
├── uploaders.py
├── stats.py
├── navbars.py
├── tables.py
└── home.py
├── gunicorn_config.py
├── .gitignore
├── .vscode
└── settings.json
├── assets
├── dbc.png
├── logo.png
├── plotly.png
├── home_logo.png
├── mantine.png
├── tabs-light.png
├── leaflet-light.png
├── buttons-light.svg
├── style.css
├── carousels-light.svg
├── menus-light.svg
├── uploaders-light.svg
├── navbars-light.svg
├── tables.svg
├── stats-light.svg
├── cards-light.svg
├── headers-light.svg
├── footers-light.svg
└── auth-light.svg
├── requirements.txt
├── Dockerfile
├── readme.md
├── components
└── navbar.py
├── app.py
└── utils.py
/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pages/themes.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/gunicorn_config.py:
--------------------------------------------------------------------------------
1 | bind = "0.0.0.0:8050"
2 | workers = 3
3 | timeout = 120
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__
2 | *.yml
3 | environment/
4 | .vscode
5 | deploy.py
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "python.analysis.typeCheckingMode": "basic"
3 | }
--------------------------------------------------------------------------------
/assets/dbc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Spyhuntr/dmc-dbc-building-blocks/HEAD/assets/dbc.png
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Spyhuntr/dmc-dbc-building-blocks/HEAD/assets/logo.png
--------------------------------------------------------------------------------
/assets/plotly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Spyhuntr/dmc-dbc-building-blocks/HEAD/assets/plotly.png
--------------------------------------------------------------------------------
/assets/home_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Spyhuntr/dmc-dbc-building-blocks/HEAD/assets/home_logo.png
--------------------------------------------------------------------------------
/assets/mantine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Spyhuntr/dmc-dbc-building-blocks/HEAD/assets/mantine.png
--------------------------------------------------------------------------------
/assets/tabs-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Spyhuntr/dmc-dbc-building-blocks/HEAD/assets/tabs-light.png
--------------------------------------------------------------------------------
/assets/leaflet-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Spyhuntr/dmc-dbc-building-blocks/HEAD/assets/leaflet-light.png
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | boto3==1.35.92
2 | dash==2.18.2
3 | dash-mantine-components==0.15.1
4 | gunicorn==23.0.0
5 | requests==2.32.3
--------------------------------------------------------------------------------
/assets/buttons-light.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine:3.14
2 |
3 | WORKDIR /app
4 | COPY . /app
5 |
6 | ARG DEBIAN_FRONTEND=noninteractive
7 |
8 | ENV PYTHONDONTWRITEBYTECODE 1
9 | ENV PYTHON UNBUFFERED 1
10 |
11 | RUN apk add --no-cache python3 py3-pip wget curl \
12 | && pip3 install -r requirements.txt
13 |
14 | EXPOSE 8050
15 |
16 | ENTRYPOINT [ "gunicorn", "--config", "gunicorn_config.py", "app:server" ]
--------------------------------------------------------------------------------
/assets/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap');
2 |
3 | .card-hdr {
4 | background-color: #f8f9fa;
5 | transition: all .2s ease-in-out;
6 | }
7 |
8 | .card-hdr:hover {
9 | transform: scale(1.05);
10 | }
11 |
12 | #home_logo img {
13 | transform: rotate(-35deg);
14 | }
15 |
16 | .mantine-LoadingOverlay-root{
17 | position: fixed;
18 | }
19 |
20 | .mantine-Switch-track {
21 | padding: 0.5rem;
22 | }
--------------------------------------------------------------------------------
/assets/carousels-light.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/menus-light.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/uploaders-light.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/navbars-light.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/tables.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # DMC / DBC Building Blocks
2 |
3 | #### This page is designed to be a collection of front end building blocks built in either [Dash Mantine Components](https://www.dash-mantine-components.com/) and [Dash Bootstrap Components](https://dash-bootstrap-components.opensource.faculty.ai/) to plug and play into everyone's dash applications.
4 |
5 |
6 |
7 | ## Contributors Guide
8 | Thank you for contributing to the community supported `Dash Mantine & Dash Bootstrap Building Blocks` project!
9 |
10 | ## What are building blocks?
11 | Building blocks are small UI components that are part of an app. These building blocks are not a full app but rather can be added into an existing app to enhance the UI/UX experience of your dash application.
12 |
13 | ## Code Review Checklist
14 |
15 | ### Basic Requirements
16 | - [ ] Runs error free when added to an app running the latest version of dash, dash-bootstrap-components and/or dash-mantine-components.
17 | - [ ] Has no errors in the browser's developer console
18 | - [ ] Is a minimal example that only includes code necessary to display the building block
19 | - [ ] Layout is responsive - i.e. is functional and looks nice in various browser window sizes
20 | - [ ] Any required data is self-contained in the app or uses an external data source such as in [Plotly's repo (https://github.com/plotly/datasets).
21 |
22 |
23 | ### Style guide (suggestions only)
24 |
25 | - [ ] Code is formatted with black
26 |
27 | Naming conventions
28 | - [ ] Uses descriptive variable names
29 | - [ ] Uses python standard snake_case variable names ie `submit_button`
30 | - [ ] In the `style` prop, uses camel case: ie `style={"textAlign": "center"}`
31 |
32 |
33 | Concise code
34 | - [ ] Uses concise syntax available in Dash>=2.0
35 | For example use `dcc.Dropdown(df.columns)` rather than `dcc.Dropdown(options = [{'label':c, 'value':c} for c in df.columns]`
36 | - [ ] Does not put callback `Input()`s `Output()`s or `State()`s in a list
37 | - [ ] Does not include props that are set to the defaults for the component. For example, it's not necessary to include `multi=False` in the `dcc.Dropdown`. Check the reference section of the docs to see the defaults for the components.
38 | - [ ] Does not include unused imports
39 | - [ ] Uses Minimal comments - only those necessary to describe "why" rather than just describing what the code does.
40 | - [ ] Uses f-strings rather than `.format()`
41 |
42 |
43 | In apps using `dash-bootstrap-components`:
44 | - [ ] Uses `className` prop whenever possible instead of the `style` prop. For example: `className="bg-primary"` rather than `style={"backgroundColor": "blue"}`
45 | - [ ] Uses `dbc.Container` as the outer container of the app rather than `html.Div`
46 |
47 | In apps using both `dash-bootstrap-component`and `dash-mantine-components`
48 | - [ ] Uses one library as the primary library and only uses the secondary library where necessary.
49 |
--------------------------------------------------------------------------------
/components/navbar.py:
--------------------------------------------------------------------------------
1 | from dash import html
2 | import dash_mantine_components as dmc
3 |
4 | head = dmc.AppShellHeader(
5 | p="sm",
6 | mb="1rem",
7 | children=[
8 | dmc.Grid([
9 | dmc.GridCol([
10 | dmc.Group([
11 | html.Div([
12 | dmc.Image(
13 | src="/assets/logo.png"
14 | )], style={'width': 50}),
15 | dmc.Text(
16 | "Dash Mantine & Dash Bootstrap Building Blocks",
17 | size="xl",
18 | c="dimmed"
19 | )
20 | ], visibleFrom="md"),
21 | dmc.Text(
22 | "DMC & DBC",
23 | size="xl",
24 | hiddenFrom="md",
25 | c="dimmed"
26 | )
27 | ],
28 | span='auto'),
29 | dmc.GridCol(
30 | dmc.Group([
31 | dmc.Anchor(
32 | dmc.Avatar(
33 | src="/assets/mantine.png"
34 | ),
35 | href="https://www.dash-mantine-components.com/",
36 | target='_blank'
37 | ),
38 | dmc.Anchor(
39 | dmc.Avatar(
40 | src="/assets/plotly.png"
41 | ),
42 | href="https://dash.plotly.com/dash-ag-grid",
43 | target='_blank'
44 | ),
45 | dmc.Menu(
46 | [
47 | dmc.MenuTarget(
48 | dmc.Avatar(
49 | src="/assets/dbc.png",
50 | style={'cursor': 'pointer'}),
51 | ),
52 | dmc.MenuDropdown(
53 | [
54 | dmc.MenuItem(
55 | "Docs",
56 | href="https://dash-bootstrap-components.opensource.faculty.ai",
57 | target="_blank"
58 | ),
59 | dmc.MenuItem(
60 | "Theme Explorer",
61 | href="https://hellodash.pythonanywhere.com/",
62 | target="_blank"
63 | )
64 | ]
65 | ),
66 | ]
67 | )
68 | ], gap='xs', mt='6px'), span='content', p=0, pr='2rem'
69 | )
70 | ])
71 | ])
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | from dash import Dash, html, dash, dcc
2 | import dash_mantine_components as dmc
3 | import sys
4 | import utils as u
5 | sys.path.append('../components')
6 |
7 | dash._dash_renderer._set_react_version('18.2.0')
8 |
9 | from components.navbar import head
10 |
11 | stylesheets = [
12 | "https://unpkg.com/@mantine/code-highlight@7/styles.css",
13 | "https://unpkg.com/@mantine/notifications@7/styles.css"
14 | ]
15 |
16 | app = Dash(__name__,
17 | external_scripts=[{
18 | "src": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/js/all.min.js",
19 | "crossorigin": "anonymous"
20 | }],
21 | meta_tags=[
22 | {'name':'DMC-DBC-Building-Blocks', 'content':'DMC/DBC Building Blocks'},
23 | {'name': 'viewport', 'content': 'width=device-width, initial-scale=1'},
24 | {'http-equiv': 'X-UA-Compatible', 'content': 'IE=edge'},
25 | {'property':'og:url', 'content': 'https://dmc-dbc-building-blocks.onrender.com/'},
26 | {'property':'og:type', 'content': 'website'},
27 | {'property':'og:title', 'content': 'DMC/DBC Building Blocks'},
28 | {'property':'og:description','content':'Building blocks for DMC/DBC'},
29 | {'property':'og:image', 'content':'https://dmc-dbc-building-blocks.onrender.com/assets/logo.png'},
30 | {'property':'og:image:width', 'content':'500'},
31 | {'property':'og:image:height', 'content':'100'}
32 | ],
33 | external_stylesheets=stylesheets,
34 | suppress_callback_exceptions=True,
35 | use_pages=True
36 | )
37 |
38 | app.title = 'DMC & DBC Building Blocks'
39 |
40 | app.layout = dmc.MantineProvider(
41 | theme={
42 | 'fontFamily': '"Open Sans", sans-serif'
43 | },
44 | children=[
45 | dmc.NotificationProvider(position="top-right"),
46 | dmc.AppShell([
47 | head,
48 | dmc.AppShellMain(
49 | children=[
50 | dcc.Loading(dmc.Container(
51 | dash.page_container,
52 | id="page-container",
53 | pb='1rem',
54 | size='xl'
55 | ), type="dot", fullscreen=True),
56 | html.Div([
57 | dmc.Center(id='contributors', children=u.build_contributors()),
58 | dmc.Center([
59 | dmc.Text(
60 | "Contributors",
61 | )
62 | ])
63 | ])
64 | ], style={'backgroundColor': '#f1f3f5'}
65 | )
66 | ],
67 | header={"height": 60},
68 | padding="xl"
69 | )
70 | ]
71 | )
72 |
73 | server = app.server
74 |
75 | if __name__ == '__main__':
76 | app.run(dev_tools_hot_reload=True, debug=True)
77 |
--------------------------------------------------------------------------------
/assets/stats-light.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/pages/authentication.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/authentication', title='Authentication')
8 | prefix = 'examples/auth/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='auth-back_btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title(f"Authentication", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="auth-sample-container",
27 | children=[]
28 | )
29 | ])
30 |
31 |
32 | @callback(
33 | Output('auth-sample-container', 'children'),
34 | Input('auth-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 | new_sample = dmc.Card(
40 | withBorder=True,
41 | radius="md",
42 | mb="3rem",
43 | shadow='xl',
44 | children=[
45 | dmc.CardSection([
46 | dmc.Grid(
47 | children=[
48 | u.card_hdr(
49 | card_info['card_heading'], card_info['user'], card_info['deps']),
50 | dmc.Switch(
51 | id={
52 | "type": "auth-code-switch",
53 | "index": key
54 | },
55 | size="xl",
56 | onLabel="Code",
57 | offLabel="Preview",
58 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
59 | ], gutter=0, grow=True, justify='space-around'),
60 | ], inheritPadding=True, withBorder=True, py="xs"),
61 |
62 | html.Div(
63 | id={
64 | "type": "auth-rendering",
65 | "index": key
66 | },
67 | children=[]
68 | )
69 | ]
70 | )
71 |
72 | children.append(new_sample)
73 |
74 | return children
75 |
76 |
77 | @callback(
78 | Output({'type': 'auth-rendering', 'index': MATCH}, 'children'),
79 | Input({'type': 'auth-code-switch', 'index': MATCH}, 'checked'),
80 | State({'type': 'auth-code-switch', 'index': MATCH}, 'id')
81 | )
82 | def build_examples(switch, id):
83 |
84 | filename = examples[id['index']]['file'].namelist()[0]
85 |
86 | if switch:
87 |
88 | if filename.endswith(('py', 'css')):
89 | return dmc.CodeHighlight(
90 | language='python',
91 | code=examples[id['index']]['file'].read(filename).decode('utf-8')
92 | )
93 |
94 | else:
95 |
96 | image_file = u.get_example_image('auth', examples[id['index']]['image'])
97 |
98 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
99 |
--------------------------------------------------------------------------------
/pages/headers.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/headers', title='Headers')
8 | prefix = 'examples/headers/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='headers_back_btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title("Headers", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="headers-sample-container",
27 | children=[]
28 | )
29 | ])
30 |
31 |
32 | @callback(
33 | Output('headers-sample-container', 'children'),
34 | Input('headers-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 | new_sample = dmc.Card(
40 | withBorder=True,
41 | radius="md",
42 | mb="3rem",
43 | shadow='xl',
44 | children=[
45 | dmc.CardSection([
46 | dmc.Grid(
47 | children=[
48 | u.card_hdr(
49 | card_info['card_heading'], card_info['user'], card_info['deps']),
50 | dmc.Switch(
51 | id={
52 | "type": "headers-code-switch",
53 | "index": key
54 | },
55 | size="xl",
56 | onLabel="Code",
57 | offLabel="Preview",
58 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
59 | ], gutter=0, grow=True, justify='space-around'),
60 | ], inheritPadding=True, withBorder=True, py="xs"),
61 |
62 | html.Div(
63 | id={
64 | "type": "headers-rendering",
65 | "index": key
66 | },
67 | children=[]
68 | )
69 | ]
70 | )
71 |
72 | children.append(new_sample)
73 |
74 | return children
75 |
76 |
77 | @callback(
78 | Output({'type': 'headers-rendering', 'index': MATCH}, 'children'),
79 | Input({'type': 'headers-code-switch', 'index': MATCH}, 'checked'),
80 | State({'type': 'headers-code-switch', 'index': MATCH}, 'id')
81 | )
82 | def build_examples(switch, id):
83 |
84 | filename = examples[id['index']]['file'].namelist()[0]
85 |
86 | if switch:
87 |
88 | if filename.endswith(('py', 'css')):
89 | return dmc.CodeHighlight(
90 | language='python',
91 | code=examples[id['index']]['file'].read(filename).decode('utf-8')
92 | )
93 |
94 | else:
95 |
96 | image_file = u.get_example_image('headers', examples[id['index']]['image'])
97 |
98 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
99 |
--------------------------------------------------------------------------------
/pages/leaflet.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/leaflet', title='Leaflet')
8 | prefix = 'examples/leaflet/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='leaflet_back_btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title("Leaflet", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="leaflet-sample-container",
27 | children=[]
28 | )
29 | ])
30 |
31 |
32 | @callback(
33 | Output('leaflet-sample-container', 'children'),
34 | Input('leaflet-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 | new_sample = dmc.Card(
40 | withBorder=True,
41 | radius="md",
42 | mb="3rem",
43 | shadow='xl',
44 | children=[
45 | dmc.CardSection([
46 | dmc.Grid(
47 | children=[
48 | u.card_hdr(
49 | card_info['card_heading'], card_info['user'], card_info['deps']),
50 | dmc.Switch(
51 | id={
52 | "type": "leaflet-code-switch",
53 | "index": key
54 | },
55 | size="xl",
56 | onLabel="Code",
57 | offLabel="Preview",
58 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
59 | ], gutter=0, grow=True, justify='space-around'),
60 | ], inheritPadding=True, withBorder=True, py="xs"),
61 |
62 | html.Div(
63 | id={
64 | "type": "leaflet-rendering",
65 | "index": key
66 | },
67 | children=[]
68 | )
69 | ]
70 | )
71 |
72 | children.append(new_sample)
73 |
74 | return children
75 |
76 |
77 | @callback(
78 | Output({'type': 'leaflet-rendering', 'index': MATCH}, 'children'),
79 | Input({'type': 'leaflet-code-switch', 'index': MATCH}, 'checked'),
80 | State({'type': 'leaflet-code-switch', 'index': MATCH}, 'id')
81 | )
82 | def build_examples(switch, id):
83 |
84 | filename = examples[id['index']]['file'].namelist()[0]
85 |
86 | if switch:
87 |
88 | if filename.endswith(('py', 'css')):
89 | return dmc.CodeHighlight(
90 | language='python',
91 | code=examples[id['index']]['file'].read(filename).decode('utf-8')
92 | )
93 |
94 | else:
95 |
96 | image_file = u.get_example_image('leaflet', examples[id['index']]['image'])
97 |
98 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
99 |
--------------------------------------------------------------------------------
/assets/cards-light.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/pages/app_cards.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/app_cards', title='Cards')
8 | prefix = 'examples/cards/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='cards-back_btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title(f"Application Cards", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="cards-sample-container",
27 | children=[]
28 | ),
29 | ])
30 |
31 |
32 | @callback(
33 | Output('cards-sample-container', 'children'),
34 | Input('cards-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 |
40 | new_sample = dmc.Card(
41 | withBorder=True,
42 | radius="md",
43 | mb="3rem",
44 | shadow='xl',
45 | children=[
46 | dmc.CardSection([
47 | dmc.Grid(
48 | children=[
49 | u.card_hdr(
50 | card_info['card_heading'], card_info['user'], card_info['deps']),
51 | dmc.Switch(
52 | id={
53 | "type": "cards-code-switch",
54 | "index": key
55 | },
56 | size="xl",
57 | onLabel="Code",
58 | offLabel="Preview",
59 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
60 | ], gutter=0, grow=True, justify='space-around'),
61 | ], inheritPadding=True, withBorder=True, py="xs"),
62 |
63 | html.Div(
64 | id={
65 | "type": "cards-rendering",
66 | "index": key
67 | },
68 | children=[]
69 | )
70 | ]
71 | )
72 |
73 | children.append(new_sample)
74 |
75 | return children
76 |
77 |
78 | @callback(
79 | Output({'type': 'cards-rendering', 'index': MATCH}, 'children'),
80 | Input({'type': 'cards-code-switch', 'index': MATCH}, 'checked'),
81 | State({'type': 'cards-code-switch', 'index': MATCH}, 'id')
82 | )
83 | def state_change(switch, id):
84 |
85 | filename = examples[id['index']]['file'].namelist()[0]
86 |
87 | if switch:
88 |
89 | if filename.endswith(('py', 'css')):
90 | return dmc.CodeHighlight(
91 | language='python',
92 | code=examples[id['index']]['file'].read(filename).decode('utf-8')
93 | )
94 |
95 | else:
96 |
97 | image_file = u.get_example_image('cards', examples[id['index']]['image'])
98 |
99 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
100 |
--------------------------------------------------------------------------------
/pages/buttons.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/buttons', title='Buttons')
8 | prefix = 'examples/buttons/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='buttons-back_btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title(f"Buttons", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="buttons-sample-container",
27 | children=[]
28 | ),
29 | ])
30 |
31 |
32 | @callback(
33 | Output('buttons-sample-container', 'children'),
34 | Input('buttons-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 |
40 | new_sample = dmc.Card(
41 | withBorder=True,
42 | radius="md",
43 | mb="3rem",
44 | shadow='xl',
45 | children=[
46 | dmc.CardSection([
47 | dmc.Grid(
48 | children=[
49 | u.card_hdr(
50 | card_info['card_heading'], card_info['user'], card_info['deps']),
51 | dmc.Switch(
52 | id={
53 | "type": "buttons-code-switch",
54 | "index": key
55 | },
56 | size="xl",
57 | onLabel="Code",
58 | offLabel="Preview",
59 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
60 | ], gutter=0, grow=True, justify='space-around'),
61 | ], inheritPadding=True, withBorder=True, py="xs"),
62 |
63 | html.Div(
64 | id={
65 | "type": "buttons-rendering",
66 | "index": key
67 | },
68 | children=[]
69 | )
70 | ]
71 | )
72 |
73 | children.append(new_sample)
74 |
75 | return children
76 |
77 |
78 | @callback(
79 | Output({'type': 'buttons-rendering', 'index': MATCH}, 'children'),
80 | Input({'type': 'buttons-code-switch', 'index': MATCH}, 'checked'),
81 | State({'type': 'buttons-code-switch', 'index': MATCH}, 'id')
82 | )
83 | def state_change(switch, id):
84 |
85 | filename = examples[id['index']]['file'].namelist()[0]
86 |
87 | if switch:
88 |
89 | if filename.endswith(('py', 'css')):
90 | return dmc.CodeHighlight(
91 | language='python',
92 | code=examples[id['index']]['file'].read(filename).decode('utf-8')
93 | )
94 |
95 | else:
96 |
97 | image_file = u.get_example_image('buttons', examples[id['index']]['image'])
98 |
99 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
100 |
--------------------------------------------------------------------------------
/pages/carousels.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/carousels', title='Carousels')
8 | prefix = 'examples/carousels/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='carousels-back_btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title(f"Carousels", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="carousels-sample-container",
27 | children=[]
28 | ),
29 | ])
30 |
31 |
32 | @callback(
33 | Output('carousels-sample-container', 'children'),
34 | Input('carousels-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 |
40 | new_sample = dmc.Card(
41 | withBorder=True,
42 | radius="md",
43 | mb="3rem",
44 | shadow='xl',
45 | children=[
46 | dmc.CardSection([
47 | dmc.Grid(
48 | children=[
49 | u.card_hdr(
50 | card_info['card_heading'], card_info['user'], card_info['deps']),
51 | dmc.Switch(
52 | id={
53 | "type": "carousels-code-switch",
54 | "index": key
55 | },
56 | size="xl",
57 | onLabel="Code",
58 | offLabel="Preview",
59 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
60 | ], gutter=0, grow=True, justify='space-around'),
61 | ], inheritPadding=True, withBorder=True, py="xs"),
62 |
63 | html.Div(
64 | id={
65 | "type": "carousels-rendering",
66 | "index": key
67 | },
68 | children=[]
69 | )
70 | ]
71 | )
72 |
73 | children.append(new_sample)
74 |
75 | return children
76 |
77 |
78 | @callback(
79 | Output({'type': 'carousels-rendering', 'index': MATCH}, 'children'),
80 | Input({'type': 'carousels-code-switch', 'index': MATCH}, 'checked'),
81 | State({'type': 'carousels-code-switch', 'index': MATCH}, 'id')
82 | )
83 | def state_change(switch, id):
84 |
85 | filename = examples[id['index']]['file'].namelist()[0]
86 |
87 | if switch:
88 |
89 | if filename.endswith(('py', 'css')):
90 | return dmc.CodeHighlight(
91 | language='python',
92 | code=examples[id['index']]['file'].read(filename).decode('utf-8')
93 | )
94 |
95 | else:
96 |
97 | image_file = u.get_example_image('carousels', examples[id['index']]['image'])
98 |
99 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
100 |
--------------------------------------------------------------------------------
/pages/tabs.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, ctx, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/tabs', title='Home')
8 | prefix = 'examples/tabs/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='tabs-back-btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title(f"Tabs", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="tabs-sample-container",
27 | children=[]
28 | )
29 | ])
30 |
31 |
32 | @callback(
33 | Output('tabs-sample-container', 'children'),
34 | Input('tabs-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 | new_sample = dmc.Card(
40 | withBorder=True,
41 | radius="md",
42 | mb="3rem",
43 | shadow='xl',
44 | children=[
45 | dmc.CardSection([
46 | dmc.Grid(
47 | children=[
48 | u.card_hdr(
49 | card_info['card_heading'], card_info['user'], card_info['deps']),
50 | dmc.Switch(
51 | id={
52 | "type": "tabs-code-switch",
53 | "index": key
54 | },
55 | size="xl",
56 | onLabel="Code",
57 | offLabel="Preview",
58 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
59 | ], gutter=0, grow=True, justify='space-around'),
60 | ], inheritPadding=True, withBorder=True, py="xs"),
61 |
62 | html.Div(
63 | id={
64 | "type": "tabs-rendering",
65 | "index": key
66 | },
67 | children=[]
68 | )
69 | ]
70 | )
71 |
72 | children.append(new_sample)
73 |
74 | return children
75 |
76 |
77 | @callback(
78 | Output({'type': 'tabs-rendering', 'index': MATCH}, 'children'),
79 | Input({'type': 'tabs-code-switch', 'index': MATCH}, 'checked'),
80 | State({'type': 'tabs-code-switch', 'index': MATCH}, 'id')
81 | )
82 | def state_change(switch, id):
83 |
84 | filename = examples[id['index']]['file'].namelist()
85 |
86 | py_file = None
87 | css_file = None
88 | for name in filename:
89 |
90 | if name.endswith('py'):
91 | py_file = examples[id['index']]['file'].read(name).decode('utf-8')
92 |
93 | if name.endswith('css'):
94 | css_file = examples[id['index']]['file'].read(name).decode('utf-8')
95 |
96 | if switch:
97 | return html.Div([
98 | dmc.Grid([
99 | dmc.GridCol([
100 | dmc.Text("Python", p="xs"),
101 | dmc.CodeHighlight(
102 | language='python',
103 | code=py_file,
104 | style={'border': '1px solid #ececec'},
105 | mr='1rem'
106 | )], span=6),
107 | dmc.GridCol([
108 | dmc.Group([dmc.Text("CSS"), dmc.Text(
109 | "Add to ./assets/style.css in your app", size='xs')], p='xs'),
110 | dmc.CodeHighlight(
111 | language='css',
112 | code=css_file,
113 | style={'border': '1px solid #ececec'}
114 | )], span=6)
115 | ], gutter=0)
116 | ])
117 | else:
118 | image_file = u.get_example_image('tabs', examples[id['index']]['image'])
119 |
120 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
121 |
--------------------------------------------------------------------------------
/pages/menu.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/menus', title='Menus')
8 | prefix = 'examples/menus/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='menus-back-btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title(f"Menus", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="menus-sample-container",
27 | children=[]
28 | )
29 | ])
30 |
31 |
32 | @callback(
33 | Output('menus-sample-container', 'children'),
34 | Input('menus-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 | new_sample = dmc.Card(
40 | withBorder=True,
41 | radius="md",
42 | mb="3rem",
43 | shadow='xl',
44 | children=[
45 | dmc.CardSection([
46 | dmc.Grid(
47 | children=[
48 | u.card_hdr(
49 | card_info['card_heading'], card_info['user'], card_info['deps']),
50 | dmc.Switch(
51 | id={
52 | "type": "menus-code-switch",
53 | "index": key
54 | },
55 | size="xl",
56 | onLabel="Code",
57 | offLabel="Preview",
58 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
59 | ], gutter=0, grow=True, justify='space-around'),
60 | ], inheritPadding=True, withBorder=True, py="xs"),
61 |
62 | html.Div(
63 | id={
64 | "type": "menus-rendering",
65 | "index": key
66 | },
67 | children=[]
68 | )
69 | ]
70 | )
71 |
72 | children.append(new_sample)
73 |
74 | return children
75 |
76 |
77 | @callback(
78 | Output({'type': 'menus-rendering', 'index': MATCH}, 'children'),
79 | Input({'type': 'menus-code-switch', 'index': MATCH}, 'checked'),
80 | State({'type': 'menus-code-switch', 'index': MATCH}, 'id')
81 | )
82 | def state_change(switch, id):
83 |
84 | filename = examples[id['index']]['file'].namelist()
85 |
86 | py_file = None
87 | css_file = None
88 | for name in filename:
89 |
90 | if name.endswith('py'):
91 | py_file = examples[id['index']]['file'].read(name).decode('utf-8')
92 |
93 | if name.endswith('css'):
94 | css_file = examples[id['index']]['file'].read(name).decode('utf-8')
95 |
96 | if switch:
97 | return html.Div([
98 | dmc.Grid([
99 | dmc.GridCol([
100 | dmc.Text("Python", p="xs"),
101 | dmc.CodeHighlight(
102 | language='python',
103 | code=py_file,
104 | style={'border': '1px solid #ececec'},
105 | mr='1rem'
106 | )], span=6),
107 | dmc.GridCol([
108 | dmc.Group([dmc.Text("CSS"), dmc.Text(
109 | "Add to ./assets/style.css in your app", size='xs')], p='xs'),
110 | dmc.CodeHighlight(
111 | language='css',
112 | code=css_file,
113 | style={'border': '1px solid #ececec'}
114 | )], span=6)
115 | ], gutter=0)
116 | ])
117 | else:
118 | image_file = u.get_example_image('menus', examples[id['index']]['image'])
119 |
120 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
121 |
--------------------------------------------------------------------------------
/pages/footers.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, ctx, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/footers', title='Home')
8 | prefix = 'examples/footers/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='footers-back-btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title("Footers", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="footers-sample-container",
27 | children=[]
28 | )
29 | ])
30 |
31 |
32 | @callback(
33 | Output('footers-sample-container', 'children'),
34 | Input('footers-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 | new_sample = dmc.Card(
40 | withBorder=True,
41 | radius="md",
42 | mb="3rem",
43 | shadow='xl',
44 | children=[
45 | dmc.CardSection([
46 | dmc.Grid(
47 | children=[
48 | u.card_hdr(
49 | card_info['card_heading'], card_info['user'], card_info['deps']),
50 | dmc.Switch(
51 | id={
52 | "type": "footers-code-switch",
53 | "index": key
54 | },
55 | size="xl",
56 | onLabel="Code",
57 | offLabel="Preview",
58 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
59 | ], gutter=0, grow=True, justify='space-around'),
60 | ], inheritPadding=True, withBorder=True, py="xs"),
61 |
62 | html.Div(
63 | id={
64 | "type": "footers-rendering",
65 | "index": key
66 | },
67 | children=[]
68 | )
69 | ]
70 | )
71 |
72 | children.append(new_sample)
73 |
74 | return children
75 |
76 |
77 | @callback(
78 | Output({'type': 'footers-rendering', 'index': MATCH}, 'children'),
79 | Input({'type': 'footers-code-switch', 'index': MATCH}, 'checked'),
80 | State({'type': 'footers-code-switch', 'index': MATCH}, 'id')
81 | )
82 | def state_change(switch, id):
83 |
84 | filename = examples[id['index']]['file'].namelist()
85 |
86 | py_file = None
87 | css_file = None
88 | for name in filename:
89 |
90 | if name.endswith('py'):
91 | py_file = examples[id['index']]['file'].read(name).decode('utf-8')
92 |
93 | if name.endswith('css'):
94 | css_file = examples[id['index']]['file'].read(name).decode('utf-8')
95 |
96 | if switch:
97 | return html.Div([
98 | dmc.Grid([
99 | dmc.GridCol([
100 | dmc.Text("Python", p="xs"),
101 | dmc.CodeHighlight(
102 | language='python',
103 | code=py_file,
104 | style={'border': '1px solid #ececec'},
105 | mr='1rem'
106 | )], span=6),
107 | dmc.GridCol([
108 | dmc.Group([dmc.Text("CSS"), dmc.Text(
109 | "Add to ./assets/style.css in your app", size='xs')], p='xs'),
110 | dmc.CodeHighlight(
111 | language='css',
112 | code=css_file,
113 | style={'border': '1px solid #ececec'}
114 | )], span=6)
115 | ], gutter=0)
116 | ])
117 | else:
118 | image_file = u.get_example_image('footers', examples[id['index']]['image'])
119 |
120 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
121 |
--------------------------------------------------------------------------------
/pages/uploaders.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, ctx, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/uploaders', title='Uploaders')
8 | prefix = 'examples/uploaders/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='uploaders-back-btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title(f"Uploaders / Downloaders", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="uploaders-sample-container",
27 | children=[]
28 | )
29 | ])
30 |
31 |
32 | @callback(
33 | Output('uploaders-sample-container', 'children'),
34 | Input('uploaders-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 | new_sample = dmc.Card(
40 | withBorder=True,
41 | radius="md",
42 | mb="3rem",
43 | shadow='xl',
44 | children=[
45 | dmc.CardSection([
46 | dmc.Grid(
47 | children=[
48 | u.card_hdr(
49 | card_info['card_heading'], card_info['user'], card_info['deps']),
50 | dmc.Switch(
51 | id={
52 | "type": "uploaders-code-switch",
53 | "index": key
54 | },
55 | size="xl",
56 | onLabel="Code",
57 | offLabel="Preview",
58 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
59 | ], gutter=0, grow=True, justify='space-around'),
60 | ], inheritPadding=True, withBorder=True, py="xs"),
61 |
62 | html.Div(
63 | id={
64 | "type": "uploaders-rendering",
65 | "index": key
66 | },
67 | children=[]
68 | )
69 | ]
70 | )
71 |
72 | children.append(new_sample)
73 |
74 | return children
75 |
76 |
77 | @callback(
78 | Output({'type': 'uploaders-rendering', 'index': MATCH}, 'children'),
79 | Input({'type': 'uploaders-code-switch', 'index': MATCH}, 'checked'),
80 | State({'type': 'uploaders-code-switch', 'index': MATCH}, 'id')
81 | )
82 | def state_change(switch, id):
83 |
84 | filename = examples[id['index']]['file'].namelist()
85 |
86 | py_file = None
87 | css_file = None
88 | for name in filename:
89 |
90 | if name.endswith('py'):
91 | py_file = examples[id['index']]['file'].read(name).decode('utf-8')
92 |
93 | if name.endswith('css'):
94 | css_file = examples[id['index']]['file'].read(name).decode('utf-8')
95 |
96 | if switch:
97 | return html.Div([
98 | dmc.Grid([
99 | dmc.GridCol([
100 | dmc.Text("Python", p="xs"),
101 | dmc.CodeHighlight(
102 | language='python',
103 | code=py_file,
104 | style={'border': '1px solid #ececec'},
105 | mr='1rem'
106 | )], span=6),
107 | dmc.GridCol([
108 | dmc.Group([dmc.Text("CSS"), dmc.Text(
109 | "Add to ./assets/style.css in your app", size='xs')], p='xs'),
110 | dmc.CodeHighlight(
111 | language='css',
112 | code=css_file,
113 | style={'border': '1px solid #ececec'}
114 | )], span=6)
115 | ], gutter=0)
116 | ])
117 | else:
118 | image_file = u.get_example_image('uploaders', examples[id['index']]['image'])
119 |
120 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
121 |
--------------------------------------------------------------------------------
/pages/stats.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, ctx, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/stats', title='Home')
8 | prefix = 'examples/stats/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='stats-back-btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title(f"Stats", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="stats-sample-container",
27 | children=[]
28 | )
29 | ])
30 |
31 |
32 | @callback(
33 | Output('stats-sample-container', 'children'),
34 | Input('stats-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 | new_sample = dmc.Card(
40 | withBorder=True,
41 | radius="md",
42 | mb="3rem",
43 | shadow='xl',
44 | children=[
45 | dmc.CardSection([
46 | dmc.Grid(
47 | children=[
48 | u.card_hdr(
49 | card_info['card_heading'], card_info['user'], card_info['deps']),
50 | dmc.Switch(
51 | id={
52 | "type": "stats-code-switch",
53 | "index": key
54 | },
55 | size="xl",
56 | onLabel="Code",
57 | offLabel="Preview",
58 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
59 | ], gutter=0, grow=True, justify='space-around'),
60 | ], inheritPadding=True, withBorder=True, py="xs"),
61 |
62 | html.Div(
63 | id={
64 | "type": "stats-rendering",
65 | "index": key
66 | },
67 | children=[]
68 | )
69 | ]
70 | )
71 |
72 | children.append(new_sample)
73 |
74 | return children
75 |
76 |
77 | @callback(
78 | Output({'type': 'stats-rendering', 'index': MATCH}, 'children'),
79 | Input({'type': 'stats-code-switch', 'index': MATCH}, 'checked'),
80 | State({'type': 'stats-code-switch', 'index': MATCH}, 'id')
81 | )
82 | def state_change(switch, id):
83 |
84 | filename = examples[id['index']]['file'].namelist()
85 |
86 | py_file = None
87 | css_file = None
88 | for name in filename:
89 |
90 | if name.endswith('py'):
91 | py_file = examples[id['index']]['file'].read(name).decode('utf-8')
92 |
93 | if name.endswith('css'):
94 | css_file = examples[id['index']]['file'].read(name).decode('utf-8')
95 |
96 | if switch:
97 | if css_file is None:
98 | return html.Div([
99 | dmc.Grid([
100 | dmc.GridCol([
101 | dmc.Text("Python", p="xs"),
102 | dmc.CodeHighlight(
103 | language='python',
104 | code=py_file,
105 | style={'border': '1px solid #ececec'},
106 | mr='1rem'
107 | )])
108 | ], gutter=0)
109 | ])
110 |
111 | else:
112 |
113 | return html.Div([
114 | dmc.Grid([
115 | dmc.GridCol([
116 | dmc.Text("Python", p="xs"),
117 | dmc.CodeHighlight(
118 | language='python',
119 | code=py_file,
120 | style={'border': '1px solid #ececec'},
121 | mr='1rem'
122 | )], span=6),
123 | dmc.GridCol([
124 | dmc.Group([dmc.Text("CSS"), dmc.Text(
125 | "Add to ./assets/style.css in your app", size='xs')], p='xs'),
126 | dmc.CodeHighlight(
127 | language='css',
128 | code=css_file,
129 | style={'border': '1px solid #ececec'}
130 | )], span=6)
131 | ], gutter=0)
132 | ])
133 | else:
134 | image_file = u.get_example_image('stats', examples[id['index']]['image'])
135 |
136 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
137 |
--------------------------------------------------------------------------------
/pages/navbars.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/navbars', title='Home')
8 | prefix = 'examples/navbars/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='navbars-back-btn',
17 | href="../",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title(f"Navbars", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="navbars-sample-container",
27 | children=[]
28 | )
29 | ])
30 |
31 |
32 | @callback(
33 | Output('navbars-sample-container', 'children'),
34 | Input('navbars-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 | new_sample = dmc.Card(
40 | withBorder=True,
41 | radius="md",
42 | mb="3rem",
43 | shadow='xl',
44 | children=[
45 | dmc.CardSection([
46 | dmc.Grid(
47 | children=[
48 | u.card_hdr(
49 | card_info['card_heading'], card_info['user'], card_info['deps']),
50 | dmc.Switch(
51 | id={
52 | "type": "navbars-code-switch",
53 | "index": key
54 | },
55 | size="xl",
56 | onLabel="Code",
57 | offLabel="Preview",
58 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
59 | ], gutter=0, grow=True, justify='space-around'),
60 | ], inheritPadding=True, withBorder=True, py="xs"),
61 |
62 | html.Div(
63 | id={
64 | "type": "navbars-rendering",
65 | "index": key
66 | },
67 | children=[]
68 | )
69 | ]
70 | )
71 |
72 | children.append(new_sample)
73 |
74 | return children
75 |
76 |
77 | @callback(
78 | Output({'type': 'navbars-rendering', 'index': MATCH}, 'children'),
79 | Input({'type': 'navbars-code-switch', 'index': MATCH}, 'checked'),
80 | State({'type': 'navbars-code-switch', 'index': MATCH}, 'id')
81 | )
82 | def state_change(switch, id):
83 |
84 | filename = examples[id['index']]['file'].namelist()
85 |
86 | py_file = None
87 | css_file = None
88 | for name in filename:
89 |
90 | if name.endswith('py'):
91 | py_file = examples[id['index']]['file'].read(name).decode('utf-8')
92 |
93 | if name.endswith('css'):
94 | css_file = examples[id['index']]['file'].read(name).decode('utf-8')
95 |
96 | if switch:
97 | if css_file is None:
98 | return html.Div([
99 | dmc.Grid([
100 | dmc.GridCol([
101 | dmc.Text("Python", p="xs"),
102 | dmc.CodeHighlight(
103 | language='python',
104 | code=py_file,
105 | style={'border': '1px solid #ececec'},
106 | mr='1rem'
107 | )])
108 | ], gutter=0)
109 | ])
110 |
111 | else:
112 |
113 | return html.Div([
114 | dmc.Grid([
115 | dmc.GridCol([
116 | dmc.Text("Python", p="xs"),
117 | dmc.CodeHighlight(
118 | language='python',
119 | code=py_file,
120 | style={'border': '1px solid #ececec'},
121 | mr='1rem'
122 | )], span=6),
123 | dmc.GridCol([
124 | dmc.Group([dmc.Text("CSS"), dmc.Text(
125 | "Add to ./assets/style.css in your app", size='xs')], p='xs'),
126 | dmc.CodeHighlight(
127 | language='css',
128 | code=css_file,
129 | style={'border': '1px solid #ececec'}
130 | )], span=6)
131 | ], gutter=0)
132 | ])
133 | else:
134 | image_file = u.get_example_image('navbars', examples[id['index']]['image'])
135 |
136 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
--------------------------------------------------------------------------------
/pages/tables.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import callback, Output, Input, State, MATCH, html, dcc
4 | import dash_mantine_components as dmc
5 | import utils as u
6 |
7 | dash.register_page(__name__, path='/tables', title='Tables')
8 | prefix = 'examples/tables/'
9 |
10 | examples = u.get_example_files(prefix)
11 |
12 | layout = dmc.Grid(
13 | children=[
14 | dmc.GridCol(
15 | dcc.Link(
16 | id='tables-back_btn',
17 | href="/",
18 | children=[
19 | dmc.Button("< Back to all categories", variant="outline")
20 | ])
21 | ),
22 | dmc.GridCol(
23 | dmc.Title(f"Tables", order=1)
24 | ),
25 | dmc.GridCol(
26 | id="tables-sample-container",
27 | children=[]
28 | ),
29 | ])
30 |
31 |
32 | @callback(
33 | Output('tables-sample-container', 'children'),
34 | Input('tables-sample-container', 'children')
35 | )
36 | def build_layout(children):
37 |
38 | for key, card_info in enumerate(examples):
39 |
40 | new_sample = dmc.Card(
41 | withBorder=True,
42 | radius="md",
43 | mb="3rem",
44 | shadow='xl',
45 | children=[
46 | dmc.CardSection([
47 | dmc.Grid(
48 | children=[
49 | u.card_hdr(
50 | card_info['card_heading'], card_info['user'], card_info['deps']),
51 | dmc.Switch(
52 | id={
53 | "type": "tables-code-switch",
54 | "index": key
55 | },
56 | size="xl",
57 | onLabel="Code",
58 | offLabel="Preview",
59 | style={"marginTop": "-0.2rem", 'marginRight':'0.5rem'}),
60 | ], gutter=0, grow=True, justify='space-around'),
61 | ], inheritPadding=True, withBorder=True, py="xs"),
62 |
63 | html.Div(
64 | id={
65 | "type": "tables-rendering",
66 | "index": key
67 | },
68 | children=[]
69 | )
70 | ]
71 | )
72 |
73 | children.append(new_sample)
74 |
75 | return children
76 |
77 |
78 | @callback(
79 | Output({'type': 'tables-rendering', 'index': MATCH}, 'children'),
80 | Input({'type': 'tables-code-switch', 'index': MATCH}, 'checked'),
81 | State({'type': 'tables-code-switch', 'index': MATCH}, 'id')
82 | )
83 | def state_change(switch, id):
84 |
85 | filename = examples[id['index']]['file'].namelist()
86 |
87 | py_file = None
88 | css_file = None
89 | js_file = None
90 | for name in filename:
91 |
92 | if name.endswith('py'):
93 | py_file = examples[id['index']]['file'].read(name).decode('utf-8')
94 |
95 | if name.endswith('css'):
96 | css_file = examples[id['index']]['file'].read(name).decode('utf-8')
97 |
98 | if name.endswith('js'):
99 | js_file = examples[id['index']]['file'].read(name).decode('utf-8')
100 |
101 |
102 | if switch:
103 | return html.Div([
104 | dmc.Grid([
105 | dmc.GridCol([
106 | dmc.Text("Python", p="xs"),
107 | dmc.CodeHighlight(
108 | language='python',
109 | code=py_file,
110 | style={'border': '1px solid #ececec'},
111 | mr='1rem'
112 | )], span=6),
113 | dmc.GridCol([
114 | dmc.Group([
115 | dmc.Text("CSS"),
116 | dmc.Text("Add to ./assets/style.css in your app", size='xs')
117 | ], p='xs'),
118 | dmc.CodeHighlight(
119 | language='css',
120 | code=css_file,
121 | style={'border': '1px solid #ececec'}
122 | ),
123 | dmc.Group([
124 | dmc.Text("JS"),
125 | dmc.Text("Add to ./assets folder in your app", size='xs')
126 | ], p='xs'),
127 | dmc.CodeHighlight(
128 | language='js',
129 | code=js_file,
130 | style={'border': '1px solid #ececec'}
131 | )
132 | ], span=6)
133 | ], gutter=0)
134 | ])
135 | else:
136 | image_file = u.get_example_image('tables', examples[id['index']]['image'])
137 |
138 | return dmc.Center(html.Img(src=f'data:image/png;base64,{image_file}'), p='xl')
139 |
--------------------------------------------------------------------------------
/assets/headers-light.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | import boto3
2 | import dash_mantine_components as dmc
3 | import logging
4 | from botocore.exceptions import ClientError
5 | import requests
6 | from zipfile import ZipFile
7 | import io
8 | from dash import html
9 | from typing import List, Union
10 | from base64 import b64encode
11 |
12 | bucket = 'dmc-dbc-building-blocks'
13 |
14 | s3_client = boto3.client('s3')
15 |
16 | def card_hdr(title: str, user: str, deps: str):
17 |
18 | link = dmc.Anchor(
19 | href=f"https://github.com/{user}",
20 | children=['@' + user],
21 | size="xs",
22 | ml="-0.7rem",
23 | style={'color': 'rgb(134, 142, 150)'})
24 |
25 | menu_items: List[Union[dmc.MenuItem, dmc.MenuLabel]] = [dmc.MenuLabel("Dependencies")]
26 | for dep in list(deps.split(',')):
27 | menu_item = dmc.MenuItem(dep)
28 |
29 | menu_items.append(menu_item)
30 |
31 | menu = dmc.Menu([
32 | dmc.MenuTarget(
33 | dmc.Avatar(
34 | html.I(className='fas fa-sitemap fa-fw'), size='sm'
35 | )
36 | ),
37 | dmc.MenuDropdown(
38 | children=menu_items
39 |
40 | ),
41 | ], trigger='hover')
42 |
43 | return dmc.GridCol(
44 | children=[
45 | dmc.Group([
46 | dmc.Text(
47 | title,
48 | size="1.25rem"
49 | ),
50 | dmc.Text(
51 | 'Made by',
52 | size="xs",
53 | ),
54 | link,
55 | menu
56 | ], visibleFrom='sm'),
57 | dmc.Text(
58 | title,
59 | size="1.25rem",
60 | hiddenFrom='sm'
61 | )
62 | ], style={'alignContent': 'center'}, span='auto')
63 |
64 |
65 | def build_contributors():
66 |
67 | contributors = ['snehilvj', 'tcbegley', 'AnnMarieW', 'Spyhuntr', 'Sohibjon', 'pip-install-python',
68 | 'amihaiOff', 'BSd3v', 'RaghunathDewal', 'topaccina', 'martin2097']
69 | contrib_group = []
70 | for contributor in contributors:
71 |
72 | new_link = dmc.Anchor(
73 | dmc.Tooltip(
74 | label=contributor,
75 | withArrow=True,
76 | children=[
77 | dmc.Avatar(
78 | src=f"https://github.com/{contributor}.png", radius="xl"
79 | )
80 | ]
81 | ),
82 | href=f"https://github.com/{contributor}",
83 | target='_blank'
84 | )
85 |
86 | contrib_group.append(new_link)
87 |
88 | return dmc.AvatarGroup(contrib_group)
89 |
90 |
91 | def create_presigned_post(bucket_name, object_name):
92 | """Generate a presigned URL S3 POST request to upload a file
93 |
94 | :param bucket_name: string
95 | :param object_name: string
96 | :param expiration: Time in seconds for the presigned URL to remain valid
97 | :return: Dictionary with the following keys:
98 | url: URL to post to
99 | fields: Dictionary of form fields and values to submit with the POST
100 | :return: None if error.
101 | """
102 |
103 | try:
104 | response = s3_client.generate_presigned_post(bucket_name,
105 | object_name,
106 | ExpiresIn=3600)
107 | except ClientError as e:
108 | logging.error(e)
109 | return None
110 |
111 | # The response contains the presigned URL and required fields
112 | return response
113 |
114 |
115 | def upload_file(contents, filename, date):
116 |
117 | result = create_presigned_post(bucket, 'uploads/' + filename)
118 |
119 | if result is not None:
120 | # Upload file to S3 using presigned URL
121 | files = {'file': contents}
122 | r = requests.post(result['url'], data=result['fields'], files=files)
123 |
124 | return r
125 |
126 |
127 | def get_example_files(prefix):
128 |
129 | example_files = s3_client.list_objects_v2(
130 | Bucket=bucket,
131 | Prefix=prefix,
132 | Delimiter='/'
133 | )
134 |
135 | file_list = []
136 | for obj in example_files.get('Contents'):
137 |
138 | if obj['Size'] > 0:
139 |
140 | key = obj.get('Key')
141 |
142 | # sample file
143 | file = s3_client.get_object(Bucket=bucket, Key=key)
144 | # meta data on the file that has user-id etc on it
145 | header = s3_client.head_object(Bucket=bucket, Key=key)
146 |
147 | f = ZipFile(io.BytesIO(file['Body'].read()), 'r')
148 | user = header['ResponseMetadata']['HTTPHeaders']['x-amz-meta-userid']
149 | card_heading = header['ResponseMetadata']['HTTPHeaders']['x-amz-meta-header']
150 | image_file = header['ResponseMetadata']['HTTPHeaders']['x-amz-meta-image']
151 | dependencies = header['ResponseMetadata']['HTTPHeaders']['x-amz-meta-deps']
152 |
153 | file_payload = {'file': f,
154 | 'user': user,
155 | 'card_heading': card_heading,
156 | 'image': image_file,
157 | 'deps': dependencies}
158 |
159 | file_list.append(file_payload)
160 |
161 | return file_list
162 |
163 |
164 | def file_listings(prefix):
165 |
166 | num_files = 0
167 |
168 | example_files = s3_client.list_objects_v2(
169 | Bucket=bucket,
170 | Prefix=prefix,
171 | Delimiter='/'
172 | )['Contents']
173 |
174 | for content in example_files:
175 | if content['Size'] > 0:
176 | num_files += 1
177 |
178 | return num_files
179 |
180 |
181 | def get_example_image(prefix, image_name):
182 |
183 | image = s3_client.get_object(Bucket=bucket, Key=f'examples/{prefix}/images/{image_name}')
184 |
185 | return b64encode(image['Body'].read()).decode('utf-8')
--------------------------------------------------------------------------------
/assets/footers-light.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/pages/home.py:
--------------------------------------------------------------------------------
1 |
2 | import dash
3 | from dash import html, dcc, Output, Input, callback, State
4 | import dash_mantine_components as dmc
5 | from utils import upload_file, file_listings
6 | import base64
7 |
8 | dash.register_page(__name__, path='/', title='DMC/DBC Home')
9 |
10 | layout = html.Div([
11 | dmc.Grid(
12 | children=[
13 | dmc.GridCol([
14 | dmc.Center(
15 | style={"height": '100%'},
16 | children=[
17 | dmc.Stack([
18 | dmc.Text(
19 | "Build your next Dash application even faster with premade responsive components designed"
20 | " and built by DMC and DBC maintainers and community.",
21 | size="xl",
22 | style={'textAlign': 'center'}
23 | ),
24 | dmc.Text("Contribute Building Block", style={'textAlign': 'center'}),
25 | dmc.Group([
26 | dcc.Link(
27 | id='github-btn',
28 | href="https://github.com/Spyhuntr/dmc-dbc-building-blocks/issues/1#issue-1506988208",
29 | target='_blank',
30 | children=[
31 | dmc.Button(
32 | "Github",
33 | leftSection=html.I(
34 | className='fa-brands fa-github fa-lg fa-fw'),
35 | )
36 | ]
37 | ),
38 | dmc.Button(
39 | "Upload",
40 | id='add-building-block-btn',
41 | rightSection=html.I(className='fas fa-upload fa-lg fa-fw'),
42 | )
43 | ])
44 | ], align='center')
45 | ]
46 | )
47 | ], span=8),
48 | dmc.GridCol([
49 | dmc.Center(
50 | style={"height": '100%'},
51 | children=[
52 | dmc.Image(
53 | id='home_logo',
54 | src="/assets/home_logo.png",
55 | style={'width': 100, 'transform': 'rotate(-35deg)'}
56 | )
57 | ]
58 | )
59 | ], span=2, offset=1)
60 | ], mb='1rem'),
61 | dmc.SimpleGrid(id='card-grid', cols={"base": 1, "sm": 2, "lg": 4}, children=[]),
62 | dmc.Modal(
63 | id="upload-modal",
64 | size='xl',
65 | children=[
66 | dmc.Text("Upload a zip file of your code. The filename should include your github handle "
67 | " if you would like to get credit for your building block. "
68 | "I will get a notification when new building blocks have been submitted.",
69 | style={'textAlign': 'center'}),
70 | dmc.Space(h=10),
71 | dmc.Text("What are building blocks?",
72 | style={'textAlign': 'center'}),
73 | dmc.Text("Building blocks are small UI components that are part of an app. "
74 | "These building blocks are not a full app but rather can be added into an "
75 | "existing app to enhance the UI/UX experience of your dash application.",
76 | style={'textAlign': 'center'}),
77 | dmc.Space(h=20),
78 | dcc.Upload(
79 | id='upload',
80 | max_size=3145728,
81 | accept='.zip,.py,.css',
82 | children=html.Div([
83 | 'Drag and Drop or ',
84 | dmc.Anchor(
85 | "Select Files",
86 | href="#",
87 | ),
88 | ]),
89 | style={
90 | 'lineHeight': '60px',
91 | 'borderWidth': '1px',
92 | 'borderStyle': 'dashed',
93 | 'borderRadius': '5px',
94 | 'textAlign': 'center'
95 | },
96 | ),
97 | html.Div(id='output-upload')
98 | ])
99 | ]
100 | )
101 |
102 |
103 | @callback(Output('card-grid', 'children'),
104 | Input('card-grid', 'children'),
105 | State('card-grid', 'children'),
106 | )
107 | def create_cards(_, children):
108 |
109 | card_info = [
110 | {'image': '/assets/cards-light.svg', 'title': 'Application Cards', 'page': '/app_cards', 'prefix': 'examples/cards/'},
111 | {'image': '/assets/navbars-light.svg', 'title': 'Navbars', 'page': '/navbars', 'prefix': 'examples/navbars/'},
112 | {'image': '/assets/footers-light.svg', 'title': 'Footers', 'page': '/footers', 'prefix': 'examples/footers/'},
113 | {'image': '/assets/headers-light.svg', 'title': 'Headers', 'page': '/headers', 'prefix': 'examples/headers/'},
114 | {'image': '/assets/menus-light.svg', 'title': 'Menus', 'page': '/menus', 'prefix': 'examples/menus/'},
115 | {'image': '/assets/uploaders-light.svg', 'title': 'Uploaders / Downloaders', 'page': '/uploaders', 'prefix': 'examples/uploaders/'},
116 | {'image': '/assets/stats-light.svg', 'title': 'Stats', 'page': '/stats', 'prefix': 'examples/stats/'},
117 | {'image': '/assets/tabs-light.png', 'title': 'Tabs', 'page': '/tabs', 'prefix': 'examples/tabs/'},
118 | {'image': '/assets/auth-light.svg', 'title': 'Authentication', 'page': '/authentication', 'prefix': 'examples/auth/'},
119 | {'image': '/assets/tables.svg', 'title': 'Tables', 'page': '/tables', 'prefix': 'examples/tables/'},
120 | {'image': '/assets/carousels-light.svg', 'title': 'Carousels', 'page': '/carousels', 'prefix': 'examples/carousels/'},
121 | {'image': '/assets/buttons-light.svg', 'title': 'Buttons', 'page': '/buttons', 'prefix': 'examples/buttons/'},
122 | {'image': '/assets/leaflet-light.svg', 'title': 'Leaflet', 'page': '/leaflet', 'prefix': 'examples/leaflet/'}
123 | ]
124 |
125 | for card in card_info:
126 | card = html.Div([
127 | dmc.Paper(
128 | children=[
129 | dmc.Anchor(
130 | href=card['page'],
131 | children=[
132 | html.Div(
133 | dmc.Image(
134 | src=card['image'],
135 | ), className='card-hdr'
136 | ),
137 | dmc.Text(
138 | card['title'],
139 | pt="md",
140 | pl="md"
141 | ),
142 | dmc.Text(
143 | f"{file_listings(card['prefix'])} Components",
144 | size="xs",
145 | pl="md",
146 | pb="md",
147 | c='dimmed'
148 | )
149 | ],
150 | variant="text",
151 | style={'textDecoration': 'None'}
152 | )],
153 | shadow="xl",
154 | withBorder=True,
155 | radius="lg",
156 | style={"overflow": "hidden"}
157 | )])
158 | children.append(card)
159 |
160 | return children
161 |
162 |
163 | @callback(
164 | Output('upload-modal', 'opened'),
165 | Input('add-building-block-btn', 'n_clicks'),
166 | prevent_initial_call=True,
167 | )
168 | def open_modal(_):
169 |
170 | if _ is not None:
171 | return True
172 |
173 |
174 | @callback(Output('output-upload', 'children'),
175 | Input('upload', 'contents'),
176 | State('upload', 'filename'),
177 | State('upload', 'last_modified'),
178 | prevent_initial_call=True)
179 | def update_output(content, name, date):
180 |
181 | # the content needs to be split. It contains the type and the real content
182 | content_type, content_string = content.split(',')
183 | # Decode the base64 string
184 | content_decoded = base64.b64decode(content_string)
185 |
186 | message = upload_file(content_decoded, name, date)
187 |
188 | if message is not None:
189 | if message.status_code == 204:
190 | return dmc.Notification(
191 | id="upload-notify",
192 | action="show",
193 | message="File successfully uploaded!",
194 | icon=html.I(className='fas fa-check fa-lg fa-fw')
195 | )
196 | else:
197 | return f"{message.status_code} - {message.reason}"
--------------------------------------------------------------------------------
/assets/auth-light.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------