Skip to content

Commit 4e0b68b

Browse files
committed
Add support for bg image in surface
1 parent cb12645 commit 4e0b68b

5 files changed

Lines changed: 136 additions & 6 deletions

File tree

src/components/surface/CdrSurface.vue

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,46 @@
11
<script setup lang="ts">
2-
import { useCssModule, computed } from 'vue';
2+
import { useCssModule, computed, type StyleValue } from 'vue';
33
import type { surface } from '../../types/interfaces';
44
import { getSurfaceProps } from '../../utils/surface';
55
66
/** Foundational container for creating structured layouts */
77
defineOptions({ name: 'CdrSurface' });
88
9-
const props = withDefaults(defineProps<surface>(), {
9+
const props = withDefaults(defineProps<surface & {
10+
/** URL for the background image */
11+
backgroundImage?: string;
12+
/** Value for the background-size CSS property */
13+
backgroundSize?: string;
14+
/** Value for the background-position CSS property */
15+
backgroundPosition?: string;
16+
}>(), {
1017
tag: 'div',
18+
backgroundImage: undefined,
19+
backgroundSize: 'cover',
20+
backgroundPosition: 'center',
1121
});
1222
1323
const style = useCssModule();
1424
1525
// Use the merged props to compute the root props for the component.
16-
const rootProps = computed(() => getSurfaceProps(props));
26+
const baseProps = computed(() => getSurfaceProps(props));
27+
28+
// Compute the inline styles for background image properties
29+
const imageStyles = computed(() => {
30+
const styles: StyleValue = {};
31+
if (props.backgroundImage) {
32+
styles['--cdr-surface-background-image'] = `url(${props.backgroundImage})`;
33+
styles['--cdr-surface-background-size'] = props.backgroundSize;
34+
styles['--cdr-surface-background-position'] = props.backgroundPosition;
35+
}
36+
return styles;
37+
});
38+
39+
// Merge base props and image styles
40+
const rootProps = computed(() => ({
41+
...baseProps.value,
42+
style: imageStyles.value,
43+
}));
1744
</script>
1845

1946
<template>

src/components/surface/__tests__/CdrSurface.spec.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,40 @@ describe('CdrSurface', () => {
112112
expect(wrapper.attributes('data-background')).toBe('primary');
113113
expect(wrapper.element).toMatchSnapshot();
114114
});
115+
116+
it('applies background image properties via style attribute', () => {
117+
const wrapper = mount(CdrSurface, {
118+
props: {
119+
backgroundImage: 'path/to/image.jpg',
120+
backgroundSize: 'contain',
121+
backgroundPosition: 'top left',
122+
}
123+
});
124+
const style = wrapper.attributes('style');
125+
expect(style).toContain('--cdr-surface-background-image: url(path/to/image.jpg);');
126+
expect(style).toContain('--cdr-surface-background-size: contain;');
127+
expect(style).toContain('--cdr-surface-background-position: top left;');
128+
expect(wrapper.element).toMatchSnapshot();
129+
});
130+
131+
it('applies background image with default size and position', () => {
132+
const wrapper = mount(CdrSurface, {
133+
props: {
134+
backgroundImage: 'path/to/another.png',
135+
}
136+
});
137+
const style = wrapper.attributes('style');
138+
expect(style).toContain('--cdr-surface-background-image: url(path/to/another.png);');
139+
expect(style).toContain('--cdr-surface-background-size: cover;'); // Default
140+
expect(style).toContain('--cdr-surface-background-position: center;'); // Default
141+
expect(wrapper.element).toMatchSnapshot();
142+
});
143+
144+
it('does not apply background image styles if prop is not provided', () => {
145+
const wrapper = mount(CdrSurface);
146+
const style = wrapper.attributes('style');
147+
// Expect style attribute to be undefined or not contain the background image variables
148+
expect(style === undefined || !style.includes('--cdr-surface-background-image')).toBe(true);
149+
expect(wrapper.element).toMatchSnapshot(); // Should match default snapshot
150+
});
115151
});

