@citizenplane/pimp 11.0.2 → 11.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@citizenplane/pimp",
3
- "version": "11.0.2",
3
+ "version": "11.0.4",
4
4
  "scripts": {
5
5
  "dev": "storybook dev -p 8080",
6
6
  "build-storybook": "storybook build --output-dir ./docs",
@@ -11,8 +11,8 @@
11
11
  <div aria-hidden="true" class="cpDialog__overlay" />
12
12
  <main ref="dialogContainer" class="cpDialog__container" :style="dynamicStyle" @keydown.tab="trapFocus">
13
13
  <header class="cpDialog__header">
14
- <div class="cpDialog__left">
15
- <div class="cpDialog__title">
14
+ <div v-if="hasTitleOrSubtitle" class="cpDialog__headerTexts">
15
+ <div v-if="hasTitle" class="cpDialog__title">
16
16
  <slot name="title">
17
17
  <h2 :id="titleId">{{ title }}</h2>
18
18
  </slot>
@@ -46,7 +46,7 @@ import { getKeyboardFocusableElements, handleTrapFocus } from '@/helpers/dom'
46
46
  interface Props {
47
47
  maxWidth?: number
48
48
  subtitle?: string
49
- title: string
49
+ title?: string
50
50
  }
51
51
 
52
52
  interface Emits {
@@ -55,6 +55,7 @@ interface Emits {
55
55
 
56
56
  const props = withDefaults(defineProps<Props>(), {
57
57
  maxWidth: 600,
58
+ title: '',
58
59
  subtitle: '',
59
60
  })
60
61
 
@@ -73,8 +74,12 @@ const dialogContainer = ref<HTMLElement | null>(null)
73
74
 
74
75
  const dynamicStyle = computed(() => ({ maxWidth: `${props.maxWidth}px` }))
75
76
 
77
+ const hasTitleSlot = computed(() => !!slots.title)
78
+ const hasTitle = computed(() => !!props.title || hasTitleSlot.value)
76
79
  const hasSubtitleSlot = computed(() => !!slots.subtitle)
77
80
  const hasSubtitle = computed(() => !!props.subtitle || hasSubtitleSlot.value)
81
+ const hasTitleOrSubtitle = computed(() => hasTitle.value || hasSubtitle.value)
82
+
78
83
  const hasFooterSlot = computed(() => !!slots.footer)
79
84
 
80
85
  const handleClose = () => emit('close')
@@ -96,9 +101,7 @@ onMounted(() => {
96
101
  nextTick(() => focusOnFirstFocusableElement())
97
102
  })
98
103
 
99
- onBeforeUnmount(() => {
100
- closeDialog()
101
- })
104
+ onBeforeUnmount(() => closeDialog())
102
105
  </script>
103
106
 
104
107
  <style lang="scss">
@@ -184,10 +187,17 @@ $dialog-breakpoint: 550px;
184
187
  align-items: flex-start;
185
188
  justify-content: space-between;
186
189
  gap: var(--cp-spacing-md);
187
- border-bottom: 1px solid var(--cp-border-soft);
190
+
191
+ &:not(:has(.cpDialog__headerTexts)) {
192
+ padding-bottom: 0;
193
+ }
194
+
195
+ &:has(.cpDialog__headerTexts) {
196
+ border-bottom: 1px solid var(--cp-border-soft);
197
+ }
188
198
  }
189
199
 
190
- &__left {
200
+ &__headerText {
191
201
  display: flex;
192
202
  flex-direction: column;
193
203
  min-width: 0;
@@ -214,6 +224,7 @@ $dialog-breakpoint: 550px;
214
224
 
215
225
  &__close {
216
226
  display: flex;
227
+ margin-left: auto;
217
228
  align-items: center;
218
229
  justify-content: center;
219
230
  padding: var(--cp-spacing-sm);
@@ -268,6 +268,10 @@ onMounted(async () => {
268
268
  box-shadow: 0 0 0 var(--cp-dimensions-0_25) var(--cp-border-disabled);
269
269
  }
270
270
 
271
+ .cpInput__icon {
272
+ color: var(--cp-foreground-disabled);
273
+ }
274
+
271
275
  .cpInput__icon:hover ~ .cpInput__inner {
272
276
  box-shadow: 0 0 0 var(--cp-dimensions-0_25) var(--cp-border-disabled);
273
277
  }
@@ -51,6 +51,7 @@ export const TitleSubtitleWithProps: Story = {
51
51
  args: {
52
52
  maxWidth: 600,
53
53
  title: 'Dialog title',
54
+ subtitle: 'Dialog subtitle',
54
55
  },
55
56
  render: (args) => ({
56
57
  setup() {
@@ -72,11 +73,32 @@ export const TitleSubtitleWithProps: Story = {
72
73
  }),
73
74
  }
74
75
 
76
+ export const ContentOnly: Story = {
77
+ args: {
78
+ maxWidth: 600,
79
+ },
80
+ render: (args) => ({
81
+ setup() {
82
+ const isOpen = ref(false)
83
+ return { args, isOpen }
84
+ },
85
+ template: `
86
+ <CpButton @click="isOpen = true">Open Dialog (content only)</CpButton>
87
+ <CpTransitionDialog>
88
+ <CpDialog v-bind="args" v-if="isOpen" @close="isOpen = false">
89
+ <p>This is the default slot content with no title or subtitle.</p>
90
+ <template #footer>
91
+ <CpButton @click="isOpen = false">Close</CpButton>
92
+ </template>
93
+ </CpDialog>
94
+ </CpTransitionDialog>
95
+ `,
96
+ }),
97
+ }
98
+
75
99
  export const TitleSubtitleWithSlots: Story = {
76
100
  args: {
77
101
  maxWidth: 560,
78
- titleTag: 'div',
79
- subtitleTag: 'div',
80
102
  },
81
103
  render: (args) => ({
82
104
  setup() {