Skip to content

Commit d81f3ba

Browse files
authored
Add code-preview layout and web component example page (#685)
* add code-preview template and example page * add escapes * s/preview/output * add title to iframe * remove un-needed if * Use jekyll comments instead * use nick's all-charts styling * allow popups in iframe so links work
1 parent f4d3955 commit d81f3ba

File tree

6 files changed

+251
-6
lines changed

6 files changed

+251
-6
lines changed

_config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,6 @@ exclude:
4747
- vendor/gems/
4848
- vendor/ruby/
4949
- STYLE_GUIDE.md
50+
- "**/README.md"
5051

5152
include: ["CNAME"]

_layouts/code-preview.html

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
{% comment %}
2+
Displays another page inside an iframe with source code on the left and the page on the right
3+
4+
For maintainers: Set the url to display using the iframe_content_url variable in the frontmatter.
5+
{% endcomment %}
6+
7+
<!doctype html>
8+
9+
<html lang="en">
10+
<head>
11+
<title>{{ page.title | escape }} - Docs - Data Commons</title>
12+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
13+
<meta
14+
name="viewport"
15+
content="width=device-width, initial-scale=1, shrink-to-fit=no"
16+
/>
17+
<link rel="icon" href="/assets/images/favicon.png" type="image/png" />
18+
<link
19+
href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@300;400;500;700"
20+
rel="stylesheet"
21+
/>
22+
<link
23+
href="https://fonts.googleapis.com/css2?family=Google+Sans+Text:wght@300;400;500;700"
24+
rel="stylesheet"
25+
/>
26+
<link
27+
href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@600&family=Roboto&family=Material+Icons&display=swap"
28+
rel="stylesheet"
29+
/>
30+
<link href="/assets/css/styles.css" rel="stylesheet" />
31+
<link href="/assets/css/code-preview.css" rel="stylesheet" />
32+
<!-- Syntax highlighting for code -->
33+
<link
34+
rel="stylesheet"
35+
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css"
36+
/>
37+
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script>
38+
</head>
39+
<body>
40+
<div id="main">
41+
{% include header.html %}
42+
<main id="{{ main_id }}" class="container-fluid">
43+
<div id="content">
44+
<div id="source-code">
45+
<h3>Source Code</h3>
46+
<pre><code id="code-target" class="language-html">Loading source code...</code></pre>
47+
</div>
48+
<div id="preview">
49+
<h3>Output</h3>
50+
<iframe
51+
id="iframe"
52+
title="{{ page.title | escape }} Rendered Output"
53+
src="{{ page.iframe_content_url | escape}}"
54+
sandbox="allow-scripts allow-popups"
55+
></iframe>
56+
</div>
57+
</div>
58+
</main>
59+
{% include footer.html %}
60+
</div>
61+
<script>
62+
// Fetch the source code for the page and display it in the source code
63+
// div.
64+
const fileUrl = "{{ page.iframe_content_url | escape }}";
65+
fetch(fileUrl)
66+
.then((response) => {
67+
if (!response.ok) throw new Error("Network response was not ok");
68+
return response.text();
69+
})
70+
.then((data) => {
71+
// Escape the HTML so it doesn't render as actual elements
72+
const codeTarget = document.getElementById("code-target");
73+
codeTarget.textContent = data;
74+
Prism.highlightElement(codeTarget);
75+
})
76+
.catch((err) => {
77+
document.getElementById("code-target").textContent =
78+
"Error loading source: " + err.message;
79+
});
80+
</script>
81+
{% include scripts.html %}
82+
</body>
83+
</html>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Web Components Examples
2+
3+
This directory contains the pages that render the side-by-side source code and rendered output for the Data Commons web components examples.
4+
5+
## How the examples are rendered
6+
7+
The examples are rendered into the `code-preview` layout in `/_layouts/code-preview.html`.
8+
9+
A `<script>` tag in the layout pulls the the raw HTML source of the file specified in the `iframe_content_url` frontmatter property and displays it in a `<code>` block. It then applies syntax highlighting to the code via [Prism.js](https://prismjs.com/).
10+
11+
The right-side live-render is an iframe that loads the same file.
12+
13+
## How to add a new example
14+
15+
1. Add a new HTML file to the assets/examples/web-components/ directory containing the full HTML for the example.
16+
2. Create a new markdown file in this directory that uses the code-preview layout.
17+
3. Add frontmatter to the new file following this template:
18+
19+
```yaml
20+
---
21+
layout: code-preview
22+
title: Web components example - [SOME DESCRIPTIVE NAME HERE]
23+
published: true
24+
nav_exclude: true # This keeps the page from showing up in the left navigation
25+
iframe_content_url: /assets/examples/web-components/[FILENAME].html
26+
---
27+
```
28+
29+
The `iframe_content_url` should point to the HTML file you created in step 1.
30+
31+
4. Finally, you can link to the new example using the path `/api/web_components/examples/[FILENAME].html`
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
layout: code-preview
3+
title: All Charts
4+
parent: All Charts - Web Components Example
5+
published: true
6+
nav_exclude: true
7+
iframe_content_url: /assets/examples/web-components/all-charts.html
8+
---

assets/css/code-preview.scss

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
---
2+
---
3+
4+
/**
5+
* Copyright 2026 Google LLC
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
/**
21+
* CSS for the code-preview layout (e.g., /api/web_components/examples/all-charts.html)
22+
*/
23+
24+
html,
25+
body {
26+
height: 100vh;
27+
}
28+
29+
#main {
30+
display: flex;
31+
flex-direction: column;
32+
height: 100%;
33+
34+
> main {
35+
flex-grow: 1;
36+
display: flex;
37+
flex-direction: column;
38+
min-height: 0;
39+
padding: 0;
40+
}
41+
}
42+
43+
header,
44+
footer {
45+
flex-shrink: 0;
46+
}
47+
48+
#content {
49+
flex-grow: 1;
50+
margin: 0;
51+
min-height: 0;
52+
display: flex;
53+
overflow: hidden;
54+
55+
/* On smaller screens, show source code and preview top to bottom */
56+
@media (max-width: 1024px) {
57+
flex-direction: column;
58+
}
59+
}
60+
61+
#preview,
62+
#source-code {
63+
width: 50%;
64+
height: 100%;
65+
display: flex;
66+
flex-direction: column;
67+
overflow: hidden;
68+
69+
h3 {
70+
margin: 0;
71+
padding: 10px;
72+
background: #fafcff;
73+
border-top: 1px solid #dee2e6;
74+
border-bottom: 1px solid #dee2e6;
75+
flex-shrink: 0;
76+
font-size: 1rem;
77+
font-weight: 500;
78+
}
79+
80+
/* On smaller screens, show source code and preview top to bottom */
81+
@media (max-width: 1024px) {
82+
width: 100%;
83+
height: 50%;
84+
min-height: 0;
85+
}
86+
}
87+
88+
#preview {
89+
iframe {
90+
border: none;
91+
width: 100%;
92+
flex-grow: 1;
93+
min-height: 0;
94+
}
95+
}
96+
97+
#source-code {
98+
pre {
99+
margin: 0;
100+
flex-grow: 1;
101+
overflow: auto;
102+
min-height: 0;
103+
padding: 10px;
104+
}
105+
}
106+
107+
#code-target {
108+
/* Reset specific height/overflow as pre handles it now */
109+
height: auto;
110+
overflow: visible;
111+
}

