Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions svelte/core-v2/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,11 @@
flex-direction: row;
column-gap: 0.25em;
align-items: center;

@media (max-width: 800px) {
flex-direction: column;
row-gap: 0.5rem;
margin:0 1em;
}
}
</style>
16 changes: 16 additions & 0 deletions svelte/core-v2/src/lib/Arrow.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,21 @@
opacity: 0;
}
}

@media (max-width: 800px) {
flex-direction: column;
align-items: center;
margin: 0.5rem 0;

span:last-child {
transform: rotate(90deg);
display: inline-block; /* transform requires block/inline-block */
}

.text {
width: auto; /* Allow text to be visible if needed or keep existing logic */
text-align: center;
}
}
}
</style>
30 changes: 22 additions & 8 deletions svelte/core-v2/src/lib/Column.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,18 @@
<style lang="scss">
section {
display: flex;
width:100%;
flex-direction: column;
background-color: black; /* default; this may be overridden per instance */
border: 2px solid black; /* default; this may be overridden per instance */
border-radius: 1rem;
overflow: hidden;
width:18rem;
width: 18rem;
transition: var(--default-transition);

@media (max-width: 800px) {
width: 100%;
}

.heading {
display: block;
margin: 0;
Expand All @@ -52,14 +55,20 @@
background-color: var(--color-background);
display: flex;
flex-direction: column;
padding-bottom:.25rem;
padding-bottom: 0.25rem;
}
}
section.capabilities {

&.detail {
width:35rem;
width: 35rem;
}

@media (max-width: 800px) {
&.detail {
width: 100%;
}
}

background-color: var(--color-capabilities);
border-color: var(--color-capabilities);

Expand All @@ -69,7 +78,10 @@
}
section.performance {
&.detail {
width:22.25rem;
width: 22.25rem;
@media (max-width: 800px) {
width: 100%;
}
}
background-color: var(--color-performance);
border-color: var(--color-performance);
Expand All @@ -78,9 +90,11 @@
}
}
section.outcomes {

&.detail {
width:21rem;
width: 21rem;
@media (max-width: 800px) {
width: 100%;
}
}

background-color: var(--color-outcomes);
Expand Down
34 changes: 23 additions & 11 deletions svelte/core-v2/src/lib/ViewControl.svelte
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
<script>
import { onMount } from 'svelte';
import { onMount } from "svelte";

export let view_mode = "summary";

// Function to update view_mode based on URL query parameter
const updateViewModeFromQuery = () => {
const urlParams = new URLSearchParams(window.location.search);
const mode = urlParams.get('view');
view_mode = mode === 'detail' ? 'detail' : 'summary';
const mode = urlParams.get("view");
view_mode = mode === "detail" ? "detail" : "summary";
};

// Function to update URL query parameter based on view_mode
const updateUrlQuery = () => {
const urlParams = new URLSearchParams(window.location.search);
urlParams.set('view', view_mode);
window.history.replaceState({}, '', `${window.location.pathname}?${urlParams.toString()}`);
urlParams.set("view", view_mode);
window.history.replaceState(
{},
"",
`${window.location.pathname}?${urlParams.toString()}`,
);
};

onMount(() => {
updateViewModeFromQuery();
window.addEventListener('popstate', updateViewModeFromQuery); // Handle back/forward
window.addEventListener("popstate", updateViewModeFromQuery); // Handle back/forward
return () => {
window.removeEventListener('popstate', updateViewModeFromQuery);
window.removeEventListener("popstate", updateViewModeFromQuery);
};
});
</script>

<div class="viewcontrol">
View mode:
<label for="summary" class:active={view_mode === 'summary'}>
<label for="summary" class:active={view_mode === "summary"}>
<input
type="radio"
name="view_mode"
Expand All @@ -38,7 +42,7 @@
on:change={updateUrlQuery}
/>summary
</label>
<label for="detail" class:active={view_mode === 'detail'}>
<label for="detail" class:active={view_mode === "detail"}>
<input
type="radio"
name="view_mode"
Expand All @@ -52,14 +56,22 @@

<style lang="scss">
.viewcontrol {
text-align: right;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 0.5rem;
flex-wrap: wrap;

label {
border: 1px solid var(--color-grey-light);
padding: 0.5em;
border-radius: 0.5em;
display: flex;
align-items: center;
white-space: nowrap;

input[type="radio"] {
margin-right:.25em;
margin-right: 0.25em;
}
}
}
Expand Down
28 changes: 28 additions & 0 deletions test/playwright/tests/research/core.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,31 @@ test('core capabilities exclusion', async ({ page }) => {
await expect(page.locator('#entityPopover h1')).toHaveText('Climate for learning');
await expect(page.getByRole('link', { name: 'Learn more about climate for learning' })).toBeHidden();
});

test('mobile layout stacking', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 812 }); // iPhone 12 width
await page.goto(url);

// Wait for the core model to load
await expect(page.locator('.coremodel')).toBeVisible();

const capabilities = page.locator('section.capabilities');
const performance = page.locator('section.performance');
const outcomes = page.locator('section.outcomes');

await expect(capabilities).toBeVisible();
await expect(performance).toBeVisible();
await expect(outcomes).toBeVisible();

const capabilitiesBox = await capabilities.boundingBox();
const performanceBox = await performance.boundingBox();
const outcomesBox = await outcomes.boundingBox();

// Verify vertical stacking: capabilities above performance above outcomes
expect(capabilitiesBox!.y + capabilitiesBox!.height).toBeLessThan(performanceBox!.y);
expect(performanceBox!.y + performanceBox!.height).toBeLessThan(outcomesBox!.y);

// Verify they are roughly the same x-coordinate (stacked)
expect(Math.abs(capabilitiesBox!.x - performanceBox!.x)).toBeLessThan(20);
expect(Math.abs(capabilitiesBox!.x - outcomesBox!.x)).toBeLessThan(20);
});