Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

Commit ee410ac

Browse files
committed
fix(avatar:badge): fix icon
1 parent df13860 commit ee410ac

File tree

9 files changed

+160
-51
lines changed

9 files changed

+160
-51
lines changed

packages/c-avatar/examples/badge-c-avatar.vue

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,41 @@
1717
alt="Evan you"
1818
lazy
1919
>
20-
<c-avatar-badge bg="green.500" aria-label="Online" title="Online" />
20+
<c-avatar-badge
21+
bg="green.500"
22+
aria-label="Online"
23+
title="Online"
24+
box-size="1em"
25+
/>
2126
</c-avatar>
2227
</c-h-stack>
2328
<chakra.p font-weight="bold">All positions</chakra.p>
2429
<c-h-stack align="center" spacing="1">
2530
<c-avatar name="Sasuke Uchiha" size="sm">
26-
<c-avatar-badge placement="top-start" bg="gray.500" />
31+
<c-avatar-badge placement="top-start" bg="gray.500" box-size="1em" />
2732
</c-avatar>
2833
<c-avatar name="Evan You">
29-
<c-avatar-badge placement="top-end" bg="red.500" />
34+
<c-avatar-badge placement="top-end" bg="red.500" box-size="1em" />
3035
</c-avatar>
3136
<c-avatar size="lg">
32-
<c-avatar-badge placement="bottom-start" bg="orange.500" />
37+
<c-avatar-badge
38+
placement="bottom-start"
39+
bg="orange.500"
40+
box-size="1em"
41+
/>
3342
</c-avatar>
3443
<c-avatar
3544
src="https://www.github.com/yyx990803.png"
3645
size="xl"
3746
alt="Evan you"
3847
lazy
3948
>
40-
<c-avatar-badge bg="green.500" aria-label="Online" title="Online" />
49+
<c-avatar-badge
50+
bg="green.500"
51+
aria-label="Online"
52+
title="Online"
53+
box-size="1em"
54+
/>
4155
</c-avatar>
4256
</c-h-stack>
4357
<chakra.p font-weight="bold">With custom border colors</chakra.p>
@@ -46,10 +60,14 @@
4660
<c-avatar-badge bg="gray.500" borderColor="lightgray" />
4761
</c-avatar>
4862
<c-avatar name="Evan You">
49-
<c-avatar-badge bg="red.500" borderColor="pink" />
63+
<c-avatar-badge bg="red.500" box-size="1em" border-color="pink" />
5064
</c-avatar>
5165
<c-avatar size="lg">
52-
<c-avatar-badge bg="orange.500" borderColor="papayawhip" />
66+
<c-avatar-badge
67+
bg="orange.500"
68+
box-size="1em"
69+
border-color="papayawhip"
70+
/>
5371
</c-avatar>
5472
<c-avatar
5573
src="https://www.github.com/yyx990803.png"
@@ -62,24 +80,25 @@
6280
title="Online"
6381
bg="green.500"
6482
borderColor="palegreen"
83+
box-size="1em"
6584
>
6685
</c-avatar-badge>
6786
</c-avatar>
6887
</c-h-stack>
6988
<chakra.p font-weight="bold">Badge with icons</chakra.p>
7089
<c-h-stack align="center" spacing="1">
7190
<c-avatar name="Sasuke Uchiha" size="sm">
72-
<c-avatar-badge bg="orange.500">
91+
<c-avatar-badge bg="orange.500" box-size="1em">
7392
<c-icon color="white" name="chevron-right" w="0.3em" />
7493
</c-avatar-badge>
7594
</c-avatar>
7695
<c-avatar name="Evan You">
77-
<c-avatar-badge bg="red.500">
96+
<c-avatar-badge bg="red.500" box-size="1em">
7897
<c-icon color="white" name="minus" w="0.3em" />
7998
</c-avatar-badge>
8099
</c-avatar>
81100
<c-avatar size="lg">
82-
<c-avatar-badge bg="yellow.500">
101+
<c-avatar-badge bg="yellow.500" box-size="1em">
83102
<c-icon color="white" name="star" w="0.3em" />
84103
</c-avatar-badge>
85104
</c-avatar>
@@ -89,7 +108,7 @@
89108
alt="Evan you"
90109
loading="lazy"
91110
>
92-
<c-avatar-badge aria-label="Connected" bg="green.500">
111+
<c-avatar-badge aria-label="Connected" bg="green.500" box-size="1em">
93112
<c-icon color="white" name="add" w="0.3em" />
94113
</c-avatar-badge>
95114
</c-avatar>