assets/examples/web-components/all-charts.html

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
stroke-dasharray: unset;
1919
}
2020
#styled-bar-multivariable::part(
21-
series-place-geoId\/20-variable-Median_Income_Person_15OrMoreYears_Male_WithIncome
22-
) {
21+
series-place-geoId\/20-variable-Median_Income_Person_15OrMoreYears_Male_WithIncome
22+
) {
2323
fill: green;
2424
}
2525
#styled-map::part(container) {
2626
border-radius: 10px;
2727
border: 1px solid #f5f5f5;
28-
box-shadow: 1px 2px 6px rgba(3, 7, 18, 0.04),
28+
box-shadow:
29+
1px 2px 6px rgba(3, 7, 18, 0.04),
2930
5px 8px 25px rgba(3, 7, 18, 0.08);
3031
}
3132
#styled-map::part(legend) {
@@ -71,7 +72,16 @@
7172
}
7273
</style>
7374
</head>
74-
<body style="max-width: 40vw; margin: auto">
75+
<body
76+
style="
77+
box-sizing: border-box;
78+
max-width: 900px;
79+
width: 100%;
80+
overflow-x: hidden;
81+
padding: 0 64px;
82+
margin: 0 auto;
83+
"
84+
>
7585
<h1>Datacommons Web Components</h1>
7686
<h2>Bar Chart</h2>
7787
<datacommons-bar
@@ -333,15 +343,16 @@ <h2>Map with year slider</h2>
333343
header="Poverty rate by country (${date})"
334344
parentPlace="Earth"
335345
subscribe="dc-map-2"
336-
variable="sdg/SI_POV_DAY1">
346+
variable="sdg/SI_POV_DAY1"
347+
>
337348
<div slot="footer">
338349
<datacommons-slider
339350
childPlaceType="Country"
340351
date="HIGHEST_COVERAGE"
341352
parentPlace="Earth"
342353
publish="dc-map-2"
343354
variable="sdg/SI_POV_DAY1"
344-
>
355+
>
345356
</datacommons-slider>
346357
</div>
347358
</datacommons-map>

0 commit comments

Comments
 (0)