src/components/surface/__tests__/__snapshots__/CdrSurface.spec.js.snap

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`CdrSurface > applies background image properties via style attribute 1`] = `
4+
<div
5+
class="cdr-surface"
6+
style="--cdr-surface-background-image: url(path/to/image.jpg); --cdr-surface-background-size: contain; --cdr-surface-background-position: top left;"
7+
>
8+
9+
10+
</div>
11+
`;
12+
13+
exports[`CdrSurface > applies background image with default size and position 1`] = `
14+
<div
15+
class="cdr-surface"
16+
style="--cdr-surface-background-image: url(path/to/another.png); --cdr-surface-background-size: cover; --cdr-surface-background-position: center;"
17+
>
18+
19+
20+
</div>
21+
`;
22+
323
exports[`CdrSurface > applies background property 1`] = `
424
<div
525
class="cdr-surface"
@@ -122,6 +142,15 @@ exports[`CdrSurface > default snapshot 1`] = `
122142
>
123143
124144
145+
</div>
146+
`;
147+
148+
exports[`CdrSurface > does not apply background image styles if prop is not provided 1`] = `
149+
<div
150+
class="cdr-surface"
151+
>
152+
153+
125154
</div>
126155
`;
127156

src/components/surface/examples/Surface.vue

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ defineOptions({ name: 'Surface' });
1111
export interface Example {
1212
label: string;
1313
title: string;
14-
props: surface | HtmlAttributes;
14+
props: surface | HtmlAttributes | Record<string, any>;
1515
}
1616
1717
const boxes: Example[] = [
@@ -78,6 +78,19 @@ const boxes: Example[] = [
7878
borderColor: 'primary',
7979
},
8080
},
81+
{
82+
label: 'This surface has a background image',
83+
title: 'Background Image Example',
84+
props: {
85+
class: 'example__card example__card--image',
86+
backgroundImage: 'https://picsum.photos/600/200',
87+
backgroundSize: 'cover',
88+
backgroundPosition: 'center center',
89+
style: {
90+
padding: '16px'
91+
}
92+
},
93+
},
8194
];
8295
</script>
8396

@@ -109,6 +122,26 @@ const boxes: Example[] = [
109122
&__card {
110123
display: inline-block;
111124
padding: $cdr-space-two-x;
125+
min-width: 300px;
126+
127+
&--image {
128+
min-height: 150px;
129+
position: relative;
130+
131+
&::after {
132+
content: '';
133+
position: absolute;
134+
inset: 0;
135+
background: linear-gradient(rgba(0,0,0,0.1), rgba(0,0,0,0.4));
136+
border-radius: inherit;
137+
pointer-events: none;
138+
}
139+
140+
> * {
141+
position: relative;
142+
z-index: 1;
143+
}
144+
}
112145
}
113146
114147
&__pill {

src/components/surface/styles/CdrSurface.module.scss

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ $css-vars: (
6060
border-width: --cdr-surface-border-width,
6161
border-style: --cdr-surface-border-style,
6262
border-radius: --border-radius,
63-
box-shadow: --cdr-surface-box-shadow,
63+
box-shadow: --cdr-surface-box-shadow
6464
);
6565

6666
.cdr-surface {
@@ -112,9 +112,14 @@ $css-vars: (
112112
}
113113

114114
background: var(--cdr-surface-background);
115-
border-radius: var(--cdr-surface-border-radius);
115+
border-radius: var(--cdr-surface-border-radius, var(--border-radius)); // Added fallback for potential naming mismatch
116116
box-shadow: var(--cdr-surface-box-shadow);
117117

118+
background-image: var(--cdr-surface-background-image);
119+
background-size: var(--cdr-surface-background-size);
120+
background-position: var(--cdr-surface-background-position);
121+
background-repeat: no-repeat;
122+
118123
&::before {
119124
border: var(--cdr-surface-border-width) var(--cdr-surface-border-style) var(--cdr-surface-border-color);
120125
border-radius: inherit;

0 commit comments

Comments
 (0)