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

Commit ba216c9

Browse files
committed
fix: avatar group and background color
1 parent ee410ac commit ba216c9

File tree

5 files changed

+148
-13
lines changed

5 files changed

+148
-13
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import {
2+
ThemingProps,
3+
useMultiStyleConfig,
4+
chakra,
5+
ComponentWithProps,
6+
SystemProps,
7+
SystemStyleObject,
8+
} from "@chakra-ui/vue-system"
9+
import {
10+
createContext,
11+
getValidChildren,
12+
SNAO,
13+
vueThemingProps,
14+
useThemingProps
15+
} from "@chakra-ui/vue-utils"
16+
import { filterUndefined, mergeWith } from "@chakra-ui/utils"
17+
18+
import { h, defineComponent, computed, ComputedRef, PropType, cloneVNode } from "vue"
19+
import { baseStyle } from './c-avatar'
20+
21+
type AvatarGroupContext = ComputedRef<ThemingProps>
22+
23+
const [AvatarGroupProvider, useAvatarGroup] = createContext<AvatarGroupContext>(
24+
{
25+
strict: false,
26+
name: "AvatarGroupContext",
27+
}
28+
)
29+
30+
export { useAvatarGroup }
31+
32+
33+
export const avatarGroupProps = {
34+
max: {
35+
type: Number,
36+
default: 2,
37+
},
38+
spacing: {
39+
type: SNAO as PropType<SystemProps["margin"]>,
40+
default: "-0.75rem"
41+
},
42+
borderRadius: {
43+
type: SNAO as PropType<SystemProps["borderRadius"]>,
44+
default: "full"
45+
},
46+
borderColor: SNAO as PropType<SystemProps["borderColor"]>,
47+
...vueThemingProps,
48+
}
49+
50+
/**
51+
* CAvatarGroup displays a number of avatars grouped together in a stack.
52+
*/
53+
// @ts-ignore complex type
54+
export const CAvatarGroup = defineComponent({
55+
props: avatarGroupProps,
56+
setup(props, { slots, attrs }) {
57+
const mergedProps = computed(() => mergeWith({}, props, attrs))
58+
const themingProps = useThemingProps(mergedProps.value)
59+
const styles = useMultiStyleConfig("Avatar", themingProps.value)
60+
61+
const validChildren = computed(() => getValidChildren(slots))
62+
const visibleChildren = computed(() =>
63+
validChildren.value.slice(0, props.max)
64+
)
65+
const excessChildrenCount = computed(() => validChildren.value.length - props.max)
66+
67+
/**
68+
* Reversing the children is a great way to avoid using zIndex
69+
* to overlap the avatars
70+
*/
71+
const reversedVisibleChildren = computed(() =>
72+
visibleChildren.value.reverse()
73+
)
74+
75+
const clonedChildren = computed(() => reversedVisibleChildren.value.map((vnode, index) => {
76+
const isFirstAvatar = index === 0
77+
78+
const childProps = filterUndefined({
79+
marginEnd: isFirstAvatar ? 0 : props.spacing,
80+
size: props.size,
81+
borderColor: vnode?.props?.borderColor ?? props.borderColor,
82+
showBorder: true,
83+
})
84+
85+
console.log("childProps", childProps)
86+
87+
return cloneVNode(vnode, childProps)
88+
}))
89+
90+
const groupStyles = computed<SystemStyleObject>(() => ({
91+
display: "flex",
92+
alignItems: "center",
93+
justifyContent: "flex-end",
94+
flexDirection: "row-reverse",
95+
...styles.value.group,
96+
}))
97+
98+
const excessStyles = computed<SystemStyleObject>(() => ({
99+
borderRadius: props.borderRadius,
100+
marginStart: props.spacing,
101+
...baseStyle,
102+
...styles.value.excessLabel,
103+
}))
104+
105+
return () => (
106+
<chakra.div
107+
role="group"
108+
__label='avatar__group'
109+
__css={groupStyles.value}
110+
>
111+
<>
112+
{excessChildrenCount.value > 0 && (
113+
<chakra.span __label="avatar__excess" __css={excessStyles.value}>
114+
{`+${excessChildrenCount.value}`}
115+
</chakra.span>
116+
)}
117+
{clonedChildren.value}
118+
</>
119+
</chakra.div>
120+
)
121+
},
122+
})

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,10 @@ export const CAvatar = defineComponent({
164164

165165
const isLoaded = ref(false)
166166

167-
const styles = useMultiStyleConfig("Avatar", themingProps)
167+
const styles = useMultiStyleConfig("Avatar", computed(() => ({
168+
...themingProps.value,
169+
name: props.name
170+
})))
168171

169172
function handleLoaded(value: unknown) {
170173
if (value) {

packages/c-avatar/src/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from "./c-avatar"
2-
export * from "./c-avatar-badge"
2+
export * from "./c-avatar-badge"
3+
export * from "./c-avatar-group"

playground/src/App.vue

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,24 @@
2525
<!-- </transition> -->
2626
</router-view>
2727
</c-square>
28-
<c-icon-button
29-
color="inherit"
30-
pos="absolute"
31-
@click="toggleColorMode"
32-
top="10"
33-
right="10"
34-
:aria-label="`Switch to ${
35-
colorMode === 'light' ? 'dark' : 'light'
36-
} mode`"
37-
:icon="colorMode === 'light' ? 'moon' : 'sun'"
38-
/>
28+
<c-h-stack top="10" right="10" pos="absolute">
29+
<c-link is-external href="https://github.com/chakra-ui/chakra-ui-vue-next">
30+
<c-icon-button
31+
color="inherit"
32+
@click="toggleColorMode"
33+
aria-label="Go to github"
34+
icon="github"
35+
/>
36+
</c-link>
37+
<c-icon-button
38+
color="inherit"
39+
@click="toggleColorMode"
40+
:aria-label="`Switch to ${
41+
colorMode === 'light' ? 'dark' : 'light'
42+
} mode`"
43+
:icon="colorMode === 'light' ? 'moon' : 'sun'"
44+
/>
45+
</c-h-stack>
3946
</c-center>
4047
</chakra.section>
4148
</template>

playground/src/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { MotionPlugin } from "@vueuse/motion"
1212
import App from "./App.vue"
1313
import router from "./router"
1414
import { mode } from "@chakra-ui/theme-tools"
15+
import { feGithub } from 'feather-icons-paths'
1516

1617
console.log({ router })
1718

@@ -26,6 +27,7 @@ const app = createApp(App)
2627
library: {
2728
feActivity,
2829
feUser,
30+
feGithub
2931
},
3032
extend: {
3133
discord: {

0 commit comments

Comments
 (0)