Skip to content

Commit 6589d07

Browse files
committed
feat(Offcanvas): add responsive variations
1 parent c87ee00 commit 6589d07

File tree

3 files changed

+194
-1
lines changed

3 files changed

+194
-1
lines changed

packages/coreui-vue/src/components/offcanvas/COffcanvas.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ const COffcanvas = defineComponent({
4646
return ['start', 'end', 'top', 'bottom'].includes(value)
4747
},
4848
},
49+
/**
50+
* Responsive offcanvas property hide content outside the viewport from a specified breakpoint and down.
51+
*
52+
* @values boolean | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'
53+
*/
54+
responsive: {
55+
type: [Boolean, String],
56+
default: true,
57+
validator: (value: boolean | string) => {
58+
if (typeof value === 'string') {
59+
return ['sm', 'md', 'lg', 'xl', 'xxl'].includes(value)
60+
}
61+
if (typeof value === 'boolean') {
62+
return true
63+
}
64+
return false
65+
},
66+
},
4967
/**
5068
* Allow body scrolling while offcanvas is open
5169
*/
@@ -101,13 +119,16 @@ const COffcanvas = defineComponent({
101119
el.classList.add('show')
102120
}, 1)
103121
}
122+
104123
const handleAfterEnter = () => {
105124
offcanvasRef.value.focus()
106125
}
126+
107127
const handleLeave = (el: RendererElement, done: () => void) => {
108128
executeAfterTransition(() => done(), el as HTMLElement)
109129
el.classList.add('hiding')
110130
}
131+
111132
const handleAfterLeave = (el: RendererElement) => {
112133
el.classList.remove('show', 'hiding')
113134
}
@@ -146,8 +167,10 @@ const COffcanvas = defineComponent({
146167
'div',
147168
{
148169
class: [
149-
'offcanvas',
150170
{
171+
[`offcanvas${
172+
typeof props.responsive !== 'boolean' ? '-' + props.responsive : ''
173+
}`]: props.responsive,
151174
[`offcanvas-${props.placement}`]: props.placement,
152175
},
153176
],

packages/docs/components/navbar.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,7 @@ In the example below, to create an offcanvas navbar that is always collapsed acr
10351035
:::demo
10361036
<CNavbar colorScheme="light" class="bg-light">
10371037
<CContainer fluid>
1038+
<CNavbarBrand>Offcanvas navbar</CNavbarBrand>
10381039
<CNavbarToggler
10391040
aria-controls="offcanvasNavbar"
10401041
aria-label="Toggle navigation"
@@ -1081,12 +1082,74 @@ In the example below, to create an offcanvas navbar that is always collapsed acr
10811082
</CContainer>
10821083
</CNavbar>
10831084
:::
1085+
```vue
1086+
<template>
1087+
<CNavbar colorScheme="light" class="bg-light">
1088+
<CContainer fluid>
1089+
<CNavbarBrand>Offcanvas navbar</CNavbarBrand>
1090+
<CNavbarToggler
1091+
aria-controls="offcanvasNavbar"
1092+
aria-label="Toggle navigation"
1093+
@click="visibleOffcanvas = !visibleOffcanvas"
1094+
/>
1095+
<COffcanvas id="offcanvasNavbar" placement="end" :visible="visibleOffcanvas" @hide="visibleOffcanvas = false">
1096+
<COffcanvasHeader>
1097+
<COffcanvasTitle>Offcanvas</COffcanvasTitle>
1098+
<CCloseButton class="text-reset" @click="visibleOffcanvas = false" />
1099+
</COffcanvasHeader>
1100+
<COffcanvasBody>
1101+
<CNavbarNav>
1102+
<CNavItem>
1103+
<CNavLink href="#" active>
1104+
Home
1105+
</CNavLink>
1106+
</CNavItem>
1107+
<CNavItem>
1108+
<CNavLink href="#">Link</CNavLink>
1109+
</CNavItem>
1110+
<CDropdown variant="nav-item" :popper="false">
1111+
<CDropdownToggle color="secondary">Dropdown button</CDropdownToggle>
1112+
<CDropdownMenu>
1113+
<CDropdownItem href="#">Action</CDropdownItem>
1114+
<CDropdownItem href="#">Another action</CDropdownItem>
1115+
<CDropdownDivider />
1116+
<CDropdownItem href="#">Something else here</CDropdownItem>
1117+
</CDropdownMenu>
1118+
</CDropdown>
1119+
<CNavItem>
1120+
<CNavLink href="#" disabled>
1121+
Disabled
1122+
</CNavLink>
1123+
</CNavItem>
1124+
</CNavbarNav>
1125+
<CForm class="d-flex">
1126+
<CFormInput type="search" class="me-2" placeholder="Search" />
1127+
<CButton type="submit" color="success" variant="outline">
1128+
Search
1129+
</CButton>
1130+
</CForm>
1131+
</COffcanvasBody>
1132+
</COffcanvas>
1133+
</CContainer>
1134+
</CNavbar>
1135+
</template>
1136+
<script>
1137+
export default {
1138+
data() {
1139+
return {
1140+
visibleOffcanvas: false,
1141+
}
1142+
}
1143+
}
1144+
</script>
1145+
```
10841146

10851147
To create an offcanvas navbar that expands into a normal navbar at a specific breakpoint like `xxl`, use `expand="xxl"` property.
10861148

10871149
:::demo
10881150
<CNavbar colorScheme="light" class="bg-light" expand="xxl">
10891151
<CContainer fluid>
1152+
<CNavbarBrand>Offcanvas navbar</CNavbarBrand>
10901153
<CNavbarToggler
10911154
aria-controls="offcanvasNavbar2"
10921155
aria-label="Toggle navigation"
@@ -1133,6 +1196,67 @@ To create an offcanvas navbar that expands into a normal navbar at a specific br
11331196
</CContainer>
11341197
</CNavbar>
11351198
:::
1199+
```vue
1200+
<template>
1201+
<CNavbar colorScheme="light" class="bg-light" expand="xxl">
1202+
<CContainer fluid>
1203+
<CNavbarBrand>Offcanvas navbar</CNavbarBrand>
1204+
<CNavbarToggler
1205+
aria-controls="offcanvasNavbar2"
1206+
aria-label="Toggle navigation"
1207+
@click="visibleOffcanvas2 = !visibleOffcanvas2"
1208+
/>
1209+
<COffcanvas id="offcanvasNavbar2" placement="end" :visible="visibleOffcanvas2" @hide="visibleOffcanvas2 = false">
1210+
<COffcanvasHeader>
1211+
<COffcanvasTitle>Offcanvas</COffcanvasTitle>
1212+
<CCloseButton class="text-reset" @click="visibleOffcanvas2 = false" />
1213+
</COffcanvasHeader>
1214+
<COffcanvasBody>
1215+
<CNavbarNav>
1216+
<CNavItem>
1217+
<CNavLink href="#" active>
1218+
Home
1219+
</CNavLink>
1220+
</CNavItem>
1221+
<CNavItem>
1222+
<CNavLink href="#">Link</CNavLink>
1223+
</CNavItem>
1224+
<CDropdown variant="nav-item" :popper="false">
1225+
<CDropdownToggle color="secondary">Dropdown button</CDropdownToggle>
1226+
<CDropdownMenu>
1227+
<CDropdownItem href="#">Action</CDropdownItem>
1228+
<CDropdownItem href="#">Another action</CDropdownItem>
1229+
<CDropdownDivider />
1230+
<CDropdownItem href="#">Something else here</CDropdownItem>
1231+
</CDropdownMenu>
1232+
</CDropdown>
1233+
<CNavItem>
1234+
<CNavLink href="#" disabled>
1235+
Disabled
1236+
</CNavLink>
1237+
</CNavItem>
1238+
</CNavbarNav>
1239+
<CForm class="d-flex">
1240+
<CFormInput type="search" class="me-2" placeholder="Search" />
1241+
<CButton type="submit" color="success" variant="outline">
1242+
Search
1243+
</CButton>
1244+
</CForm>
1245+
</COffcanvasBody>
1246+
</COffcanvas>
1247+
</CContainer>
1248+
</CNavbar>
1249+
</template>
1250+
<script>
1251+
export default {
1252+
data() {
1253+
return {
1254+
visibleOffcanvas2: false,
1255+
}
1256+
}
1257+
}
1258+
</script>
1259+
```
11361260

11371261
<script>
11381262
export default {

packages/docs/components/offcanvas.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,51 @@ If you set a `backdrop` to `static`, your React offcanvas component will not clo
205205
</script>
206206
```
207207

208+
## Responsive
209+
210+
Responsive offcanvas properties hide content outside the viewport from a specified breakpoint and down.
211+
Above that breakpoint, the contents within will behave as usual.
212+
For example, `responsive="lg"` hides content in an offcanvas below the lg breakpoint, but shows the content above the lg breakpoint.
213+
214+
::: demo
215+
<CButton color="primary" @click="() => { visibleResponsiveBackdrop = !visibleResponsiveBackdrop }">Toggle offcanvas</CButton>
216+
<CAlert class="d-none d-lg-block" color="info">Resize your browser to show the responsive offcanvas toggle.</CAlert>
217+
<COffcanvas placement="start" responsive="lg" :visible="visibleResponsiveBackdrop" @hide="() => { visibleResponsiveBackdrop = !visibleResponsiveBackdrop }">
218+
<COffcanvasHeader>
219+
<COffcanvasTitle>Responsive offcanvas</COffcanvasTitle>
220+
<CCloseButton class="text-reset" @click="() => { visibleResponsiveBackdrop = false }"/>
221+
</COffcanvasHeader>
222+
<COffcanvasBody>
223+
<p>This is content within an <code>.offcanvas-lg</code></p>.
224+
</COffcanvasBody>
225+
</COffcanvas>
226+
:::
227+
```vue
228+
<template>
229+
<CButton color="primary" @click="() => { visibleResponsiveBackdrop = !visibleResponsiveBackdrop }">Toggle static offcanvas</CButton>
230+
<CAlert class="d-none d-lg-block" color="info">Resize your browser to show the responsive offcanvas toggle.</CAlert>
231+
<COffcanvas placement="start" responsive="lg" :visible="visibleResponsiveBackdrop" @hide="() => { visibleResponsiveBackdrop = !visibleResponsiveBackdrop }">
232+
<COffcanvasHeader>
233+
<COffcanvasTitle>Responsive offcanvas</COffcanvasTitle>
234+
<CCloseButton class="text-reset" @click="() => { visibleResponsiveBackdrop = false }"/>
235+
</COffcanvasHeader>
236+
<COffcanvasBody>
237+
<p>This is content within an <code>.offcanvas-lg</code></p>.
238+
</COffcanvasBody>
239+
</COffcanvas>
240+
</template>
241+
<script>
242+
export default {
243+
data() {
244+
return {
245+
visibleResponsiveBackdrop: false,
246+
}
247+
}
248+
}
249+
</script>
250+
```
251+
252+
208253
## Placement
209254

210255
There's no default placement for offcanvas components, so you must add one of the modifier classes below;
@@ -343,6 +388,7 @@ Since the offcanvas panel is conceptually a modal dialog, be sure to add `aria-l
343388
visibleEnd: false,
344389
visibleBottom: false,
345390
visibleScrolling: false,
391+
visibleResponsiveBackdrop: false,
346392
visibleWithStaticBackdrop: false,
347393
visibleWithBothOptions: false,
348394
}

0 commit comments

Comments
 (0)