Skip to content

Commit 195440f

Browse files
mdoGeoSot
andauthored
v5.2.0 design refresh, plus responsive offcanvas classes (#35736)
* Add responsive offcanvas classes - Updates navbar-expand classes to de-dupe some styles—these shouldn't interfere now. - Adds some JS to the offcanvas component to help with responsiveness Co-Authored-By: GeoSot <geo.sotis@gmail.com> * Redesign homepage, docs, and examples Homepage: - New Bootstrap purple navbar - Redesigned masthead - Rewrote and redesigned homepage content - Replace Copy text with icons like Bootstrap Icons site across all ClipboardJS instances - Fixed padding issues in site footer - Match homepage button styles to examples page, use gap instead of tons of responsive margin utils Docs: - New navbar, no more subnav. Migrated search and version picker into the main navbar and refreshed the design of it all, including the responsive toggles. - New sidebar navigation is always expanded, and now features Bootstrap Icons alongside section headings - Sidebar navigation autoscrolls to active link for better usability - Subnav and navbar padding issues ironed out - Enhanced the version picker in anticipation of v5.2: we can now link right to the same page in the previous version. - Redesign callouts to add more color to our pages - Collapse table of contents on mobile - Cleanup and redesign button styles with CSS variables - Update design for subnav version dropdown - Update highlight and example to be full-width until md - Improve the Added In badges - Turn the ToC into a well on mobile - Redesign code snippets to better house two action buttons Examples: - Redesign Examples page layout - Add new example for responsive offcanvases in navbars * Convert offcanvas to CSS vars * Feat: add resize handler to Offcanvas.js. If we could use as default the `.offcanvas` class without modifiers, we then, could add a simplified selector The selector itself, ignores the .offcanvas class as it doesn't have any responsive behavior The `aria-modal` addon is to protect us, selection backdrop elements * Separate examples code, Add some selectors, fix stackblitz btn Co-authored-by: GeoSot <geo.sotis@gmail.com>
1 parent 26ea6f1 commit 195440f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1572
-625
lines changed

.bundlewatch.config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
},
2727
{
2828
"path": "./dist/css/bootstrap.css",
29-
"maxSize": "27.75 kB"
29+
"maxSize": "28.5 kB"
3030
},
3131
{
3232
"path": "./dist/css/bootstrap.min.css",
33-
"maxSize": "26.0 kB"
33+
"maxSize": "26.5 kB"
3434
},
3535
{
3636
"path": "./dist/js/bootstrap.bundle.js",

js/src/offcanvas.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const EVENT_SHOWN = `shown${EVENT_KEY}`
4141
const EVENT_HIDE = `hide${EVENT_KEY}`
4242
const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}`
4343
const EVENT_HIDDEN = `hidden${EVENT_KEY}`
44+
const EVENT_RESIZE = `resize${EVENT_KEY}`
4445
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
4546
const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`
4647

@@ -263,6 +264,14 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
263264
}
264265
})
265266

267+
EventHandler.on(window, EVENT_RESIZE, () => {
268+
for (const element of SelectorEngine.find('[aria-modal][class*=show][class*=offcanvas-]')) {
269+
if (getComputedStyle(element).position !== 'fixed') {
270+
Offcanvas.getOrCreateInstance(element).hide()
271+
}
272+
}
273+
})
274+
266275
enableDismissTrigger(Offcanvas)
267276

