-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
419 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
@layer components { | ||
.bcc-react { | ||
@apply relative flex w-full items-center overflow-visible; | ||
} | ||
.bcc-react-toggle { | ||
@apply mr-1 flex shrink-0 cursor-pointer items-center justify-center rounded-full p-1 leading-tight transition; | ||
} | ||
.bcc-react-list { | ||
@apply hide-scrollbar flex flex-1 items-center gap-1 overflow-x-auto overflow-y-hidden rounded-full p-1; | ||
} | ||
.bcc-react-empty { | ||
@apply text-label flex items-center; | ||
} | ||
|
||
.bcc-react-selector { | ||
@apply absolute -left-1 z-50 flex items-center gap-1 rounded-full bg-neutral-100 px-1 dark:bg-neutral-600; | ||
/* Default --bottom */ | ||
@apply top-11 origin-top-left shadow-lg; | ||
} | ||
|
||
.bcc-react-selector--top { | ||
@apply -top-10 origin-bottom-left shadow; | ||
} | ||
|
||
.bcc-react-selector-item { | ||
@apply p-2 text-xl leading-none; | ||
} | ||
|
||
.bcc-react-emoji-list-item { | ||
@apply flex cursor-pointer items-center justify-center rounded-full p-1 text-2xl leading-none shadow transition-all hover:scale-105; | ||
/* Default --not-selected */ | ||
@apply text-black bg-neutral-100; | ||
} | ||
.bcc-react-emoji-list-item--selected { | ||
@apply bg-neutral-800 text-white; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { describe, it, expect } from "vitest"; | ||
|
||
import { mount } from "@vue/test-utils"; | ||
import BccReact from "./BccReact.vue"; | ||
|
||
describe("BccReact", () => { | ||
it("renders reactions", () => { | ||
expect(BccReact).toBeTruthy(); | ||
|
||
const wrapper = mount(BccReact, { | ||
props: { | ||
emojis: [ | ||
{ | ||
id: "thumbsup", | ||
emoji: "👍", | ||
count: 1, | ||
}, | ||
{ | ||
id: "happy", | ||
emoji: "😃", | ||
count: 4, | ||
}, | ||
], | ||
}, | ||
}); | ||
|
||
expect(wrapper.text()).toContain("4"); | ||
expect(wrapper.text()).not.toContain("1"); | ||
expect(wrapper.html()).toMatchSnapshot(); | ||
}); | ||
}); |
165 changes: 165 additions & 0 deletions
165
design-library/src/components/BccReact/BccReact.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
import BccReact from "./BccReact.vue"; | ||
|
||
import type { Meta, StoryFn } from "@storybook/vue3"; | ||
|
||
export default { | ||
title: "Components/BccReact", | ||
component: BccReact, | ||
argTypes: {}, | ||
} as Meta<typeof BccReact>; | ||
|
||
const Template: StoryFn<typeof BccReact> = (args) => ({ | ||
components: { BccReact }, | ||
setup() { | ||
return { args }; | ||
}, | ||
methods: { | ||
onToggle(emojiId: string) { | ||
const emoji = args.emojis.find((e) => e.id === emojiId); | ||
if (!emoji) return; | ||
if (emoji.count === undefined) emoji.count = 0; | ||
emoji.count += emoji.selected ? -1 : 1; | ||
emoji.selected = !emoji.selected; | ||
|
||
// Enable for only allowing single reaction per user | ||
/* | ||
if (args.singleReaction && emoji.selected) { | ||
args.emojis.forEach((e) => { | ||
if (e.id !== emojiId && e.selected) { | ||
e.selected = false; | ||
e.count = (e.count || 1) - 1; | ||
} | ||
}); | ||
} | ||
*/ | ||
}, | ||
}, | ||
template: ` | ||
<div class="h-16 flex items-center"> | ||
<BccReact v-bind="args" @toggle="onToggle" /> | ||
</div> | ||
`, | ||
}); | ||
|
||
export const Example = Template.bind({}); | ||
Example.args = { | ||
top: false, | ||
emojis: [ | ||
{ | ||
id: "thumbsup", | ||
emoji: "👍", | ||
count: 0, | ||
}, | ||
{ | ||
id: "happy", | ||
emoji: "😃", | ||
count: 2, | ||
selected: true, | ||
}, | ||
{ | ||
id: "smile", | ||
emoji: "😊", | ||
count: 0, | ||
}, | ||
{ | ||
id: "glasses", | ||
emoji: "😎", | ||
count: 0, | ||
}, | ||
{ | ||
id: "love", | ||
emoji: "😍", | ||
count: 0, | ||
}, | ||
{ | ||
id: "stars", | ||
emoji: "🤩", | ||
count: 0, | ||
}, | ||
{ | ||
id: "rocket", | ||
emoji: "🚀", | ||
count: 93, | ||
}, | ||
], | ||
}; | ||
|
||
Example.parameters = { | ||
docs: { | ||
source: { | ||
language: "html", | ||
code: ` | ||
<--script--> | ||
onToggle(emojiId: string) { | ||
const emoji = args.emojis.find((e) => e.id === emojiId); | ||
if (!emoji) return; | ||
if (emoji.count === undefined) emoji.count = 0; | ||
emoji.count += emoji.selected ? -1 : 1; | ||
emoji.selected = !emoji.selected; | ||
// Enable for only allowing single reaction per user | ||
/* | ||
if (args.singleReaction && emoji.selected) { | ||
args.emojis.forEach((e) => { | ||
if (e.id !== emojiId && e.selected) { | ||
e.selected = false; | ||
e.count = (e.count || 1) - 1; | ||
} | ||
}); | ||
} | ||
*/ | ||
} | ||
</-script--> | ||
<template> | ||
<div class="h-16 flex items-center"> | ||
<BccReact v-bind="args" @toggle="onToggle" /> | ||
</div> | ||
</template> | ||
`, | ||
}, | ||
}, | ||
}; | ||
|
||
export const EmptyEmojis = Template.bind({}); | ||
EmptyEmojis.args = { | ||
top: true, | ||
placeholder: "No reactions yet", | ||
emojis: [ | ||
{ | ||
id: "thumbsup", | ||
emoji: "👍", | ||
count: 0, | ||
}, | ||
{ | ||
id: "happy", | ||
emoji: "😃", | ||
count: 0, | ||
}, | ||
{ | ||
id: "smile", | ||
emoji: "😊", | ||
count: 0, | ||
}, | ||
{ | ||
id: "glasses", | ||
emoji: "😎", | ||
count: 0, | ||
}, | ||
{ | ||
id: "love", | ||
emoji: "😍", | ||
count: 0, | ||
}, | ||
{ | ||
id: "stars", | ||
emoji: "🤩", | ||
count: 0, | ||
}, | ||
{ | ||
id: "rocket", | ||
emoji: "🚀", | ||
count: 0, | ||
}, | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
<script setup lang="ts"> | ||
import { AddReactionFillIcon, AddReactionIcon, KeyboardArrowLeftIcon } from "@bcc-code/icons-vue"; | ||
import { computed, ref } from "vue"; | ||
import BccReactEmoji from "./BccReactEmoji.vue"; | ||
import type { EmojiStat } from "./BccReactEmoji.vue"; | ||
type Props = { | ||
emojis: EmojiStat[]; | ||
top?: boolean; | ||
placeholder?: string; | ||
}; | ||
const props = withDefaults(defineProps<Props>(), { | ||
top: false, | ||
placeholder: "Be the first to react 😉", | ||
}); | ||
const emit = defineEmits<{ | ||
(e: "toggle", id: string): void; | ||
}>(); | ||
const activeEmojis = computed(() => { | ||
const active = props.emojis.filter((emoji) => emoji.count && emoji.count > 0); | ||
active.sort((a, b) => b.count! - a.count!); | ||
return active; | ||
}); | ||
const show = ref(false); | ||
function selectEmoji(emoji: EmojiStat) { | ||
emit("toggle", emoji.id); | ||
setTimeout(() => { | ||
show.value = false; | ||
}, 250); | ||
} | ||
</script> | ||
|
||
<template> | ||
<div class="bcc-react"> | ||
<TransitionGroup name="bcc-fade"> | ||
<button | ||
key="toggle" | ||
@click="show = !show" | ||
v-if="show || emojis.some((e) => !e.selected)" | ||
class="bcc-react-toggle" | ||
:class="[top ? 'rounded-b-full' : 'rounded-t-full']" | ||
> | ||
<AddReactionFillIcon v-if="show" class="w-6" /> | ||
<AddReactionIcon v-else class="w-6" /> | ||
</button> | ||
|
||
<div class="bcc-react-list"> | ||
<template v-if="activeEmojis.length > 0"> | ||
<TransitionGroup name="bcc-explode" appear> | ||
<template v-for="emoji in activeEmojis" :key="emoji.id"> | ||
<keep-alive> | ||
<BccReactEmoji @click="selectEmoji(emoji)" v-bind="emoji" /> | ||
</keep-alive> | ||
</template> | ||
</TransitionGroup> | ||
</template> | ||
<p v-else-if="placeholder" class="bcc-react-empty"> | ||
<KeyboardArrowLeftIcon class="mr-1 w-4" /> {{ placeholder }} | ||
</p> | ||
</div> | ||
</TransitionGroup> | ||
|
||
<Transition name="bcc-scale-fast"> | ||
<div | ||
key="list" | ||
v-if="show" | ||
class="bcc-react-selector" | ||
:class="{ 'bcc-react-selector--top': top }" | ||
> | ||
<TransitionGroup name="bcc-explode"> | ||
<template v-for="emoji in emojis" :key="emoji.id"> | ||
<button | ||
v-if="!emoji.selected" | ||
@click="selectEmoji(emoji)" | ||
class="bcc-react-selector-item" | ||
> | ||
{{ emoji.emoji }} | ||
</button> | ||
</template> | ||
</TransitionGroup> | ||
</div> | ||
</Transition> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<script setup lang="ts"> | ||
import { ref, watch } from "vue"; | ||
export type EmojiStat = { | ||
id: string; | ||
emoji: string; | ||
count?: number; | ||
selected?: boolean; | ||
}; | ||
const props = defineProps<EmojiStat>(); | ||
const animate = ref(false); | ||
watch( | ||
() => props.count, | ||
() => { | ||
animate.value = true; | ||
setTimeout(() => { | ||
animate.value = false; | ||
}, 1000); | ||
} | ||
); | ||
</script> | ||
|
||
<template> | ||
<button | ||
class="bcc-react-emoji-list-item" | ||
:class="{ | ||
'bcc-react-emoji-list-item--selected': selected, | ||
'animate-wiggle': animate, | ||
}" | ||
> | ||
<span>{{ emoji }}</span> | ||
<span v-if="count && count > 1" class="mx-1 text-xs">{{ count }}</span> | ||
</button> | ||
</template> |
18 changes: 18 additions & 0 deletions
18
design-library/src/components/BccReact/__snapshots__/BccReact.spec.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html | ||
|
||
exports[`BccReact > renders reactions 1`] = ` | ||
"<div class=\\"bcc-react\\"> | ||
<transition-group-stub name=\\"bcc-fade\\" appear=\\"false\\" persisted=\\"false\\" css=\\"true\\"><button class=\\"bcc-react-toggle rounded-t-full\\"><svg aria-hidden=\\"true\\" viewBox=\\"0 -960 960 960\\" fill=\\"currentColor\\" class=\\"w-6\\"> | ||
<path d=\\"M480-480Zm0 400q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q43 0 83 8.5t77 24.5v90q-35-20-75.5-31.5T480-800q-133 0-226.5 93.5T160-480q0 133 93.5 226.5T480-160q133 0 226.5-93.5T800-480q0-32-6.5-62T776-600h86q9 29 13.5 58.5T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm320-680h-40q-17 0-28.5-11.5T720-800q0-17 11.5-28.5T760-840h40v-40q0-17 11.5-28.5T840-920q17 0 28.5 11.5T880-880v40h40q17 0 28.5 11.5T960-800q0 17-11.5 28.5T920-760h-40v40q0 17-11.5 28.5T840-680q-17 0-28.5-11.5T800-720v-40ZM620-520q25 0 42.5-17.5T680-580q0-25-17.5-42.5T620-640q-25 0-42.5 17.5T560-580q0 25 17.5 42.5T620-520Zm-280 0q25 0 42.5-17.5T400-580q0-25-17.5-42.5T340-640q-25 0-42.5 17.5T280-580q0 25 17.5 42.5T340-520Zm140 260q58 0 107-28t79-76q6-12-1-24t-21-12H316q-14 0-21 12t-1 24q30 48 79.5 76T480-260Z\\"></path> | ||
</svg></button> | ||
<div class=\\"bcc-react-list\\"> | ||
<transition-group-stub name=\\"bcc-explode\\" appear=\\"true\\" persisted=\\"false\\" css=\\"true\\"><button class=\\"bcc-react-emoji-list-item\\"><span>😃</span><span class=\\"mx-1 text-xs\\">4</span></button><button class=\\"bcc-react-emoji-list-item\\"><span>👍</span> | ||
<!--v-if--> | ||
</button></transition-group-stub> | ||
</div> | ||
</transition-group-stub> | ||
<transition-stub name=\\"bcc-scale-fast\\" appear=\\"false\\" persisted=\\"false\\" css=\\"true\\"> | ||
<!--v-if--> | ||
</transition-stub> | ||
</div>" | ||
`; |
Oops, something went wrong.