Skip to content

Commit f29dfbe

Browse files
committed
Add optional header and footer slots to ipl-dialog and ipl-sidebar
1 parent eab49cf commit f29dfbe

File tree

10 files changed

+233
-3
lines changed

10 files changed

+233
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 3.8.0
2+
3+
- Add optional `header` and `footer` slots to ipl-dialog and ipl-sidebar
4+
15
# 3.7.0
26

37
- Add default and `end` slot to ipl-dialog-title

docs/dialogs.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ title: Dialogs
88

99
::: demo SidebarExample
1010

11+
::: demo SidebarHeaderFooterExample
12+
1113
## ipl-dialog
1214

1315
::: demo DialogExample
1416

17+
::: demo DialogHeaderFooterExample
18+
1519
## Known issues
1620

1721
- The backdrop does not animate in Firefox ([Bugzilla](https://bugzilla.mozilla.org/show_bug.cgi?id=1725177))
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<template>
2+
<div
3+
style="position: relative; overflow: hidden; min-height: 150px"
4+
class="sidebar-example-layout"
5+
>
6+
<!-- #region example -->
7+
<ipl-dialog
8+
v-model:is-open="dialogOpen"
9+
style="width: 500px"
10+
:persistent="persistent"
11+
>
12+
<template #header>
13+
<ipl-dialog-title
14+
title="Test Dialog"
15+
@close="dialogOpen = false"
16+
/>
17+
</template>
18+
<div class="width-capped-content">
19+
<ipl-space
20+
color="light"
21+
class="vertical-layout"
22+
>
23+
<div>Hello!</div>
24+
<ipl-button
25+
label="Button!"
26+
/>
27+
<ipl-small-toggle
28+
v-model="doOverflow"
29+
label="Overflow?"
30+
/>
31+
<div v-if="doOverflow">
32+
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
33+
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
34+
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
35+
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
36+
</div>
37+
</ipl-space>
38+
</div>
39+
<template #footer>
40+
<div class="width-capped-content">
41+
<ipl-button
42+
label="Close dialog"
43+
color="red"
44+
@click="dialogOpen = false"
45+
/>
46+
</div>
47+
</template>
48+
</ipl-dialog>
49+
<ipl-button
50+
label="Open dialog (Header & Footer)"
51+
@click="dialogOpen = true"
52+
/>
53+
<!-- #endregion example -->
54+
</div>
55+
<div class="horizontal-layout">
56+
<ipl-checkbox
57+
v-model="persistent"
58+
label="Persistent"
59+
/>
60+
</div>
61+
</template>
62+
63+
<script setup lang="ts">
64+
import { IplButton, IplSpace, IplDialog, IplCheckbox, IplSmallToggle, IplDialogTitle } from '../../src';
65+
import { ref } from 'vue';
66+
67+
const dialogOpen = ref(false);
68+
const persistent = ref(false);
69+
const doOverflow = ref(true);
70+
</script>
71+
72+
<style lang="scss">
73+
.sidebar-example-layout {
74+
display: flex;
75+
align-items: center;
76+
justify-content: center;
77+
78+
> .ipl-button {
79+
width: auto;
80+
}
81+
}
82+
</style>
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<template>
2+
<div
3+
style="position: relative; overflow: hidden; min-height: 150px"
4+
class="sidebar-example-layout"
5+
>
6+
<!-- #region example -->
7+
<ipl-sidebar
8+
v-model:is-open="sidebarOpen"
9+
:persistent="persistent"
10+
>
11+
<template #header>
12+
<ipl-dialog-title
13+
title="Test Sidebar"
14+
@close="sidebarOpen = false"
15+
/>
16+
</template>
17+
<div class="width-capped-content">
18+
<ipl-space
19+
color="light"
20+
class="vertical-layout"
21+
>
22+
<div>Hello!</div>
23+
<ipl-button
24+
label="Button!"
25+
/>
26+
<ipl-small-toggle
27+
v-model="doOverflow"
28+
label="Overflow?"
29+
/>
30+
<div v-if="doOverflow">
31+
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
32+
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
33+
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
34+
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
35+
</div>
36+
</ipl-space>
37+
</div>
38+
<template #footer>
39+
<div class="width-capped-content">
40+
<ipl-button
41+
label="Close sidebar"
42+
color="red"
43+
@click="sidebarOpen = false"
44+
/>
45+
</div>
46+
</template>
47+
</ipl-sidebar>
48+
<ipl-button
49+
label="Open sidebar (Header & footer)"
50+
@click="sidebarOpen = true"
51+
/>
52+
<!-- #endregion example -->
53+
</div>
54+
<div class="horizontal-layout">
55+
<ipl-checkbox
56+
v-model="persistent"
57+
label="Persistent"
58+
/>
59+
</div>
60+
</template>
61+
62+
<script setup lang="ts">
63+
import { IplSidebar, IplButton, IplSpace, IplCheckbox, IplDialogTitle, IplSmallToggle } from '../../src';
64+
import { ref } from 'vue';
65+
66+
const sidebarOpen = ref(false);
67+
const persistent = ref(false);
68+
const doOverflow = ref(true);
69+
</script>
70+
71+
<style lang="scss">
72+
.sidebar-example-layout {
73+
display: flex;
74+
align-items: center;
75+
justify-content: center;
76+
77+
> .ipl-button {
78+
width: auto;
79+
}
80+
}
81+
</style>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@iplsplatoon/vue-components",
3-
"version": "3.7.0",
3+
"version": "3.8.0",
44
"description": "Vue components for internal Inkling Performance Labs utilities.",
55
"homepage": "https://github.com/IPLSplatoon/vue-components",
66
"repository": "https://github.com/IPLSplatoon/vue-components",

src/components/__tests__/__snapshots__/iplSidebar.test.ts.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
exports[`IplSidebar matches snapshot 1`] = `
44
"<dialog inert="">
5+
<div class="header"></div>
56
<div class="content">test sidebar content</div>
7+
<div class="footer"></div>
68
</dialog>"
79
`;

src/components/iplDialog.vue

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@
55
@cancel.prevent="onCancel"
66
@click.self="onClick"
77
>
8+
<div class="header">
9+
<slot name="header" />
10+
</div>
811
<div class="content">
912
<slot />
1013
</div>
14+
<div class="footer">
15+
<slot name="footer" />
16+
</div>
1117
</dialog>
1218
</template>
1319

@@ -88,6 +94,18 @@ dialog {
8894
top: 50%;
8995
transform: translate(-50%, -50%);
9096
border-radius: constants.$border-radius-outer;
97+
max-height: calc(100dvh - 16px);
98+
}
99+
100+
// Touchscreen devices tend to have random UI elements loitering around the bottom of the screen
101+
// (e.g. the little bar you swipe up from to return to the home screen; I don't know what it's called.
102+
// I can see it on my iPad and my Pixel, so it isn't unique to one operating system.)
103+
// This media query addresses that by adding more empty space below dialogs on touchscreens.
104+
@media (pointer: coarse) {
105+
dialog {
106+
max-height: calc(100dvh - 32px);
107+
top: calc(50% - 8px);
108+
}
91109
}
92110
93111
@include dialogs.dialog-common-animation;

src/components/iplSidebar.vue

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@
55
@cancel.prevent="onCancel"
66
@click.self="onClick"
77
>
8+
<div class="header">
9+
<slot name="header" />
10+
</div>
811
<div class="content">
912
<slot />
1013
</div>
14+
<div class="footer">
15+
<slot name="footer" />
16+
</div>
1117
</dialog>
1218
</template>
1319

@@ -86,12 +92,23 @@ dialog {
8692
transform: translateX(-85vw);
8793
width: 85%;
8894
height: 100%;
95+
max-height: 100%;
8996
9097
&:not([open]) {
9198
opacity: 0;
9299
}
93100
}
94101
102+
// Touchscreen devices tend to have random UI elements loitering around the bottom of the screen
103+
// (e.g. the little bar you swipe up from to return to the home screen; I don't know what it's called.
104+
// I can see it on my iPad and my Pixel, so it isn't unique to one operating system.)
105+
// This media query addresses that by adding more empty space below dialogs on touchscreens.
106+
@media (pointer: coarse) {
107+
dialog > .footer:not(:empty) {
108+
padding-bottom: 24px;
109+
}
110+
}
111+
95112
@include dialogs.dialog-common-animation;
96113
97114
@keyframes dialog-enter {

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import './styles/variables.scss';
22
import './styles/variables-light.scss';
3+
import './styles/dialogs.scss';
34

45
export { default as IplButton } from './components/iplButton.vue';
56
export { default as IplCheckbox } from './components/iplCheckbox.vue';

src/styles/dialogs.scss

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@
3232
border: none;
3333
background-color: var(--ipl-bg-primary);
3434
color: var(--ipl-body-text-color);
35-
max-height: 100%;
3635
box-sizing: border-box;
3736
margin: 0;
3837
padding: 0;
3938
inset: 0;
40-
display: block;
39+
display: flex;
40+
flex-direction: column;
41+
overflow: hidden;
4142
position: fixed;
4243
// Unfortunately, if you want animation, you'll have to put up with this.
4344
z-index: 999999;
@@ -66,8 +67,28 @@
6667
background: var(--ipl-page-overlay-color);
6768
}
6869

70+
> .header:not(:empty) {
71+
padding: 8px;
72+
border-bottom: 1px solid var(--ipl-input-color);
73+
background-color: var(--ipl-bg-secondary);
74+
75+
> :deep(.ipl-dialog-title) {
76+
padding: 0 8px;
77+
background-color: transparent;
78+
}
79+
}
80+
81+
> .footer:not(:empty) {
82+
padding: 8px;
83+
border-top: 1px solid var(--ipl-input-color);
84+
background-color: var(--ipl-bg-secondary);
85+
}
86+
6987
> .content {
7088
padding: 8px;
89+
flex-grow: 1;
90+
overflow-y: auto;
91+
overscroll-behavior: contain;
7192
}
7293

7394
&:focus-visible {

0 commit comments

Comments
 (0)