Skip to content

Commit 3cd64c9

Browse files
MaxGhenisclaudeCopilot
authored
Add sleep state notice to embedded Streamlit apps (#2775)
* Add sleep state notice to embedded Streamlit apps This PR addresses the issue where users cannot wake up sleeping Streamlit apps when they are embedded in iframes. The changes include: - Created a reusable StreamlitEmbed component with a dismissible alert - The alert informs users that if the app is sleeping, they should visit the direct Streamlit link to wake it up - Updated all 9 Streamlit embed pages to use this new component: - ACA Calculator - GiveCalc - Child Tax Credit Calculator - Citizens Economic Council - State EITCs and CTCs - Child Tax Credit Comparison - TRAFWA Calculator - 2024 Election Calculator - UK 2024 Manifestos Comparison The component maintains all existing functionality including responsive sizing for some apps and fixed dimensions for others. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Make sleep notice conditional based on loading time Improves the user experience by: - Only showing the alert if the iframe takes more than 8 seconds to load (suggesting the app might be sleeping) - Using sessionStorage to remember if the user dismissed the alert - Hiding the alert automatically if the iframe loads quickly - Adding iframe load detection with useRef This reduces unnecessary alerts when apps are already awake while still helping users when apps are actually sleeping. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Simplify to always show notice with session dismissal Based on research, there's no reliable way to detect Streamlit sleep state from the parent page due to: - CORS restrictions prevent inspecting iframe content - Sleep pages load instantly (same speed as active apps) - postMessage would require modifying the Streamlit apps themselves - "Unable to wake up when embedded" is a known Streamlit community issue This simpler approach: - Shows the notice by default (more honest about the limitation) - Remembers dismissal in sessionStorage (won't nag during same session) - Much simpler code without fragile timing heuristics - Documents the CORS limitation in code comments 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Make sleep notice more subtle Replaced the prominent Alert component with a minimal banner: - Thin gray bar with subtle border - Smaller text (13px) - Concise message: "If the app is sleeping, visit it directly to wake it up" - Simple × button to close - Much less visually intrusive - No bold "App Sleep Notice" header This provides the information users need without being obtrusive. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Replace link with subtle button for better UX Changes: - Message now reads: "If the app is sleeping: [Wake it up]" - "Wake it up" is a small, subtle button instead of linked text - Button has light border and background (#ffffff on #f0f2f5) - Hover effect: border and text turn blue (#1890ff) - More actionable and clearer than inline link text - Better visual hierarchy with flexbox gap spacing The button is still subtle but makes the action more obvious. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix typo: Houshold → Household Co-Authored-By: Copilot <copilot@github.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot <copilot@github.com>
1 parent 4768c0f commit 3cd64c9

11 files changed

+218
-237
lines changed

changelog_entry.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
- bump: patch
22
changes:
33
added:
4-
- Added blog post comparing PolicyEngine and official UK poverty rates
4+
- Add sleep state notice to all embedded Streamlit apps, instructing users to visit the direct link if the app is sleeping

src/applets/ACACalc.jsx

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,12 @@
1-
import Header from "../layout/Header";
2-
import { Helmet } from "react-helmet";
3-
import style from "../style";
4-
import { useWindowHeight } from "../hooks/useWindow";
1+
import StreamlitEmbed from "./StreamlitEmbed";
52

63
export default function ACACalc() {
7-
const windowHeight = useWindowHeight();
8-
94
return (
10-
<>
11-
<Helmet>
12-
<title>ACA-Calc | PolicyEngine</title>
13-
</Helmet>
14-
<Header />
15-
<div
16-
style={{
17-
display: "flex",
18-
justifyContent: "center",
19-
height: windowHeight - style.spacing.HEADER_HEIGHT,
20-
width: "100vw",
21-
}}
22-
>
23-
<iframe
24-
src="https://policyengine-aca-calc.streamlit.app?embedded=true"
25-
title="ACA-Calc"
26-
height={`calc(100vh - ${style.spacing.HEADER_HEIGHT})`}
27-
width="100%"
28-
style={{ overflow: "hidden" }}
29-
/>
30-
</div>
31-
</>
5+
<StreamlitEmbed
6+
embedUrl="https://policyengine-aca-calc.streamlit.app?embedded=true"
7+
directUrl="https://policyengine-aca-calc.streamlit.app"
8+
title="ACA-Calc"
9+
iframeTitle="ACA-Calc"
10+
/>
3211
);
3312
}

src/applets/CTCCalculator.jsx

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,12 @@
1-
import Header from "../layout/Header";
2-
import { Helmet } from "react-helmet";
3-
import style from "../style";
4-
import { useWindowHeight } from "../hooks/useWindow";
1+
import StreamlitEmbed from "./StreamlitEmbed";
52

63
export default function CTCCalculator() {
7-
const windowHeight = useWindowHeight();
8-
94
return (
10-
<>
11-
<Helmet>
12-
<title>Child tax credit calculator | PolicyEngine</title>
13-
</Helmet>
14-
<Header />
15-
<div
16-
style={{
17-
display: "flex",
18-
justifyContent: "center",
19-
height: windowHeight - style.spacing.HEADER_HEIGHT,
20-
width: "100vw",
21-
}}
22-
>
23-
<iframe
24-
src="https://ctc-calculator.streamlit.app?embedded=true"
25-
title="Child tax credit calculator"
26-
height={`calc(100vh - ${style.spacing.HEADER_HEIGHT})`}
27-
width="100%"
28-
style={{ overflow: "hidden" }}
29-
/>
30-
</div>
31-
</>
5+
<StreamlitEmbed
6+
embedUrl="https://ctc-calculator.streamlit.app?embedded=true"
7+
directUrl="https://ctc-calculator.streamlit.app"
8+
title="Child tax credit calculator"
9+
iframeTitle="Child tax credit calculator"
10+
/>
3211
);
3312
}

src/applets/CTCComparison.jsx

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,12 @@
1-
import Header from "../layout/Header";
2-
import { Helmet } from "react-helmet";
3-
import style from "../style";
4-
import { useWindowHeight } from "../hooks/useWindow";
1+
import StreamlitEmbed from "./StreamlitEmbed";
52

63
export default function CTCComparison() {
7-
const windowHeight = useWindowHeight();
8-
94
return (
10-
<>
11-
<Helmet>
12-
<title>Child tax credit calculator | PolicyEngine</title>
13-
</Helmet>
14-
<Header />
15-
<div
16-
style={{
17-
display: "flex",
18-
justifyContent: "center",
19-
height: windowHeight - style.spacing.HEADER_HEIGHT,
20-
width: "100vw",
21-
}}
22-
>
23-
<iframe
24-
src="https://vance-harris-ctc-comparison.streamlit.app?embedded=true"
25-
title="Child tax credit calculator"
26-
height={`calc(100vh - ${style.spacing.HEADER_HEIGHT})`}
27-
width="100%"
28-
style={{ overflow: "hidden" }}
29-
/>
30-
</div>
31-
</>
5+
<StreamlitEmbed
6+
embedUrl="https://vance-harris-ctc-comparison.streamlit.app?embedded=true"
7+
directUrl="https://vance-harris-ctc-comparison.streamlit.app"
8+
title="Child tax credit calculator"
9+
iframeTitle="Child tax credit calculator"
10+
/>
3211
);
3312
}
Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,14 @@
1-
import Header from "../layout/Header";
2-
import { Helmet } from "react-helmet";
1+
import StreamlitEmbed from "./StreamlitEmbed";
32

43
export default function CitizensEconomicCouncil() {
5-
// Update the title to be "CEC reform simulator | PolicyEngine")
6-
74
return (
8-
<>
9-
<Helmet>
10-
<title>CEC reform simulator | PolicyEngine</title>
11-
</Helmet>
12-
<Header />
13-
<div
14-
style={{
15-
display: "flex",
16-
justifyContent: "center",
17-
}}
18-
>
19-
<iframe
20-
src="https://policyengine-cec-simulator.streamlit.app?embedded=true"
21-
title="Citizens' Economic Council reform simulator"
22-
height="800"
23-
width="800"
24-
style={{ overflow: "hidden" }}
25-
/>
26-
</div>
27-
</>
5+
<StreamlitEmbed
6+
embedUrl="https://policyengine-cec-simulator.streamlit.app?embedded=true"
7+
directUrl="https://policyengine-cec-simulator.streamlit.app"
8+
title="CEC reform simulator"
9+
iframeTitle="Citizens' Economic Council reform simulator"
10+
height="800"
11+
width="800"
12+
/>
2813
);
2914
}

src/applets/GiveCalc.jsx

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,12 @@
1-
import Header from "../layout/Header";
2-
import { Helmet } from "react-helmet";
3-
import style from "../style";
4-
import { useWindowHeight } from "../hooks/useWindow";
1+
import StreamlitEmbed from "./StreamlitEmbed";
52

63
export default function GiveCalc() {
7-
const windowHeight = useWindowHeight();
8-
94
return (
10-
<>
11-
<Helmet>
12-
<title>GiveCalc | PolicyEngine</title>
13-
</Helmet>
14-
<Header />
15-
<div
16-
style={{
17-
display: "flex",
18-
justifyContent: "center",
19-
height: windowHeight - style.spacing.HEADER_HEIGHT,
20-
width: "100vw",
21-
}}
22-
>
23-
<iframe
24-
src="https://givecalc.streamlit.app?embedded=true"
25-
title="GiveCalc"
26-
height={`calc(100vh - ${style.spacing.HEADER_HEIGHT})`}
27-
width="100%"
28-
style={{ overflow: "hidden" }}
29-
/>
30-
</div>
31-
</>
5+
<StreamlitEmbed
6+
embedUrl="https://givecalc.streamlit.app?embedded=true"
7+
directUrl="https://givecalc.streamlit.app"
8+
title="GiveCalc"
9+
iframeTitle="GiveCalc"
10+
/>
3211
);
3312
}
Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,12 @@
1-
import Header from "../layout/Header";
2-
import { Helmet } from "react-helmet";
3-
import style from "../style";
4-
import { useWindowHeight } from "../hooks/useWindow";
1+
import StreamlitEmbed from "./StreamlitEmbed";
52

63
export default function ManifestosComparison() {
7-
const windowHeight = useWindowHeight();
8-
94
return (
10-
<>
11-
<Helmet>
12-
<title>UK 2024 Manifestos Comparison | PolicyEngine</title>
13-
</Helmet>
14-
<Header />
15-
<div
16-
style={{
17-
display: "flex",
18-
justifyContent: "center",
19-
height: windowHeight - style.spacing.HEADER_HEIGHT,
20-
width: "100vw",
21-
}}
22-
>
23-
<iframe
24-
src="https://manifestos.streamlit.app?embedded=true"
25-
title="UK 2024 Manifestos Comparison"
26-
height={`calc(100vh - ${style.spacing.HEADER_HEIGHT})`}
27-
width="100%"
28-
style={{ overflow: "hidden" }}
29-
/>
30-
</div>
31-
</>
5+
<StreamlitEmbed
6+
embedUrl="https://manifestos.streamlit.app?embedded=true"
7+
directUrl="https://manifestos.streamlit.app"
8+
title="UK 2024 Manifestos Comparison"
9+
iframeTitle="UK 2024 Manifestos Comparison"
10+
/>
3211
);
3312
}

src/applets/StateEitcsCtcs.jsx

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,14 @@
1-
import Header from "../layout/Header";
2-
import { Helmet } from "react-helmet";
1+
import StreamlitEmbed from "./StreamlitEmbed";
32

43
export default function StateEitcsCtcs() {
54
return (
6-
<>
7-
<Helmet>
8-
<title>State EITCs and CTCs | PolicyEngine</title>
9-
</Helmet>
10-
<Header />
11-
<div
12-
style={{
13-
display: "flex",
14-
justifyContent: "center",
15-
}}
16-
>
17-
<iframe
18-
src="https://us-state-eitcs-ctcs.streamlit.app?embedded=true"
19-
title="State EITCs and CTCs"
20-
height="800"
21-
width="1000"
22-
style={{ overflow: "hidden" }}
23-
/>
24-
</div>
25-
</>
5+
<StreamlitEmbed
6+
embedUrl="https://us-state-eitcs-ctcs.streamlit.app?embedded=true"
7+
directUrl="https://us-state-eitcs-ctcs.streamlit.app"
8+
title="State EITCs and CTCs"
9+
iframeTitle="State EITCs and CTCs"
10+
height="800"
11+
width="1000"
12+
/>
2613
);
2714
}

0 commit comments

Comments
 (0)