packages/c-avatar/examples/base-c-avatar.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,6 @@
7272
</c-h-stack>
7373
</c-stack>
7474
</template>
75-
<script setup>
75+
<script setup lang="ts">
7676
import { CAvatar } from "../src"
7777
</script>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<template>
2+
<c-avatar
3+
src="https://www.jbakebwa.dev/assets/images/jbakebwa-headshot.jpeg"
4+
name="Jonathan Bakebwa"
5+
loading="lazy"
6+
icon="add"
7+
>
8+
<c-avatar-badge bg="tomato" border-color="papayawhip" box-size="1.25em" />
9+
</c-avatar>
10+
</template>
11+
12+
<script setup lang="ts">
13+
import { CAvatar, CAvatarBadge } from "../src"
14+
</script>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { SystemStyleObject } from '@chakra-ui/styled-system'
2+
import { warn } from '@chakra-ui/utils'
3+
import { chakra, HTMLChakraProps } from '@chakra-ui/vue-system'
4+
import { computed, defineComponent, getCurrentInstance, PropType, watchEffect } from 'vue'
5+
import { useAvatarStyles } from './c-avatar'
6+
7+
type BadgePlacement = "top-start" | "top-end" | "bottom-start" | "bottom-end"
8+
9+
const placementMap: Record<BadgePlacement, SystemStyleObject> = {
10+
"top-start": {
11+
top: "0",
12+
insetStart: "0",
13+
transform: "translate(-25%, -25%)",
14+
},
15+
"top-end": {
16+
top: "0",
17+
insetEnd: "0",
18+
transform: "translate(25%, -25%)",
19+
},
20+
"bottom-start": {
21+
bottom: "0",
22+
insetStart: "0",
23+
transform: "translate(-25%, 25%)",
24+
},
25+
"bottom-end": {
26+
bottom: "0",
27+
insetEnd: "0",
28+
transform: "translate(25%, 25%)",
29+
},
30+
}
31+
32+
export interface AvatarBadgeProps extends HTMLChakraProps<"div"> {
33+
placement?: BadgePlacement
34+
}
35+
36+
/**
37+
* CAvatarBadge used to show extra badge to the top-right
38+
* or bottom-right corner of an avatar.
39+
*/
40+
41+
export const CAvatarBadge = defineComponent({
42+
name: "CAvatarBadge",
43+
props: {
44+
placement: {
45+
type: String as PropType<BadgePlacement>,
46+
default: "bottom-end",
47+
}
48+
},
49+
setup(props, { attrs, slots }) {
50+
const styles = useAvatarStyles()
51+
52+
const instance = getCurrentInstance()
53+
54+
warn.bind(instance)({
55+
condition: !Object.keys(placementMap).includes(props.placement),
56+
message: `<CAvatarBadge /> expects a placement value of ${Object.keys(placementMap).join(", ")}. Instead got "${props.placement}"`
57+
})
58+
59+
const badgeStyles = computed<SystemStyleObject>(() => ({
60+
position: "absolute",
61+
display: "flex",
62+
alignItems: "center",
63+
justifyContent: "center",
64+
...placementMap[props.placement] || {},
65+
...styles.value.badge,
66+
}))
67+
68+
return () => (
69+
<chakra.div
70+
__label={"avatar__badge"}
71+
__css={badgeStyles.value}
72+
{...attrs}
73+
>
74+
{slots?.default?.()}
75+
</chakra.div>
76+
)
77+
}
78+
})

