Skip to content

Commit d4f97a8

Browse files
feat: aspect-ratio
1 parent 882f06b commit d4f97a8

File tree

5 files changed

+137
-0
lines changed

5 files changed

+137
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import type { PrimitiveProps } from '~/primitive/index.ts'
2+
3+
export interface AspectRatioProps extends PrimitiveProps {
4+
ratio?: number
5+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<script setup lang="ts">
2+
import { shallowRef } from 'vue'
3+
import type { AspectRatioProps } from './AspectRatio.ts'
4+
import { Primitive } from '~/primitive/index.ts'
5+
6+
defineOptions({
7+
name: 'AspectRatio',
8+
inheritAttrs: false,
9+
})
10+
11+
withDefaults(defineProps<AspectRatioProps>(), {
12+
ratio: 1,
13+
})
14+
15+
const elRef = shallowRef<HTMLElement>()
16+
17+
defineExpose({
18+
$el: elRef,
19+
})
20+
</script>
21+
22+
<template>
23+
<div
24+
:style="{
25+
// ensures inner element is contained
26+
position: 'relative',
27+
// ensures padding bottom trick maths works
28+
width: '100%',
29+
paddingBottom: `${100 / ratio}%`,
30+
}"
31+
data-radix-aspect-ratio-wrapper=""
32+
>
33+
<Primitive
34+
:ref="(el: any) => {
35+
elRef = (el?.$el ?? el) || undefined
36+
}"
37+
:as="as"
38+
:as-child="asChild"
39+
v-bind="$attrs"
40+
:style="{
41+
// ensures children expand in ratio
42+
position: 'absolute',
43+
top: 0,
44+
right: 0,
45+
bottom: 0,
46+
left: 0,
47+
}"
48+
>
49+
<slot />
50+
</Primitive>
51+
</div>
52+
</template>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as AspectRatio } from './AspectRatio.vue'
2+
export type { AspectRatioProps } from './AspectRatio.ts'
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { AspectRatio } from '../index.ts'
2+
import './styles.css'
3+
4+
export default { title: 'Components/AspectRatio' }
5+
6+
const image = (
7+
<img
8+
src="https://images.unsplash.com/photo-1605030753481-bb38b08c384a?&auto=format&fit=crop&w=400&q=80"
9+
alt="A house in a forest"
10+
style={{ objectFit: 'cover', width: '100%', height: '100%' }}
11+
/>
12+
)
13+
14+
export function Styled() {
15+
return (
16+
<div style={{ width: '500px' }}>
17+
<AspectRatio class="asperRation__root">
18+
<h1>Default ratio (1/1)</h1>
19+
</AspectRatio>
20+
</div>
21+
)
22+
}
23+
24+
export function CustomRatios() {
25+
return (
26+
<div style={{ display: 'flex', gap: '20px' }}>
27+
<div style={{ width: '200px' }}>
28+
<AspectRatio ratio={1 / 2}>{image}</AspectRatio>
29+
</div>
30+
<div style={{ width: '200px' }}>
31+
<AspectRatio>{image}</AspectRatio>
32+
</div>
33+
<div style={{ width: '200px' }}>
34+
<AspectRatio ratio={16 / 9}>{image}</AspectRatio>
35+
</div>
36+
<div style={{ width: '200px' }}>
37+
<AspectRatio ratio={2 / 1}>{image}</AspectRatio>
38+
</div>
39+
</div>
40+
)
41+
}
42+
43+
export function Chromatic() {
44+
return (
45+
<>
46+
<h1>Default ratio</h1>
47+
<div style={{ width: '300px' }}>
48+
<AspectRatio class="asperRation__root">
49+
<p>Default ratio (1/1)</p>
50+
</AspectRatio>
51+
</div>
52+
53+
<h1>Custom ratios</h1>
54+
<div style={{ display: 'flex', gap: '20px' }}>
55+
<div style={{ width: '200px' }}>
56+
<AspectRatio ratio={1 / 2}>{image}</AspectRatio>
57+
</div>
58+
<div style={{ width: '200px' }}>
59+
<AspectRatio>{image}</AspectRatio>
60+
</div>
61+
<div style={{ width: '200px' }}>
62+
<AspectRatio ratio={16 / 9}>{image}</AspectRatio>
63+
</div>
64+
<div style={{ width: '200px' }}>
65+
<AspectRatio ratio={2 / 1}>{image}</AspectRatio>
66+
</div>
67+
</div>
68+
</>
69+
)
70+
}
71+
Chromatic.parameters = { chromatic: { disable: false } }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.asperRation__root{
2+
display: flex;
3+
align-items: center;
4+
justify-content: center;
5+
background-color: red;
6+
color: white;
7+
}

0 commit comments

Comments
 (0)