@meith/theme-clubhouse 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
+ import type { PostBitSlotModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { Alert, AlertDescription, AlertTitle, Avatar, Card } from '@meith/ui'
2
- import type { PostBitSlotModel } from '@meith/theme-kit'
3
4
 
4
5
  import { HEADING, LINK, MICRO, MICRO_BARE, MUTED_LINK, NUMERIC, Stamp, UserRef } from '../shared'
5
6
 
@@ -9,9 +10,17 @@ const VISIBILITY_TINT = {
9
10
  deleted: 'border-thread-deleted/50 bg-destructive/5',
10
11
  } as const
11
12
 
12
- function StatusBanner({ visibility }: { visibility: PostBitSlotModel['post']['visibility'] }) {
13
+ function StatusBanner({
14
+ visibility,
15
+ copy,
16
+ }: {
17
+ visibility: PostBitSlotModel['post']['visibility']
18
+ copy: SlotCopy
19
+ }) {
13
20
  if (visibility === 'visible') return null
14
21
 
22
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.postBit.${key}`)
23
+
15
24
  return (
16
25
  <Alert
17
26
  tone={visibility === 'deleted' ? 'error' : 'warning'}
@@ -19,9 +28,9 @@ function StatusBanner({ visibility }: { visibility: PostBitSlotModel['post']['vi
19
28
  >
20
29
  <AlertDescription>
21
30
  <AlertTitle>
22
- {visibility === 'deleted' ? 'Deleted post.' : 'Waiting for approval.'}
31
+ {visibility === 'deleted' ? c('deletedPost') : c('waitingApproval')}
23
32
  </AlertTitle>{' '}
24
- Only moderators can see this.
33
+ {c('staffOnly')}
25
34
  </AlertDescription>
26
35
  </Alert>
27
36
  )
@@ -65,10 +74,14 @@ function StatLine({ label, children }: { label: string; children: React.ReactNod
65
74
  function AuthorBlock({
66
75
  author,
67
76
  badges,
77
+ copy,
68
78
  }: {
69
79
  author: PostBitSlotModel['post']['author']
70
80
  badges: React.ReactNode
81
+ copy: SlotCopy
71
82
  }) {
83
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.postBit.${key}`)
84
+
72
85
  return (
73
86
  <>
74
87
  <div aria-hidden="true" className="h-12 border-b-2 border-b-secondary bg-primary" />
@@ -90,7 +103,7 @@ function AuthorBlock({
90
103
  {author.isOnline && (
91
104
  <p className="mt-1 flex items-center gap-1.5 text-xs text-moderation-approved">
92
105
  <span aria-hidden="true" className="size-1.5 rounded-full bg-moderation-approved" />
93
- Online
106
+ {c('online')}
94
107
  </p>
95
108
  )}
96
109
 
@@ -104,12 +117,12 @@ function AuthorBlock({
104
117
  </div>
105
118
 
106
119
  <dl className="mt-2.5 space-y-1 border-t border-border px-4 py-2.5">
107
- <StatLine label="Posts">{author.postCount.toLocaleString('en')}</StatLine>
120
+ <StatLine label={c('posts')}>{author.postCount.label}</StatLine>
108
121
  {author.reputation != null && (
109
- <StatLine label="Rep">{author.reputation.toLocaleString('en')}</StatLine>
122
+ <StatLine label={c('rep')}>{author.reputation.label}</StatLine>
110
123
  )}
111
124
  {author.joinedAt !== null && (
112
- <StatLine label="Joined">
125
+ <StatLine label={c('joined')}>
113
126
  <Stamp at={author.joinedAt} />
114
127
  </StatLine>
115
128
  )}
@@ -123,7 +136,9 @@ function AuthorBlock({
123
136
  )
124
137
  }
125
138
 
126
- export function PostBit({ post, select, regions }: PostBitSlotModel) {
139
+ export function PostBit({ post, select, regions, copy }: PostBitSlotModel & { copy: SlotCopy }) {
140
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.postBit.${key}`)
141
+
127
142
  return (
128
143
  <Card
129
144
  as="article"
@@ -132,11 +147,11 @@ export function PostBit({ post, select, regions }: PostBitSlotModel) {
132
147
  data-visibility={post.visibility}
133
148
  className={`target:bg-post-highlight ${VISIBILITY_TINT[post.visibility]}`}
134
149
  >
135
- <StatusBanner visibility={post.visibility} />
150
+ <StatusBanner visibility={post.visibility} copy={copy} />
136
151
 
137
152
  <div className="grid grid-cols-1 sm:grid-cols-[11rem_minmax(0,1fr)]">
138
153
  <div className="border-b border-border bg-surface pb-1 sm:border-r sm:border-b-0">
139
- <AuthorBlock author={post.author} badges={regions.pluginBadges} />
154
+ <AuthorBlock author={post.author} badges={regions.pluginBadges} copy={copy} />
140
155
  </div>
141
156
 
142
157
  <div className="min-w-0">
@@ -159,7 +174,7 @@ export function PostBit({ post, select, regions }: PostBitSlotModel) {
159
174
  <span
160
175
  className={`${MICRO_BARE} rounded-sm bg-primary px-1.5 py-0.5 text-primary-foreground`}
161
176
  >
162
- Opening post
177
+ {c('openingPost')}
163
178
  </span>
164
179
  )}
165
180
 
@@ -173,11 +188,11 @@ export function PostBit({ post, select, regions }: PostBitSlotModel) {
173
188
 
174
189
  {post.ignored !== null ? (
175
190
  <div className="px-4 py-5 text-sm text-muted-foreground">
176
- You are ignoring{' '}
177
- <span className="font-semibold text-foreground">{post.ignored.authorUsername}</span>.
178
- This post is hidden.{' '}
191
+ {c('ignoring')}{' '}
192
+ <span className="font-semibold text-foreground">{post.ignored.authorUsername}</span>.{' '}
193
+ {c('postHidden')}{' '}
179
194
  <a href={post.ignored.revealHref} className={`font-semibold text-foreground ${LINK}`}>
180
- Show it anyway
195
+ {c('showAnyway')}
181
196
  </a>
182
197
  </div>
183
198
  ) : (
@@ -199,7 +214,7 @@ export function PostBit({ post, select, regions }: PostBitSlotModel) {
199
214
  <div className="border-t border-border px-4 py-3">
200
215
  <h4 className={`${MICRO} mb-2`}>
201
216
  {post.attachments.length}{' '}
202
- {post.attachments.length === 1 ? 'attachment' : 'attachments'}
217
+ {post.attachments.length === 1 ? c('attachment.one') : c('attachment.other')}
203
218
  </h4>
204
219
  <ul className="flex flex-wrap gap-3">
205
220
  {post.attachments.map((file) => (
@@ -1,6 +1,7 @@
1
- import type { ShellModel } from '@meith/theme-kit'
1
+ import type { ShellModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
2
3
 
3
- export function Shell({ viewer, children }: ShellModel) {
4
+ export function Shell({ viewer, children, copy }: ShellModel & { copy: SlotCopy }) {
4
5
  return (
5
6
  <div
6
7
  className="flex min-h-dvh flex-col bg-background text-foreground"
@@ -10,7 +11,7 @@ export function Shell({ viewer, children }: ShellModel) {
10
11
  href="#board-content"
11
12
  className="sr-only focus-visible:not-sr-only focus-visible:absolute focus-visible:top-4 focus-visible:left-4 focus-visible:z-50 focus-visible:inline-flex focus-visible:h-9 focus-visible:items-center focus-visible:rounded-full focus-visible:border focus-visible:border-border focus-visible:bg-card focus-visible:px-4 focus-visible:text-sm focus-visible:font-semibold focus-visible:text-foreground focus-visible:shadow-elevation"
12
13
  >
13
- Skip to content
14
+ {fromSlotCopy(copy, 'clubhouse.shell.skipToContent')}
14
15
  </a>
15
16
 
16
17
  {children}
@@ -1,14 +1,17 @@
1
+ import type { SlotCopy, SubforumListModel } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { Card, CardContent } from '@meith/ui'
2
- import type { SubforumListModel } from '@meith/theme-kit'
3
4
 
4
5
  import { HEADING, LINK, MICRO, NUMERIC, PanelHead } from '../shared'
5
6
 
6
- export function SubforumList({ forums }: SubforumListModel) {
7
+ export function SubforumList({ forums, copy }: SubforumListModel & { copy: SlotCopy }) {
7
8
  if (forums.length === 0) return null
8
9
 
10
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.subforumList.${key}`)
11
+
9
12
  return (
10
13
  <Card aria-labelledby="subforums-heading">
11
- <PanelHead id="subforums-heading" title="Subforums" />
14
+ <PanelHead id="subforums-heading" title={c('title')} />
12
15
 
13
16
  <CardContent className="px-4 py-3">
14
17
  <ul className="flex flex-wrap gap-x-6 gap-y-2 text-sm">
@@ -19,8 +22,7 @@ export function SubforumList({ forums }: SubforumListModel) {
19
22
  </a>
20
23
  {forum.type !== 'link' && (
21
24
  <p className={`${MICRO} ${NUMERIC} mt-0.5`}>
22
- {forum.threadCount.toLocaleString('en')} threads ·{' '}
23
- {forum.postCount.toLocaleString('en')} posts
25
+ {forum.threadCount.label} {c('threads')} · {forum.postCount.label} {c('posts')}
24
26
  </p>
25
27
  )}
26
28
  </li>
@@ -1,9 +1,12 @@
1
+ import type { SlotCopy, ThreadRowSlotModel } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { Badge } from '@meith/ui'
2
- import type { ThreadRowSlotModel } from '@meith/theme-kit'
3
4
 
4
5
  import { HEADING, LINK, MICRO, Prefix, ReadMark, Stamp, TABLE_ROW, Tally, UserRef } from '../shared'
5
6
 
6
- export function ThreadRow({ thread, select }: ThreadRowSlotModel) {
7
+ export function ThreadRow({ thread, select, copy }: ThreadRowSlotModel & { copy: SlotCopy }) {
8
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.threadRow.${key}`)
9
+
7
10
  return (
8
11
  <li
9
12
  data-unread={thread.isUnread ? '' : undefined}
@@ -29,9 +32,9 @@ export function ThreadRow({ thread, select }: ThreadRowSlotModel) {
29
32
  <div className="min-w-0">
30
33
  <div className="flex flex-wrap items-baseline gap-x-2 gap-y-1">
31
34
  {thread.prefix !== null && <Prefix prefix={thread.prefix} />}
32
- {thread.isSticky && <Badge tone="pinned">Pinned</Badge>}
33
- {thread.isLocked && <Badge tone="locked">Locked</Badge>}
34
- {thread.isMoved && <Badge tone="moved">Moved</Badge>}
35
+ {thread.isSticky && <Badge tone="pinned">{c('pinned')}</Badge>}
36
+ {thread.isLocked && <Badge tone="locked">{c('locked')}</Badge>}
37
+ {thread.isMoved && <Badge tone="moved">{c('moved')}</Badge>}
35
38
 
36
39
  <a
37
40
  href={thread.href}
@@ -39,35 +42,35 @@ export function ThreadRow({ thread, select }: ThreadRowSlotModel) {
39
42
  >
40
43
  {thread.title}
41
44
  </a>
42
- {thread.isUnread && <span className="sr-only"> (new posts)</span>}
45
+ {thread.isUnread && <span className="sr-only"> {c('newPosts')}</span>}
43
46
  </div>
44
47
 
45
48
  <p className="mt-0.5 text-xs text-muted-foreground">
46
- Started by <UserRef user={thread.author} className="font-medium" />
49
+ {c('startedBy')} <UserRef user={thread.author} className="font-medium" />
47
50
  </p>
48
51
  </div>
49
52
 
50
53
  <span className="col-start-2 md:col-start-3 md:block md:text-right">
51
- <Tally value={thread.replyCount} label="replies" />
54
+ <Tally value={thread.replyCount} label={c('replies')} />
52
55
  <span className="ms-3 md:hidden">
53
- <Tally value={thread.viewCount} label="views" />
56
+ <Tally value={thread.viewCount} label={c('views')} />
54
57
  </span>
55
58
  </span>
56
59
 
57
60
  <span className="hidden md:block md:text-right">
58
- <Tally value={thread.viewCount} label="views" />
61
+ <Tally value={thread.viewCount} label={c('views')} />
59
62
  </span>
60
63
 
61
64
  <div className="col-start-2 min-w-0 text-xs text-muted-foreground md:col-start-5">
62
65
  {thread.lastPost === null ? (
63
- <span className={MICRO}>No replies yet</span>
66
+ <span className={MICRO}>{c('noRepliesYet')}</span>
64
67
  ) : (
65
68
  <>
66
69
  <a
67
70
  href={thread.lastPost.href}
68
71
  className={`block font-semibold text-foreground ${LINK}`}
69
72
  >
70
- Latest reply
73
+ {c('latestReply')}
71
74
  </a>
72
75
  <span className="mt-0.5 block truncate">
73
76
  <UserRef user={thread.lastPost.author} className="font-medium" />
@@ -1,9 +1,19 @@
1
+ import type { SlotCopy, ThreadViewModel } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { Badge, cn } from '@meith/ui'
2
- import type { ThreadViewModel } from '@meith/theme-kit'
3
4
 
4
5
  import { BUTTON, HEADING, MICRO, MUTED_LINK, NUMERIC, PAGE_BODY, PageHead, Prefix } from '../shared'
5
6
 
6
- export function ThreadView({ thread, forum, replyHref, markReadAction, regions }: ThreadViewModel) {
7
+ export function ThreadView({
8
+ thread,
9
+ forum,
10
+ replyHref,
11
+ markReadAction,
12
+ regions,
13
+ copy,
14
+ }: ThreadViewModel & { copy: SlotCopy }) {
15
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.threadView.${key}`)
16
+
7
17
  return (
8
18
  <div className={PAGE_BODY}>
9
19
  <PageHead
@@ -18,7 +28,7 @@ export function ThreadView({ thread, forum, replyHref, markReadAction, regions }
18
28
  'bg-secondary text-secondary-foreground hover:bg-secondary/80',
19
29
  )}
20
30
  >
21
- Mark read
31
+ {c('markRead')}
22
32
  </button>
23
33
  </form>
24
34
  )}
@@ -27,7 +37,7 @@ export function ThreadView({ thread, forum, replyHref, markReadAction, regions }
27
37
  href={replyHref}
28
38
  className={cn(BUTTON, 'bg-primary text-primary-foreground hover:bg-primary-hover')}
29
39
  >
30
- Reply
40
+ {c('reply')}
31
41
  </a>
32
42
  )}
33
43
  </>
@@ -41,13 +51,12 @@ export function ThreadView({ thread, forum, replyHref, markReadAction, regions }
41
51
 
42
52
  <div className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1">
43
53
  {thread.prefix !== null && <Prefix prefix={thread.prefix} />}
44
- {thread.isSticky && <Badge tone="pinned">Pinned</Badge>}
45
- {thread.isLocked && <Badge tone="locked">Locked — no new replies</Badge>}
46
- {thread.isMoved && <Badge tone="moved">Moved</Badge>}
54
+ {thread.isSticky && <Badge tone="pinned">{c('pinned')}</Badge>}
55
+ {thread.isLocked && <Badge tone="locked">{c('lockedNoReplies')}</Badge>}
56
+ {thread.isMoved && <Badge tone="moved">{c('moved')}</Badge>}
47
57
 
48
58
  <span className={`${MICRO} ${NUMERIC}`}>
49
- {thread.replyCount.toLocaleString('en')} replies ·{' '}
50
- {thread.viewCount.toLocaleString('en')} views
59
+ {thread.replyCount.label} {c('replies')} · {thread.viewCount.label} {c('views')}
51
60
  </span>
52
61
  </div>
53
62
  </PageHead>
@@ -1,6 +1,7 @@
1
+ import type { LinkModel, SlotCopy, UserPanelModel } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { Avatar, cn } from '@meith/ui'
2
4
  import { Menu } from '@meith/ui/menu'
3
- import type { LinkModel, UserPanelModel } from '@meith/theme-kit'
4
5
 
5
6
  import { BUTTON, MUTED_LINK } from '../shared'
6
7
 
@@ -36,7 +37,10 @@ export function UserPanel({
36
37
  notificationsHref,
37
38
  messagesHref,
38
39
  children,
39
- }: UserPanelModel) {
40
+ copy,
41
+ }: UserPanelModel & { copy: SlotCopy }) {
42
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.userPanel.${key}`)
43
+
40
44
  if (viewer.isGuest) {
41
45
  return (
42
46
  <div className="flex items-center gap-2">
@@ -58,7 +62,7 @@ export function UserPanel({
58
62
  )
59
63
  }
60
64
 
61
- const name = viewer.username ?? 'Signed in'
65
+ const name = viewer.username ?? c('signedIn')
62
66
 
63
67
  return (
64
68
  <div className="flex min-w-0 flex-col items-start gap-1 sm:items-end">
@@ -70,24 +74,24 @@ export function UserPanel({
70
74
  />
71
75
 
72
76
  <div className="flex min-w-0 items-center gap-2">
73
- {unreadNotifications > 0 && (
77
+ {unreadNotifications.value > 0 && (
74
78
  <Count href={notificationsHref} className="bg-primary text-primary-foreground">
75
- {unreadNotifications}
76
- <span className="sr-only"> unread notifications</span>
77
- <span aria-hidden="true">new</span>
79
+ {unreadNotifications.label}
80
+ <span className="sr-only"> {c('unreadNotifications')}</span>
81
+ <span aria-hidden="true">{c('new')}</span>
78
82
  </Count>
79
83
  )}
80
- {unreadMessages > 0 && (
84
+ {unreadMessages.value > 0 && (
81
85
  <Count href={messagesHref} className="border border-border text-foreground">
82
- {unreadMessages}
83
- <span className="sr-only"> unread messages</span>
84
- <span aria-hidden="true">unread</span>
86
+ {unreadMessages.label}
87
+ <span className="sr-only"> {c('unreadMessages')}</span>
88
+ <span aria-hidden="true">{c('unread')}</span>
85
89
  </Count>
86
90
  )}
87
91
 
88
92
  <span data-account="menu" className="flex min-w-0 items-center">
89
93
  <Menu
90
- label="Your account"
94
+ label={c('yourAccount')}
91
95
  items={links}
92
96
  triggerClassName="rounded-full px-2 py-1"
93
97
  trigger={
@@ -124,7 +128,7 @@ export function UserPanel({
124
128
  <nav
125
129
  data-account="plain"
126
130
  style={{ display: 'none' }}
127
- aria-label="Your account"
131
+ aria-label={c('yourAccount')}
128
132
  className="flex-wrap items-center gap-x-3 gap-y-1 text-xs sm:justify-end"
129
133
  >
130
134
  <span className="font-semibold text-foreground">{name}</span>
@@ -1,5 +1,6 @@
1
+ import type { OnlineMemberModel, SlotCopy, WhoIsOnlineModel } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { Badge } from '@meith/ui'
2
- import type { OnlineMemberModel, WhoIsOnlineModel } from '@meith/theme-kit'
3
4
 
4
5
  import { LINK, MICRO, NUMERIC, Stamp, UserRef } from '../shared'
5
6
 
@@ -8,39 +9,44 @@ const VISIBLE_NAMES = 12
8
9
  export function WhoIsOnline({
9
10
  guestCount,
10
11
  members,
12
+ memberCount,
11
13
  total,
12
14
  recordCount,
13
15
  recordAt,
14
16
  fullListHref,
15
- }: WhoIsOnlineModel) {
17
+ copy,
18
+ }: WhoIsOnlineModel & { copy: SlotCopy }) {
16
19
  const shown = members.slice(0, VISIBLE_NAMES)
17
20
  const rest = members.slice(VISIBLE_NAMES)
18
21
 
22
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.whoIsOnline.${key}`)
23
+
19
24
  return (
20
25
  <section
21
26
  aria-labelledby="who-is-online-heading"
22
27
  className="flex flex-col gap-1.5 text-xs text-muted-foreground"
23
28
  >
24
29
  <h2 id="who-is-online-heading" className={MICRO}>
25
- In the clubhouse
30
+ {c('heading')}
26
31
  </h2>
27
32
 
28
33
  <p className={NUMERIC}>
29
- <span className="font-semibold text-foreground">{total.toLocaleString('en')}</span> online{' '}
30
- {members.length.toLocaleString('en')} {members.length === 1 ? 'member' : 'members'},{' '}
31
- {guestCount.toLocaleString('en')} {guestCount === 1 ? 'guest' : 'guests'}
34
+ <span className="font-semibold text-foreground">{total.label}</span> {c('online')}{' '}
35
+ {memberCount.label} {memberCount.value === 1 ? c('member.one') : c('member.other')},{' '}
36
+ {guestCount.label} {guestCount.value === 1 ? c('guest.one') : c('guest.other')}
32
37
  </p>
33
38
 
34
- {members.length === 0 ? (
35
- <p>
36
- {guestCount === 0
37
- ? 'Nobody is reading the board right now.'
38
- : 'Only guests are reading the board right now.'}
39
- </p>
39
+ {memberCount.value === 0 ? (
40
+ <p>{guestCount.value === 0 ? c('nobody') : c('onlyGuests')}</p>
40
41
  ) : (
41
42
  <p className="min-w-0">
42
43
  {shown.map((member, index) => (
43
- <Name key={member.userId ?? member.username} member={member} first={index === 0} />
44
+ <Name
45
+ key={member.userId ?? member.username}
46
+ member={member}
47
+ first={index === 0}
48
+ copy={copy}
49
+ />
44
50
  ))}
45
51
 
46
52
  {rest.length > 0 && (
@@ -48,12 +54,17 @@ export function WhoIsOnline({
48
54
  <summary
49
55
  className={`inline cursor-default list-none ${LINK} [&::-webkit-details-marker]:hidden [&::marker]:content-none`}
50
56
  >
51
- {' and '}
52
- <span className={NUMERIC}>{rest.length.toLocaleString('en')}</span> more
57
+ {' '}
58
+ {c('and')} <span className={NUMERIC}>{rest.length}</span> {c('more')}
53
59
  </summary>
54
60
  {': '}
55
61
  {rest.map((member, index) => (
56
- <Name key={member.userId ?? member.username} member={member} first={index === 0} />
62
+ <Name
63
+ key={member.userId ?? member.username}
64
+ member={member}
65
+ first={index === 0}
66
+ copy={copy}
67
+ />
57
68
  ))}
58
69
  </details>
59
70
  )}
@@ -62,11 +73,11 @@ export function WhoIsOnline({
62
73
 
63
74
  <p className="flex flex-wrap items-baseline gap-x-3 gap-y-1">
64
75
  <a href={fullListHref} className={`font-semibold text-foreground ${LINK}`}>
65
- See everyone online
76
+ {c('seeEveryone')}
66
77
  </a>
67
78
  {recordAt !== null && (
68
79
  <span className={`ms-auto ${NUMERIC}`}>
69
- Record: {recordCount.toLocaleString('en')} on <Stamp at={recordAt} />
80
+ {c('record')} {recordCount.label} on <Stamp at={recordAt} />
70
81
  </span>
71
82
  )}
72
83
  </p>
@@ -74,7 +85,15 @@ export function WhoIsOnline({
74
85
  )
75
86
  }
76
87
 
77
- function Name({ member, first }: { member: OnlineMemberModel; first: boolean }) {
88
+ function Name({
89
+ member,
90
+ first,
91
+ copy,
92
+ }: {
93
+ member: OnlineMemberModel
94
+ first: boolean
95
+ copy: SlotCopy
96
+ }) {
78
97
  return (
79
98
  <>
80
99
  {!first && ', '}
@@ -82,7 +101,7 @@ function Name({ member, first }: { member: OnlineMemberModel; first: boolean })
82
101
  {member.isInvisible && (
83
102
  <>
84
103
  {' '}
85
- <Badge tone="neutral">Invisible</Badge>
104
+ <Badge tone="neutral">{fromSlotCopy(copy, 'clubhouse.whoIsOnline.invisible')}</Badge>
86
105
  </>
87
106
  )}
88
107
  </>
package/src/theme.ts CHANGED
@@ -1,6 +1,30 @@
1
1
  import { defaultTheme } from '@meith/theme-default'
2
2
  import { defineTheme } from '@meith/theme-kit'
3
3
 
4
+ import {
5
+ announcementCopy,
6
+ boardIndexCopy,
7
+ boardStatsCopy,
8
+ categoryBlockCopy,
9
+ footerCopy,
10
+ forumDisplayCopy,
11
+ forumRowCopy,
12
+ headerCopy,
13
+ latestPostsCopy,
14
+ latestThreadsCopy,
15
+ memberProfileCopy,
16
+ navigationCopy,
17
+ noticeCopy,
18
+ paginationCopy,
19
+ postActionsCopy,
20
+ postBitCopy,
21
+ shellCopy,
22
+ subforumListCopy,
23
+ threadRowCopy,
24
+ threadViewCopy,
25
+ userPanelCopy,
26
+ whoIsOnlineCopy,
27
+ } from './copy'
4
28
  import { Announcement } from './slots/announcement'
5
29
  import { BoardIndex } from './slots/board-index'
6
30
  import { BoardStats } from './slots/board-stats'
@@ -56,4 +80,28 @@ export const clubhouseTheme = defineTheme({
56
80
 
57
81
  MemberProfile,
58
82
  },
83
+ copy: {
84
+ Announcement: announcementCopy,
85
+ BoardIndex: boardIndexCopy,
86
+ BoardStats: boardStatsCopy,
87
+ CategoryBlock: categoryBlockCopy,
88
+ Footer: footerCopy,
89
+ ForumDisplay: forumDisplayCopy,
90
+ ForumRow: forumRowCopy,
91
+ Header: headerCopy,
92
+ LatestPosts: latestPostsCopy,
93
+ LatestThreads: latestThreadsCopy,
94
+ MemberProfile: memberProfileCopy,
95
+ Navigation: navigationCopy,
96
+ Notice: noticeCopy,
97
+ Pagination: paginationCopy,
98
+ PostActions: postActionsCopy,
99
+ PostBit: postBitCopy,
100
+ Shell: shellCopy,
101
+ SubforumList: subforumListCopy,
102
+ ThreadRow: threadRowCopy,
103
+ ThreadView: threadViewCopy,
104
+ UserPanel: userPanelCopy,
105
+ WhoIsOnline: whoIsOnlineCopy,
106
+ },
59
107
  })