packages/c-avatar/src/c-avatar-image.tsx

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,11 @@ export const CAvatarImage = defineComponent({
3737
},
3838
emits: ["load", "error"],
3939
setup(props, { slots, emit, attrs }) {
40-
const { status, imageRef } = useImage({
40+
const { status } = useImage({
4141
...props,
4242
ignoreFallback: props.ignoreFallback,
4343
})
4444
const hasLoaded = computed(() => status.value === "loaded")
45-
const showFallback = computed(() => !props.src || !hasLoaded.value)
4645

4746
/**
4847
* Fallback avatar applies under 2 conditions:
@@ -51,10 +50,7 @@ export const CAvatarImage = defineComponent({
5150
*
5251
* In this case, we'll show either the name avatar or default avatar
5352
*/
54-
55-
watchEffect(() => {
56-
console.debug("hasLoaded", status.value)
57-
})
53+
const showFallback = computed(() => !props.src || !hasLoaded.value)
5854

5955
const { icon } = useAvatarContext()
6056

@@ -72,23 +68,25 @@ export const CAvatarImage = defineComponent({
7268

7369
return () => {
7470

71+
const showFallback = !props.src || !hasLoaded.value
72+
if (showFallback) {
73+
return props.name ? (
74+
<CAvatarName {...attrs}
75+
name={props.name}
76+
hidden={hasLoaded.value}
77+
/>
78+
) : (
79+
<Icon.value {...attrs} />
80+
)
81+
}
7582
return (
7683
<>
77-
{!hasLoaded.value && props.name && (
78-
<CAvatarName {...attrs}
79-
name={props.name}
80-
hidden={hasLoaded.value}
81-
/>
82-
)}
83-
{!props.src && !props.name && (
84-
<Icon.value {...attrs} />
85-
)}
86-
<chakra.img {...attrs}
84+
<chakra.img
85+
{...attrs}
8786
__label="avatar__img"
8887
src={props.src}
8988
srcset={props.srcSet}
9089
alt={props.name}
91-
ref={imageRef}
9290
onLoad={() => emit("load", [props.src, props.srcSet])}
9391
onError={(e) => emit("error", e)}
9492
referrerPolicy={props.referrerPolicy}
@@ -99,9 +97,7 @@ export const CAvatarImage = defineComponent({
9997
objectFit: "cover",
10098
borderRadius: props.borderRadius
10199
}}
102-
hidden={!hasLoaded.value}
103100
/>
104-
105101
</>
106102
)
107103
}

packages/c-avatar/src/c-avatar.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ export const CAvatar = defineComponent({
210210
__label='avatar'
211211
data-loaded={dataAttr(isLoaded.value)}
212212
__css={avatarStyles.value}
213-
{...extractedAttrs.value.rest}
213+
{...attrs}
214214
>
215215
<CAvatarImage
216216
src={props.src}
@@ -224,9 +224,8 @@ export const CAvatar = defineComponent({
224224
iconLabel={props.iconLabel}
225225
ignoreFallback={props.ignoreFallback}
226226
{...extractedAttrs.value.imgAttrs}
227-
>
228-
{slots?.default?.()}
229-
</CAvatarImage>
227+
/>
228+
{slots?.default?.()}
230229
</chakra.span>
231230
)
232231
}

packages/c-avatar/src/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from "./c-avatar"
2+
export * from "./c-avatar-badge"

packages/c-color-mode/src/color-mode-provider.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ export function setupColorModeContext(
141141
app.provide(AppColorModeContextSymbol, {
142142
colorMode: computed(() => colorMode.value),
143143
toggleColorMode,
144+
forced: computed(() => false)
144145
})
145146
}
146147

packages/c-image/src/use-image.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
watch,
1010
onMounted,
1111
watchPostEffect,
12+
nextTick,
13+
watchEffect,
1214
} from "vue"
1315

1416
type NativeImageProps = ImgHTMLAttributes
@@ -64,32 +66,30 @@ export function useImage(props: UseImageProps) {
6466

6567
const status = ref<Status>("pending")
6668

67-
// const imageRef = ref<HTMLImageElement | null>()
68-
const [imageRef, imageRefEl] = useRef<HTMLImageElement>()
69-
7069
const load = () => {
7170
if (!src) return
72-
if (imageRefEl.value) {
73-
imageRefEl.value.src = src
74-
if (crossOrigin) imageRefEl.value.crossOrigin = crossOrigin
75-
if (srcSet) imageRefEl.value.srcset = srcSet
76-
if (sizes) imageRefEl.value.sizes = sizes
77-
if (loading) imageRefEl.value.loading = loading
78-
79-
imageRefEl.value.onload = (event: Event) => {
71+
72+
const image = new Image()
73+
74+
if (image) {
75+
image.src = src
76+
if (crossOrigin) image.crossOrigin = crossOrigin
77+
if (srcSet) image.srcset = srcSet
78+
if (sizes) image.sizes = sizes
79+
80+
image.onload = (event: Event) => {
8081
status.value = "loaded"
8182
onLoad?.(event as unknown as Event)
8283
}
8384

84-
imageRefEl.value.onerror = (error) => {
85+
image.onerror = (error) => {
8586
status.value = "failed"
8687
onError?.(error as any)
8788
}
8889
}
8990
}
9091

91-
watch(imageRefEl, (_imageRefEl) => {
92-
console.debug("useImage options", props, _imageRefEl)
92+
watchPostEffect(() => {
9393
/**
9494
* If user opts out of the fallback/placeholder
9595
* logic, let's bail out.
@@ -98,18 +98,19 @@ export function useImage(props: UseImageProps) {
9898
return
9999
}
100100

101-
if (src && imageRefEl.value) {
101+
if (src) {
102102
load()
103103
}
104104
})
105105

106+
watchEffect(() => console.debug("status", status.value))
107+
106108
/**
107109
* If user opts out of the fallback/placeholder
108110
* logic, let's just return 'loaded'
109111
*/
110112
return {
111113
status: computed(() => (unref(ignoreFallback) ? "loaded" : status.value)),
112-
imageRef
113114
}
114115
}
115116

0 commit comments

Comments
 (0)