-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: APPS-2946 Create Two Column Layout component (#614)
* feat: begin sidebar structure, start drawio docs * feat: more progress side * feat: progress on 2col, stories * chore: finish stories, tests * chore: cleanup, documentation * fix: double padding * fix: inconsistent spacing when card-meta is above sidebar --------- Co-authored-by: Jess Divers <[email protected]>
- Loading branch information
1 parent
e9f40c4
commit cc5d52d
Showing
6 changed files
with
511 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
<mxfile host="65bd71144e"> | ||
<diagram id="k3MkfsP0TAj-Hgy-79KS" name="Page-1"> | ||
<mxGraphModel dx="650" dy="1500" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> | ||
<root> | ||
<mxCell id="0"/> | ||
<mxCell id="1" parent="0"/> | ||
<mxCell id="2" value="" style="whiteSpace=wrap;html=1;aspect=fixed;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1"> | ||
<mxGeometry x="20" y="10" width="380" height="380" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="3" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#ae4132;dashed=1;strokeWidth=3;" vertex="1" parent="1"> | ||
<mxGeometry x="30" y="20" width="220" height="360" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="9" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1"> | ||
<mxGeometry x="440" y="10" width="160" height="610" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="10" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fad9d5;strokeColor=#ae4132;" vertex="1" parent="1"> | ||
<mxGeometry x="450" y="20" width="140" height="90" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="11" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b0e3e6;strokeColor=#0e8088;" vertex="1" parent="1"> | ||
<mxGeometry x="450" y="120" width="140" height="90" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="12" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fad9d5;strokeColor=#ae4132;" vertex="1" parent="1"> | ||
<mxGeometry x="450" y="220" width="140" height="120" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="14" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=none;strokeWidth=3;dashed=1;strokeColor=#004C99;" vertex="1" parent="1"> | ||
<mxGeometry x="260" y="20" width="130" height="360" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="18" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;strokeColor=#000033;startArrow=none;" edge="1" parent="1" source="20"> | ||
<mxGeometry relative="1" as="geometry"> | ||
<mxPoint x="210" y="190" as="sourcePoint"/> | ||
<mxPoint x="325" y="370" as="targetPoint"/> | ||
<Array as="points"> | ||
<mxPoint x="325" y="270"/> | ||
</Array> | ||
</mxGeometry> | ||
</mxCell> | ||
<mxCell id="21" value="" style="endArrow=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;strokeColor=#000033;" edge="1" parent="1" source="4" target="20"> | ||
<mxGeometry relative="1" as="geometry"> | ||
<mxPoint x="325" y="150" as="sourcePoint"/> | ||
<mxPoint x="325" y="380" as="targetPoint"/> | ||
<Array as="points"/> | ||
</mxGeometry> | ||
</mxCell> | ||
<mxCell id="20" value="Sticky" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=#FFF9CF;strokeWidth=4;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="295" y="220" width="60" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="24" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"> | ||
<mxGeometry x="450" y="350" width="140" height="90" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="28" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1"> | ||
<mxGeometry x="30" y="20" width="220" height="70" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="29" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1"> | ||
<mxGeometry x="30" y="140" width="220" height="120" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="31" value="" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;labelBackgroundColor=none;strokeColor=#FF8000;strokeWidth=2;fontColor=#050505;fillColor=none;" vertex="1" parent="1"> | ||
<mxGeometry x="40" y="100" width="200" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="32" value="slot: primaryTop&nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="50" y="40" width="190" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="36" value="" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;labelBackgroundColor=none;strokeColor=#FF8000;strokeWidth=2;fontColor=#050505;fillColor=none;" vertex="1" parent="1"> | ||
<mxGeometry x="450" y="120" width="140" height="90" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="39" value="" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;labelBackgroundColor=none;strokeColor=#FF8000;strokeWidth=2;fontColor=#050505;fillColor=none;" vertex="1" parent="1"> | ||
<mxGeometry x="450" y="350" width="140" height="90" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="47" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=none;strokeWidth=3;dashed=1;strokeColor=#00CCCC;" vertex="1" parent="1"> | ||
<mxGeometry x="260" y="19" width="130" height="185" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="44" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#ae4132;dashed=1;strokeWidth=3;movable=0;resizable=0;rotatable=0;deletable=0;editable=0;connectable=0;" vertex="1" parent="1"> | ||
<mxGeometry x="450" y="20" width="140" height="590" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="4" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b0e3e6;strokeColor=#0e8088;" vertex="1" parent="1"> | ||
<mxGeometry x="260" y="20" width="130" height="70" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="23" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"> | ||
<mxGeometry x="260" y="100" width="130" height="100" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="49" value="SMALL SCREENS" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=#FFFFFF;strokeWidth=2;fontSize=13;fontColor=#000033;" vertex="1" parent="1"> | ||
<mxGeometry x="430" y="-40" width="120" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="66" value="slot: sidebarTop (mobile only)&nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="50" y="100" width="190" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="68" value="slot: primaryMid&nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="50" y="185" width="190" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="69" value="" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;labelBackgroundColor=none;strokeColor=#FF8000;strokeWidth=2;fontColor=#050505;fillColor=none;" vertex="1" parent="1"> | ||
<mxGeometry x="40" y="273" width="200" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="70" value="slot: sidebarBottom (mobile only)&nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="50" y="273" width="190" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="71" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1"> | ||
<mxGeometry x="30" y="310" width="220" height="70" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="72" value="slot: primaryBottom&nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="50" y="330" width="190" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="73" value="slot: sidebarTop (desktop only)&nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="260" y="40" width="120" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="74" value="slot: sidebarBottom (desktop only)&nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="265" y="140" width="120" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="75" value="XLARGE / LARGE / MEDIUM SCREENS" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=#FFFFFF;strokeWidth=2;fontSize=13;fontColor=#000033;" vertex="1" parent="1"> | ||
<mxGeometry x="10" y="-40" width="270" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="76" value="slot: primaryTop&nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="450" y="50" width="140" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="77" value="slot: primaryMid&nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="450" y="260" width="140" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="78" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fad9d5;strokeColor=#ae4132;" vertex="1" parent="1"> | ||
<mxGeometry x="450" y="450" width="140" height="120" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="79" value="slot: primaryBottom" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="450" y="490" width="140" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="80" value="slot: sidebarTop&nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="460" y="150" width="120" height="30" as="geometry"/> | ||
</mxCell> | ||
<mxCell id="81" value="slot: sidebarBottom&nbsp;&nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;labelBackgroundColor=none;strokeWidth=2;fontColor=#050505;" vertex="1" parent="1"> | ||
<mxGeometry x="461" y="380" width="120" height="30" as="geometry"/> | ||
</mxCell> | ||
</root> | ||
</mxGraphModel> | ||
</diagram> | ||
</mxfile> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
<script lang="ts" setup> | ||
import { onMounted, ref, watch } from 'vue' | ||
import type { Ref } from 'vue' | ||
import { useWindowSize } from '@vueuse/core' | ||
import SectionWrapper from '@/lib-components/SectionWrapper.vue' | ||
// Track height of sidebar and ensure main content as at least as tall | ||
const isMobile: Ref<boolean> = ref(false) | ||
const sidebar: Ref<HTMLDivElement | null> = ref(null) | ||
const primaryCol: Ref<HTMLDivElement | null> = ref(null) | ||
function setMainMinHeight() { | ||
primaryCol.value!.style!.minHeight = `${sidebar.value!.clientHeight + 125}px` // add 125 px to account for top and bottom padding | ||
} | ||
onMounted(() => { | ||
const { width } = useWindowSize() | ||
watch([width, sidebar], ([newWidth]) => { | ||
isMobile.value = newWidth <= 750 | ||
if (isMobile.value === true) | ||
primaryCol.value!.style!.minHeight = 'auto' // on mobile, reset height | ||
else | ||
setMainMinHeight() | ||
}, { immediate: true }) | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div class="two-column"> | ||
<!-- main column --> | ||
<div | ||
ref="primaryCol" | ||
class="primary-column top" | ||
> | ||
<SectionWrapper class="primary-section-wrapper"> | ||
<slot name="primaryTop" /> | ||
<div v-if="isMobile" class="sidebar-mobile-top"> | ||
<slot name="sidebarTop" /> | ||
</div> | ||
<slot name="primaryMid" /> | ||
<div v-if="isMobile" class="sidebar-mobile-bottom"> | ||
<slot name="sidebarBottom" /> | ||
</div> | ||
<slot name="primaryBottom" /> | ||
</SectionWrapper> | ||
</div> | ||
|
||
<!-- sidebar column --> | ||
<div class="sidebar-column"> | ||
<div | ||
ref="sidebar" | ||
class="sidebar-content-wrapper" | ||
> | ||
<slot v-if="!isMobile" name="sidebarTop" /> | ||
<slot v-if="!isMobile" name="sidebarBottom" /> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<style lang="scss" scoped> | ||
.two-column { | ||
position: relative; | ||
width: 100%; | ||
max-width: var(--ftva-container-max-width); | ||
display: flex; | ||
flex-direction: row; | ||
flex-wrap: wrap; | ||
.primary-column { | ||
margin-bottom: 0px; | ||
width: 67%; | ||
.primary-section-wrapper { | ||
padding-left: 0px; | ||
margin: var(--space-2xl) auto; | ||
padding: 0 var(--unit-gutter); | ||
} | ||
} | ||
.sidebar-column { | ||
min-width: 314px; | ||
width: 30%; | ||
position: absolute; | ||
height: 100%; | ||
top: 0; | ||
right: 0; | ||
padding-top: var(--space-2xl); | ||
padding-bottom: 40px; | ||
padding-right: var(--unit-gutter); | ||
.sidebar-content-wrapper { | ||
position: sticky; | ||
top: 85px; | ||
will-change: top; | ||
>* { | ||
margin-bottom: 30px; | ||
&:last-child { | ||
margin-bottom: 48px; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
// MEDIUM DEVICE STYLES | ||
@media (max-width: 1200px) { | ||
.two-column { | ||
padding-right: var(--unit-gutter); | ||
} | ||
.two-column>.primary-column { | ||
width: 62%; | ||
} | ||
} | ||
// MOBILE STYLES | ||
@media #{$small} { | ||
.two-column { | ||
display: grid; | ||
grid-template-columns: 1fr; | ||
.primary-column { | ||
width: auto; | ||
grid-column: 1; | ||
.primary-section-wrapper { | ||
padding-left: var(--unit-gutter); | ||
// Cardmeta divs have a bottom-margin, but the last one doesn't always display if content is overflowing. | ||
// We remove the margin from the last card-meta div to ensure it displays consistently, and re-add the spacing below | ||
:deep(.card-meta) { | ||
div:last-child { | ||
margin-bottom: 0px; | ||
} | ||
} | ||
} | ||
.sidebar-mobile-top { | ||
padding-top: var(--space-l); // add padding to top of sidebar | ||
} | ||
.sidebar-mobile-top, .sidebar-mobile-bottom { | ||
> * { | ||
margin-bottom: 30px; | ||
} | ||
} | ||
} | ||
.sidebar-column { | ||
display: none; | ||
} | ||
} | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
describe('LAYOUT / Two Columns W Sticky Sidebar', () => { | ||
it('Default', () => { | ||
cy.visit( | ||
'/iframe.html?id=layout-2-column-layout-with-sticky-sidebar--event-series' | ||
) | ||
cy.get('.two-column').should('exist') | ||
|
||
cy.percySnapshot('LAYOUT / Two Columns W Sticky Sidebar: Event Series') | ||
}) | ||
}) |
Oops, something went wrong.
cc5d52d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉 Published on https://ucla-library-storybook.netlify.app as production
🚀 Deployed on https://66f20cc39968794ddd192add--ucla-library-storybook.netlify.app