268277
/**

js/tests/unit/offcanvas.spec.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,28 @@ describe('Offcanvas', () => {
155155
offCanvas.show()
156156
})
157157
})
158+
159+
it('should call `hide` on resize, if element\'s position is not fixed any more', () => {
160+
return new Promise(resolve => {
161+
fixtureEl.innerHTML = '<div class="offcanvas-lg"></div>'
162+
163+
const offCanvasEl = fixtureEl.querySelector('div')
164+
const offCanvas = new Offcanvas(offCanvasEl)
165+
166+
spyOn(offCanvas, 'hide').and.callThrough()
167+
168+
offCanvasEl.addEventListener('shown.bs.offcanvas', () => {
169+
const resizeEvent = createEvent('resize')
170+
offCanvasEl.style.removeProperty('position')
171+
172+
window.dispatchEvent(resizeEvent)
173+
expect(offCanvas.hide).toHaveBeenCalled()
174+
resolve()
175+
})
176+
177+
offCanvas.show()
178+
})
179+
})
158180
})
159181

160182
describe('config', () => {

scss/_navbar.scss

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -222,41 +222,31 @@
222222
display: none;
223223
}
224224

225-
.offcanvas-header {
226-
display: none;
227-
}
228-
229225
.offcanvas {
230-
position: inherit;
231-
bottom: 0;
226+
// stylelint-disable declaration-no-important
227+
position: static;
232228
z-index: auto;
233229
flex-grow: 1;
234-
visibility: visible !important; // stylelint-disable-line declaration-no-important
235-
background-color: transparent;
236-
border-right: 0;
237-
border-left: 0;
230+
width: auto !important;
231+
height: auto !important;
232+
visibility: visible !important;
233+
background-color: transparent !important;
234+
border: 0 !important;
235+
transform: none !important;
238236
@include box-shadow(none);
239237
@include transition(none);
240-
transform: none;
241-
}
242-
.offcanvas-top,
243-
.offcanvas-bottom {
244-
height: auto;
245-
border-top: 0;
246-
border-bottom: 0;
247-
}
238+
// stylelint-enable declaration-no-important
248239

249-
.offcanvas-body {
250-
display: flex;
251-
flex-grow: 0;
252-
padding: 0;
253-
overflow-y: visible;
254-
}
240+
.offcanvas-header {
241+
display: none;
242+
}
255243

256-
// Reset `background-color` in case `.bg-*` classes are used in offcanvas
257-
.offcanvas,
258-
.offcanvas-body {
259-
background-color: transparent !important; // stylelint-disable-line declaration-no-important
244+
.offcanvas-body {
245+
display: flex;
246+
flex-grow: 0;
247+
padding: 0;
248+
overflow-y: visible;
249+
}
260250
}
261251
}
262252
}

scss/_offcanvas.scss

Lines changed: 116 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,115 @@
1-
.offcanvas {
2-
position: fixed;
3-
bottom: 0;
4-
z-index: $zindex-offcanvas;
5-
display: flex;
6-
flex-direction: column;
7-
max-width: 100%;
8-
color: $offcanvas-color;
9-
visibility: hidden;
10-
background-color: $offcanvas-bg-color;
11-
background-clip: padding-box;
12-
outline: 0;
13-
@include box-shadow($offcanvas-box-shadow);
14-
@include transition(transform $offcanvas-transition-duration ease-in-out);
15-
16-
&.showing,
17-
&.show:not(.hiding) {
18-
transform: none;
1+
// stylelint-disable function-disallowed-list
2+
3+
%offcanvas-css-vars {
4+
// scss-docs-start offcanvas-css-vars
5+
--#{$prefix}offcanvas-width: #{$offcanvas-horizontal-width};
6+
--#{$prefix}offcanvas-height: #{$offcanvas-vertical-height};
7+
--#{$prefix}offcanvas-padding-x: #{$offcanvas-padding-x};
8+
--#{$prefix}offcanvas-padding-y: #{$offcanvas-padding-y};
9+
--#{$prefix}offcanvas-color: #{$offcanvas-color};
10+
--#{$prefix}offcanvas-bg: #{$offcanvas-bg-color};
11+
--#{$prefix}offcanvas-border-width: #{$offcanvas-border-width};
12+
--#{$prefix}offcanvas-border-color: #{$offcanvas-border-color};
13+
--#{$prefix}offcanvas-box-shadow: #{$offcanvas-box-shadow};
14+
// scss-docs-end offcanvas-css-vars
15+
}
16+
17+
@each $breakpoint in map-keys($grid-breakpoints) {
18+
$next: breakpoint-next($breakpoint, $grid-breakpoints);
19+
$infix: breakpoint-infix($next, $grid-breakpoints);
20+
21+
.offcanvas#{$infix} {
22+
@extend %offcanvas-css-vars;
1923
}
24+
}
25+
26+
@each $breakpoint in map-keys($grid-breakpoints) {
27+
$next: breakpoint-next($breakpoint, $grid-breakpoints);
28+
$infix: breakpoint-infix($next, $grid-breakpoints);
29+
30+
.offcanvas#{$infix} {
31+
@include media-breakpoint-down($next) {
32+
position: fixed;
33+
bottom: 0;
34+
z-index: $zindex-offcanvas;
35+
display: flex;
36+
flex-direction: column;
37+
max-width: 100%;
38+
color: var(--#{$prefix}offcanvas-color);
39+
visibility: hidden;
40+
background-color: var(--#{$prefix}offcanvas-bg);
41+
background-clip: padding-box;
42+
outline: 0;
43+
@include box-shadow(var(--#{$prefix}offcanvas-box-shadow));
44+
@include transition(transform $offcanvas-transition-duration ease-in-out);
45+
46+
&.showing,
47+
&.show:not(.hiding) {
48+
transform: none;
49+
}
50+
51+
&.showing,
52+
&.hiding,
53+
&.show {
54+
visibility: visible;
55+
}
56+
57+
&.offcanvas-start {
58+
top: 0;
59+
left: 0;
60+
width: var(--#{$prefix}offcanvas-width);
61+
border-right: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
62+
transform: translateX(-100%);
63+
}
64+
65+
&.offcanvas-end {
66+
top: 0;
67+
right: 0;
68+
width: var(--#{$prefix}offcanvas-width);
69+
border-left: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
70+
transform: translateX(100%);
71+
}
2072

21-
&.showing,
22-
&.hiding,
23-
&.show {
24-
visibility: visible;
73+
&.offcanvas-top {
74+
top: 0;
75+
right: 0;
76+
left: 0;
77+
height: var(--#{$prefix}offcanvas-height);
78+
max-height: 100%;
79+
border-bottom: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
80+
transform: translateY(-100%);
81+
}
82+
83+
&.offcanvas-bottom {
84+
right: 0;
85+
left: 0;
86+
height: var(--#{$prefix}offcanvas-height);
87+
max-height: 100%;
88+
border-top: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
89+
transform: translateY(100%);
90+
}
91+
}
92+
93+
@if not ($infix == "") {
94+
@include media-breakpoint-up($next) {
95+
--#{$prefix}offcanvas-height: auto;
96+
--#{$prefix}offcanvas-border-width: 0;
97+
background-color: transparent !important; // stylelint-disable-line declaration-no-important
98+
99+
.offcanvas-header {
100+
display: none;
101+
}
102+
103+
.offcanvas-body {
104+
display: flex;
105+
flex-grow: 0;
106+
padding: 0;
107+
overflow-y: visible;
108+
// Reset `background-color` in case `.bg-*` classes are used in offcanvas
109+
background-color: transparent !important; // stylelint-disable-line declaration-no-important
110+
}
111+
}
112+
}
25113
}
26114
}
27115

@@ -33,13 +121,13 @@
33121
display: flex;
34122
align-items: center;
35123
justify-content: space-between;
36-
padding: $offcanvas-padding-y $offcanvas-padding-x;
124+
padding: var(--#{$prefix}offcanvas-padding-y) var(--#{$prefix}offcanvas-padding-x);
37125

38126
.btn-close {
39-
padding: ($offcanvas-padding-y * .5) ($offcanvas-padding-x * .5);
40-
margin-top: $offcanvas-padding-y * -.5;
41-
margin-right: $offcanvas-padding-x * -.5;
42-
margin-bottom: $offcanvas-padding-y * -.5;
127+
padding: calc(var(--#{$prefix}offcanvas-padding-y) * .5) calc(var(--#{$prefix}offcanvas-padding-x) * .5);
128+
margin-top: calc(var(--#{$prefix}offcanvas-padding-y) * -.5);
129+
margin-right: calc(var(--#{$prefix}offcanvas-padding-x) * -.5);
130+
margin-bottom: calc(var(--#{$prefix}offcanvas-padding-y) * -.5);
43131
}
44132
}
45133

@@ -50,41 +138,6 @@
50138

51139
.offcanvas-body {
52140
flex-grow: 1;
53-
padding: $offcanvas-padding-y $offcanvas-padding-x;
141+
padding: var(--#{$prefix}offcanvas-padding-y) var(--#{$prefix}offcanvas-padding-x);
54142
overflow-y: auto;
55143
}
56-
57-
.offcanvas-start {
58-
top: 0;
59-
left: 0;
60-
width: $offcanvas-horizontal-width;
61-
border-right: $offcanvas-border-width solid $offcanvas-border-color;
62-
transform: translateX(-100%);
63-
}
64-
65-
.offcanvas-end {
66-
top: 0;
67-
right: 0;
68-
width: $offcanvas-horizontal-width;
69-
border-left: $offcanvas-border-width solid $offcanvas-border-color;
70-
transform: translateX(100%);
71-
}
72-
73-
.offcanvas-top {
74-
top: 0;
75-
right: 0;
76-
left: 0;
77-
height: $offcanvas-vertical-height;
78-
max-height: 100%;
79-
border-bottom: $offcanvas-border-width solid $offcanvas-border-color;
80-
transform: translateY(-100%);
81-
}
82-
83-
.offcanvas-bottom {
84-
right: 0;
85-
left: 0;
86-
height: $offcanvas-vertical-height;
87-
max-height: 100%;
88-
border-top: $offcanvas-border-width solid $offcanvas-border-color;
89-
transform: translateY(100%);
90-
}

scss/_spinners.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
--#{$prefix}spinner-animation-name: spinner-border;
3030
// scss-docs-end spinner-border-css-vars
3131

32-
border: var(--#{$prefix}spinner-border-width) solid currentColor;
32+
border: var(--#{$prefix}spinner-border-width) solid currentcolor;
3333
border-right-color: transparent;
3434
}
3535

0 commit comments

Comments
 (0)