Skip to content

Commit 445485c

Browse files
Added ariakit comments implementation (#1448)
1 parent 4253e09 commit 445485c

File tree

10 files changed

+566
-8
lines changed

10 files changed

+566
-8
lines changed

packages/ariakit/src/ariakitStyles.css

+183
Original file line numberDiff line numberDiff line change
@@ -1003,4 +1003,187 @@ responsible for the majority of the styling. */
10031003

10041004
.bn-ak-link:where(.dark, .dark *) {
10051005
color: hsl(204 100% 64%);
1006+
}
1007+
1008+
/* https://ariakit.org/components/hovercard */
1009+
/*.bn-ak-button {*/
1010+
/* --border: rgb(0 0 0/13%);*/
1011+
/* --highlight: rgb(255 255 255/20%);*/
1012+
/* --shadow: rgb(0 0 0/10%);*/
1013+
/* display: flex;*/
1014+
/* height: 2.5rem;*/
1015+
/* user-select: none;*/
1016+
/* align-items: center;*/
1017+
/* justify-content: center;*/
1018+
/* gap: 0.25rem;*/
1019+
/* white-space: nowrap;*/
1020+
/* border-style: none;*/
1021+
/* background-color: white;*/
1022+
/* padding-left: 1rem;*/
1023+
/* padding-right: 1rem;*/
1024+
/* font-size: 1rem;*/
1025+
/* line-height: 1.5rem;*/
1026+
/* color: black;*/
1027+
/* text-decoration-line: none;*/
1028+
/* outline-width: 2px;*/
1029+
/* outline-offset: 2px;*/
1030+
/* outline-color: hsl(204 100% 40%);*/
1031+
/* box-shadow:*/
1032+
/* inset 0 0 0 1px var(--border),*/
1033+
/* inset 0 2px 0 var(--highlight),*/
1034+
/* inset 0 -1px 0 var(--shadow),*/
1035+
/* 0 1px 1px var(--shadow);*/
1036+
/* position: absolute;*/
1037+
/* top: 1rem;*/
1038+
/* right: 1rem;*/
1039+
/* border-radius: 9999px;*/
1040+
/* font-weight: 600;*/
1041+
/*}*/
1042+
1043+
/*.bn-ak-button:where(.dark, .dark *) {*/
1044+
/* --border: rgb(255 255 255/10%);*/
1045+
/* --highlight: rgb(255 255 255/5%);*/
1046+
/* --shadow: rgb(0 0 0/25%);*/
1047+
/* background-color: rgb(255 255 255 / 0.05);*/
1048+
/* color: white;*/
1049+
/* box-shadow:*/
1050+
/* inset 0 0 0 1px var(--border),*/
1051+
/* inset 0 -1px 0 1px var(--shadow),*/
1052+
/* inset 0 1px 0 var(--highlight);*/
1053+
/*}*/
1054+
1055+
/*.bn-ak-button:not(:active):hover {*/
1056+
/* --border: rgb(0 0 0/33%);*/
1057+
/*}*/
1058+
1059+
/*.bn-ak-button:where(.dark, .dark *):not(:active):hover {*/
1060+
/* --border: rgb(255 255 255/25%);*/
1061+
/*}*/
1062+
1063+
.bn-ak-primary {
1064+
--border: rgba(0, 0, 0, 0.15);
1065+
--highlight: rgba(255, 255, 255, 0.25);
1066+
--shadow: rgba(0, 0, 0, 0.15);
1067+
background-color: hsl(204 100% 40%);
1068+
color: white;
1069+
}
1070+
1071+
.bn-ak-primary:hover {
1072+
--border: rgba(0, 0, 0, 0.35);
1073+
background-color: hsl(204 100% 35%);
1074+
}
1075+
1076+
.bn-ak-primary:where(.dark, .dark *) {
1077+
--border: rgba(255, 255, 255, 0.25);
1078+
--highlight: rgba(255, 255, 255, 0.1);
1079+
--shadow: rgba(0, 0, 0, 0.25);
1080+
background-color: hsl(204 100% 35%);
1081+
}
1082+
1083+
.bn-ak-primary:hover:where(.dark, .dark *) {
1084+
--border: rgba(255, 255, 255, 0.45);
1085+
background-color: hsl(204 100% 40%);
1086+
}
1087+
1088+
.bn-ak-button[aria-disabled="true"] {
1089+
opacity: 0.5;
1090+
}
1091+
1092+
.bn-ak-button[data-focus-visible] {
1093+
outline-style: solid;
1094+
}
1095+
1096+
.bn-ak-button:active,
1097+
.bn-ak-button[data-active] {
1098+
padding-top: 0.125rem;
1099+
box-shadow:
1100+
inset 0 0 0 1px var(--border),
1101+
inset 0 2px 0 var(--border);
1102+
}
1103+
1104+
@media (min-width: 640px) {
1105+
.bn-ak-button {
1106+
gap: 0.5rem;
1107+
}
1108+
}
1109+
1110+
.bn-ak-button:active:where(.dark, .dark *),
1111+
.bn-ak-button[data-active]:where(.dark, .dark *) {
1112+
box-shadow:
1113+
inset 0 0 0 1px var(--border),
1114+
inset 0 1px 1px 1px var(--shadow);
1115+
}
1116+
1117+
.bn-ak-flat {
1118+
box-shadow: none;
1119+
}
1120+
1121+
.bn-ak-flat:where(.dark, .dark *) {
1122+
box-shadow: none;
1123+
}
1124+
1125+
.bn-ak-flat:active:where(.dark, .dark *),
1126+
.bn-ak-flat[data-active]:where(.dark, .dark *) {
1127+
box-shadow: none;
1128+
}
1129+
1130+
.bn-ak-anchor {
1131+
font-weight: 500;
1132+
color: hsl(204 100% 35%);
1133+
text-decoration-line: underline;
1134+
text-underline-offset: 0.25em;
1135+
text-decoration-skip-ink: none;
1136+
}
1137+
1138+
.bn-ak-anchor:hover {
1139+
text-decoration-thickness: 3px;
1140+
}
1141+
1142+
.bn-ak-anchor:where(.dark, .dark *) {
1143+
color: hsl(204 100% 64%);
1144+
}
1145+
1146+
.bn-ak-hovercard {
1147+
position: relative;
1148+
z-index: 50;
1149+
display: flex;
1150+
width: 300px;
1151+
flex-direction: column;
1152+
gap: 0.5rem;
1153+
border-radius: 0.5rem;
1154+
border-width: 1px;
1155+
border-style: solid;
1156+
border-color: hsl(204 20% 88%);
1157+
background-color: white;
1158+
padding: 1rem;
1159+
color: black;
1160+
box-shadow:
1161+
0 10px 15px -3px rgb(0 0 0 / 0.1),
1162+
0 4px 6px -4px rgb(0 0 0 / 0.1);
1163+
}
1164+
1165+
.bn-ak-hovercard:focus-visible,
1166+
.bn-ak-hovercard[data-focus-visible] {
1167+
outline: 2px solid hsl(204 100% 40%);
1168+
outline-offset: 2px;
1169+
}
1170+
1171+
.bn-ak-hovercard:where(.dark, .dark *) {
1172+
border-color: hsl(204 4% 24%);
1173+
background-color: hsl(204 4% 16%);
1174+
color: white;
1175+
box-shadow:
1176+
0 10px 15px -3px rgb(0 0 0 / 0.25),
1177+
0 4px 6px -4px rgb(0 0 0 / 0.1);
1178+
}
1179+
1180+
.bn-ak-avatar {
1181+
width: 4rem;
1182+
border-radius: 9999px;
1183+
}
1184+
1185+
.bn-ak-username {
1186+
font-size: 1.125rem;
1187+
line-height: 1.75rem;
1188+
font-weight: 600;
10061189
}

packages/ariakit/src/badge/Badge.tsx

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import {
2+
Button as AriakitButton,
3+
Group as AriakitGroup,
4+
Tooltip as AriakitTooltip,
5+
TooltipAnchor as AriakitTooltipAnchor,
6+
TooltipProvider as AriakitTooltipProvider,
7+
} from "@ariakit/react";
8+
9+
import { assertEmpty, mergeCSSClasses } from "@blocknote/core";
10+
import { ComponentProps } from "@blocknote/react";
11+
import { forwardRef } from "react";
12+
13+
export const Badge = forwardRef<
14+
HTMLButtonElement,
15+
ComponentProps["Generic"]["Badge"]["Root"]
16+
>((props, ref) => {
17+
const {
18+
className,
19+
text,
20+
icon,
21+
isSelected,
22+
mainTooltip,
23+
secondaryTooltip,
24+
onClick,
25+
...rest
26+
} = props;
27+
28+
assertEmpty(rest, false);
29+
30+
const badge = (
31+
<AriakitButton
32+
className={mergeCSSClasses(
33+
className,
34+
"bn-ak-badge bn-ak-button",
35+
isSelected && "bn-ak-primary"
36+
)}
37+
aria-selected={isSelected === true}
38+
onClick={(event) => onClick?.(event)}
39+
ref={ref}>
40+
<span>{icon}</span>
41+
<span>{text}</span>
42+
</AriakitButton>
43+
);
44+
45+
if (!mainTooltip) {
46+
return badge;
47+
}
48+
49+
return (
50+
<AriakitTooltipProvider>
51+
<AriakitTooltipAnchor render={badge} />
52+
<AriakitTooltip className="bn-ak-tooltip" portal={false}>
53+
<span>{mainTooltip}</span>
54+
{secondaryTooltip && <span>{secondaryTooltip}</span>}
55+
</AriakitTooltip>
56+
</AriakitTooltipProvider>
57+
);
58+
});
59+
60+
export const BadgeGroup = forwardRef<
61+
HTMLDivElement,
62+
ComponentProps["Generic"]["Badge"]["Group"]
63+
>((props, ref) => {
64+
const { className, children, ...rest } = props;
65+
66+
assertEmpty(rest);
67+
68+
return (
69+
<AriakitGroup
70+
className={mergeCSSClasses(className, "bn-ak-badge-group")}
71+
ref={ref}>
72+
{children}
73+
</AriakitGroup>
74+
);
75+
});
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { Group as AriakitGroup } from "@ariakit/react";
2+
3+
import { assertEmpty, mergeCSSClasses } from "@blocknote/core";
4+
import { ComponentProps } from "@blocknote/react";
5+
import { forwardRef } from "react";
6+
7+
export const Card = forwardRef<
8+
HTMLDivElement,
9+
ComponentProps["Comments"]["Card"]
10+
>((props, ref) => {
11+
const { className, children, ...rest } = props;
12+
13+
assertEmpty(rest, false);
14+
15+
return (
16+
<AriakitGroup
17+
className={mergeCSSClasses(className, "bn-ak-hovercard")}
18+
ref={ref}>
19+
{children}
20+
</AriakitGroup>
21+
);
22+
});
23+
24+
export const CardSection = forwardRef<
25+
HTMLDivElement,
26+
ComponentProps["Comments"]["CardSection"]
27+
>((props, ref) => {
28+
const { className, children, ...rest } = props;
29+
30+
assertEmpty(rest, false);
31+
32+
return (
33+
<AriakitGroup
34+
className={mergeCSSClasses(className, "bn-ak-card-section")}
35+
ref={ref}>
36+
{children}
37+
</AriakitGroup>
38+
);
39+
});
+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { Group as AriakitGroup } from "@ariakit/react";
2+
3+
import { assertEmpty } from "@blocknote/core";
4+
import { ComponentProps } from "@blocknote/react";
5+
import { forwardRef, useState } from "react";
6+
7+
const AuthorInfo = forwardRef<
8+
HTMLDivElement,
9+
Pick<ComponentProps["Comments"]["Comment"], "authorInfo" | "timeString">
10+
>((props, _ref) => {
11+
const { authorInfo, timeString, ...rest } = props;
12+
13+
assertEmpty(rest, false);
14+
15+
if (authorInfo === "loading") {
16+
return (
17+
<AriakitGroup className={"bn-ak-author-info"}>
18+
<div className={"bn-ak-avatar bn-ak-skeleton"} />
19+
<div className={"bn-ak-username bn-ak-skeleton"} />
20+
</AriakitGroup>
21+
);
22+
}
23+
24+
return (
25+
<AriakitGroup className={"bn-ak-author-info"}>
26+
<img
27+
src={authorInfo.avatarUrl}
28+
alt={authorInfo.username}
29+
className={"bn-ak-avatar"}
30+
/>
31+
<div className={"bn-ak-username"}>
32+
{authorInfo.username}
33+
<span>{timeString}</span>
34+
</div>
35+
</AriakitGroup>
36+
);
37+
});
38+
39+
export const Comment = forwardRef<
40+
HTMLDivElement,
41+
ComponentProps["Comments"]["Comment"]
42+
>((props, ref) => {
43+
const {
44+
className,
45+
showActions,
46+
authorInfo,
47+
timeString,
48+
actions,
49+
children,
50+
...rest
51+
} = props;
52+
53+
assertEmpty(rest, false);
54+
55+
const [hovered, setHovered] = useState(false);
56+
57+
const doShowActions =
58+
actions &&
59+
(showActions === true ||
60+
showActions === undefined ||
61+
(showActions === "hover" && hovered));
62+
63+
return (
64+
<AriakitGroup
65+
ref={ref}
66+
className={className}
67+
onMouseEnter={() => setHovered(true)}
68+
onMouseLeave={() => setHovered(false)}>
69+
{doShowActions ? (
70+
<AriakitGroup
71+
style={{
72+
position: "absolute",
73+
right: 0,
74+
top: 0,
75+
zIndex: 10,
76+
}}>
77+
{actions}
78+
</AriakitGroup>
79+
) : null}
80+
<AuthorInfo {...props} />
81+
{children}
82+
</AriakitGroup>
83+
);
84+
});

0 commit comments

Comments
 (0)