@meith/theme-raidframe 0.7.0 → 0.9.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.
Files changed (38) hide show
  1. package/package.json +4 -4
  2. package/src/copy.ts +286 -0
  3. package/src/index.ts +2 -2
  4. package/src/messages/en.json +144 -0
  5. package/src/messages/index.ts +5 -0
  6. package/src/shared.tsx +1 -2
  7. package/src/slots/announcement.tsx +16 -6
  8. package/src/slots/auth-page.tsx +12 -3
  9. package/src/slots/board-index.tsx +10 -3
  10. package/src/slots/board-stats.tsx +18 -12
  11. package/src/slots/category-block.tsx +13 -6
  12. package/src/slots/discovery-view.tsx +17 -8
  13. package/src/slots/error-notice.tsx +17 -5
  14. package/src/slots/footer.tsx +16 -4
  15. package/src/slots/forum-display.tsx +20 -11
  16. package/src/slots/forum-row.tsx +26 -10
  17. package/src/slots/header.tsx +43 -10
  18. package/src/slots/latest-posts.tsx +12 -6
  19. package/src/slots/latest-threads.tsx +18 -8
  20. package/src/slots/member-profile.tsx +14 -10
  21. package/src/slots/navigation.tsx +6 -3
  22. package/src/slots/notice.tsx +7 -4
  23. package/src/slots/pagination.tsx +10 -6
  24. package/src/slots/panel-nav.tsx +40 -13
  25. package/src/slots/panel-page.tsx +12 -11
  26. package/src/slots/post-actions.tsx +17 -10
  27. package/src/slots/post-bit.tsx +29 -18
  28. package/src/slots/post-form.tsx +14 -4
  29. package/src/slots/redirect-notice.tsx +16 -8
  30. package/src/slots/search-form.tsx +12 -8
  31. package/src/slots/search-results.tsx +26 -16
  32. package/src/slots/shell.tsx +6 -3
  33. package/src/slots/subforum-list.tsx +8 -5
  34. package/src/slots/thread-row.tsx +19 -11
  35. package/src/slots/thread-view.tsx +22 -8
  36. package/src/slots/user-panel.tsx +14 -14
  37. package/src/slots/who-is-online.tsx +19 -10
  38. package/src/theme.ts +66 -0
@@ -1,10 +1,13 @@
1
- import type { ThreadRowSlotModel } from '@meith/theme-kit'
1
+ import type { SlotCopy, ThreadRowSlotModel } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
2
3
 
3
4
  import { MICRO, NUMERIC, ReadPip, Stamp, UserRef } from '../shared'
4
5
 
5
6
  const TAG = 'border px-1.5 py-px font-mono text-[0.625rem] font-bold uppercase tracking-[0.12em]'
6
7
 
7
- export function ThreadRow({ thread, select }: ThreadRowSlotModel) {
8
+ export function ThreadRow({ thread, select, copy }: ThreadRowSlotModel & { copy: SlotCopy }) {
9
+ const c = (key: string) => fromSlotCopy(copy, `raidframe.threadRow.${key}`)
10
+
8
11
  return (
9
12
  <tr className="border-t border-border align-top hover:bg-secondary/50">
10
13
  <td className="px-3 py-2.5">
@@ -31,40 +34,45 @@ export function ThreadRow({ thread, select }: ThreadRowSlotModel) {
31
34
  <a href={thread.href} className="font-medium text-foreground hover:text-primary">
32
35
  {thread.title}
33
36
  </a>
34
- {thread.isUnread && <span className="sr-only">(new posts)</span>}
37
+ {thread.isUnread && <span className="sr-only">{c('newPosts')}</span>}
35
38
 
36
39
  {thread.isSticky && (
37
- <span className={`${TAG} border-thread-pinned/60 text-thread-pinned`}>pinned</span>
40
+ <span className={`${TAG} border-thread-pinned/60 text-thread-pinned`}>
41
+ {c('pinned')}
42
+ </span>
38
43
  )}
39
44
  {thread.isLocked && (
40
- <span className={`${TAG} border-thread-locked/60 text-thread-locked`}>locked</span>
45
+ <span className={`${TAG} border-thread-locked/60 text-thread-locked`}>
46
+ {c('locked')}
47
+ </span>
41
48
  )}
42
49
  {thread.isMoved && (
43
- <span className={`${TAG} border-thread-moved/60 text-thread-moved`}>moved</span>
50
+ <span className={`${TAG} border-thread-moved/60 text-thread-moved`}>{c('moved')}</span>
44
51
  )}
45
52
  </div>
46
53
 
47
54
  <p className={`${MICRO} mt-1 normal-case`}>
48
- <span className="uppercase">started by</span>{' '}
55
+ <span className="uppercase">{c('startedBy')}</span>{' '}
49
56
  <UserRef user={thread.author} className="hover:text-primary" />
50
57
  </p>
51
58
  </td>
52
59
 
53
60
  <td className={`w-16 px-2 py-2.5 text-right text-xs ${NUMERIC} text-foreground`}>
54
- {thread.replyCount}
61
+ {thread.replyCount.label}
55
62
  </td>
56
63
  <td className={`w-16 px-2 py-2.5 text-right text-xs ${NUMERIC} text-muted-foreground`}>
57
- {thread.viewCount}
64
+ {thread.viewCount.label}
58
65
  </td>
59
66
 
60
67
  <td className="hidden w-52 px-3 py-2.5 text-xs text-muted-foreground sm:table-cell">
61
68
  {thread.lastPost === null ? (
62
- <span className={MICRO}>—</span>
69
+ <span className={MICRO}>{c('none')}</span>
63
70
  ) : (
64
71
  <a href={thread.lastPost.href} className="block hover:text-primary">
65
72
  <Stamp at={thread.lastPost.at} className="text-foreground" />
66
73
  <span className={`${MICRO} mt-0.5 block normal-case`}>
67
- by <UserRef user={thread.lastPost.author} linked={false} />
74
+ {c('byPrefix')}
75
+ <UserRef user={thread.lastPost.author} linked={false} />
68
76
  </span>
69
77
  </a>
70
78
  )}
@@ -1,14 +1,24 @@
1
- import type { ThreadViewModel } from '@meith/theme-kit'
1
+ import type { SlotCopy, ThreadViewModel } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
2
3
 
3
4
  import { BUTTON, BUTTON_PRIMARY, HEADING, MICRO, NUMERIC, RULE } from '../shared'
4
5
 
5
6
  const TAG = 'border px-1.5 py-px font-mono text-[0.625rem] font-bold uppercase tracking-[0.12em]'
6
7
 
7
- export function ThreadView({ thread, forum, replyHref, markReadAction, regions }: ThreadViewModel) {
8
+ export function ThreadView({
9
+ thread,
10
+ forum,
11
+ replyHref,
12
+ markReadAction,
13
+ regions,
14
+ copy,
15
+ }: ThreadViewModel & { copy: SlotCopy }) {
16
+ const c = (key: string) => fromSlotCopy(copy, `raidframe.threadView.${key}`)
17
+
8
18
  const reply =
9
19
  replyHref === null ? null : (
10
20
  <a href={replyHref} className={BUTTON_PRIMARY}>
11
- post reply
21
+ {c('postReply')}
12
22
  </a>
13
23
  )
14
24
 
@@ -26,15 +36,19 @@ export function ThreadView({ thread, forum, replyHref, markReadAction, regions }
26
36
 
27
37
  <p className="mt-1.5 flex flex-wrap items-center gap-2">
28
38
  {thread.isSticky && (
29
- <span className={`${TAG} border-thread-pinned/60 text-thread-pinned`}>pinned</span>
39
+ <span className={`${TAG} border-thread-pinned/60 text-thread-pinned`}>
40
+ {c('pinned')}
41
+ </span>
30
42
  )}
31
43
  {thread.isLocked && (
32
- <span className={`${TAG} border-thread-locked/60 text-thread-locked`}>locked</span>
44
+ <span className={`${TAG} border-thread-locked/60 text-thread-locked`}>
45
+ {c('locked')}
46
+ </span>
33
47
  )}
34
48
  <span className={`${MICRO} ${NUMERIC} normal-case`}>
35
- <span className="text-foreground">{thread.replyCount}</span> replies
49
+ <span className="text-foreground">{thread.replyCount.label}</span> {c('replies')}
36
50
  <span className="text-border">{' | '}</span>
37
- <span className="text-foreground">{thread.viewCount}</span> views
51
+ <span className="text-foreground">{thread.viewCount.label}</span> {c('views')}
38
52
  </span>
39
53
  </p>
40
54
  </div>
@@ -65,7 +79,7 @@ export function ThreadView({ thread, forum, replyHref, markReadAction, regions }
65
79
  {markReadAction !== null && (
66
80
  <form action={markReadAction} method="post">
67
81
  <button type="submit" className={BUTTON}>
68
- mark read
82
+ {c('markRead')}
69
83
  </button>
70
84
  </form>
71
85
  )}
@@ -1,5 +1,6 @@
1
+ import type { SlotCopy, UserPanelModel } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { Menu } from '@meith/ui/menu'
2
- import type { UserPanelModel } from '@meith/theme-kit'
3
4
 
4
5
  import { BUTTON, BUTTON_PRIMARY, MICRO } from '../shared'
5
6
 
@@ -30,7 +31,10 @@ export function UserPanel({
30
31
  notificationsHref,
31
32
  messagesHref,
32
33
  children,
33
- }: UserPanelModel) {
34
+ copy,
35
+ }: UserPanelModel & { copy: SlotCopy }) {
36
+ const c = (key: string) => fromSlotCopy(copy, `raidframe.userPanel.${key}`)
37
+
34
38
  if (viewer.isGuest) {
35
39
  return (
36
40
  <div className="flex flex-wrap items-center gap-2">
@@ -43,7 +47,7 @@ export function UserPanel({
43
47
  )
44
48
  }
45
49
 
46
- const name = viewer.username ?? 'signed in'
50
+ const name = viewer.username ?? c('signedIn')
47
51
 
48
52
  return (
49
53
  <div className="flex flex-wrap items-center gap-2">
@@ -54,26 +58,26 @@ export function UserPanel({
54
58
  }}
55
59
  />
56
60
 
57
- {unreadNotifications > 0 && (
61
+ {unreadNotifications.value > 0 && (
58
62
  <a
59
63
  href={notificationsHref}
60
64
  className={`${COUNT} border-primary/60 bg-primary/15 text-primary hover:border-primary`}
61
65
  >
62
- {unreadNotifications} new
66
+ {unreadNotifications.label} {c('new')}
63
67
  </a>
64
68
  )}
65
- {unreadMessages > 0 && (
69
+ {unreadMessages.value > 0 && (
66
70
  <a
67
71
  href={messagesHref}
68
72
  className={`${COUNT} border-forum-unread/60 bg-forum-unread/15 text-forum-unread hover:border-forum-unread`}
69
73
  >
70
- {unreadMessages} pm
74
+ {unreadMessages.label} {c('pm')}
71
75
  </a>
72
76
  )}
73
77
 
74
78
  <div data-account="menu" className="flex min-w-0 items-center">
75
79
  <Menu
76
- label="Your account"
80
+ label={c('accountLabel')}
77
81
  items={links}
78
82
  triggerClassName="rounded-none border-border bg-card px-2 py-1 hover:border-primary/70 hover:bg-card"
79
83
  trigger={
@@ -96,16 +100,12 @@ export function UserPanel({
96
100
  <nav
97
101
  data-account="plain"
98
102
  style={{ display: 'none' }}
99
- aria-label="Your account"
103
+ aria-label={c('accountLabel')}
100
104
  className="flex-wrap items-center gap-x-3 gap-y-1"
101
105
  >
102
106
  <span className={`${MICRO} text-foreground`}>{name}</span>
103
107
  {links.map((link) => (
104
- <a
105
- key={link.href}
106
- href={link.href}
107
- className={`${MICRO} hover:text-primary`}
108
- >
108
+ <a key={link.href} href={link.href} className={`${MICRO} hover:text-primary`}>
109
109
  {link.label}
110
110
  </a>
111
111
  ))}
@@ -1,20 +1,25 @@
1
- import type { WhoIsOnlineModel } from '@meith/theme-kit'
1
+ import type { SlotCopy, WhoIsOnlineModel } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
2
3
 
3
4
  import { Frame, MICRO, NUMERIC, PanelHead, Stamp, UserRef } from '../shared'
4
5
 
5
6
  export function WhoIsOnline({
6
7
  guestCount,
7
8
  members,
9
+ memberCount,
8
10
  total,
9
11
  recordCount,
10
12
  recordAt,
11
13
  fullListHref,
12
- }: WhoIsOnlineModel) {
14
+ copy,
15
+ }: WhoIsOnlineModel & { copy: SlotCopy }) {
16
+ const c = (key: string) => fromSlotCopy(copy, `raidframe.whoIsOnline.${key}`)
17
+
13
18
  return (
14
19
  <Frame aria-labelledby="who-is-online-heading">
15
20
  <PanelHead
16
21
  id="who-is-online-heading"
17
- title="Online now"
22
+ title={c('heading')}
18
23
  aside={
19
24
  <span className="inline-flex items-center gap-1.5 border border-moderation-approved/50 bg-moderation-approved/10 px-1.5 py-0.5">
20
25
  <span
@@ -24,21 +29,21 @@ export function WhoIsOnline({
24
29
  <span
25
30
  className={`${NUMERIC} text-[0.625rem] font-bold tracking-[0.12em] text-moderation-approved uppercase`}
26
31
  >
27
- {total} online
32
+ {total.label} {c('onlineSuffix')}
28
33
  </span>
29
34
  </span>
30
35
  }
31
36
  />
32
37
 
33
38
  <p className="px-3 py-2.5 text-xs">
34
- {members.length === 0 ? (
35
- <span className={MICRO}>no members</span>
39
+ {memberCount.value === 0 ? (
40
+ <span className={MICRO}>{c('noMembers')}</span>
36
41
  ) : (
37
42
  members.map((member, index) => (
38
43
  <span key={member.username}>
39
44
  {index > 0 && <span className="text-border">{' | '}</span>}
40
45
  <UserRef user={member} className="text-foreground hover:text-primary" />
41
- {member.isInvisible && <span className={`${MICRO} ml-1`}>hidden</span>}
46
+ {member.isInvisible && <span className={`${MICRO} ml-1`}>{c('hidden')}</span>}
42
47
  </span>
43
48
  ))
44
49
  )}
@@ -46,12 +51,16 @@ export function WhoIsOnline({
46
51
 
47
52
  <p className={`${MICRO} border-t border-border px-3 py-1.5 normal-case`}>
48
53
  <a href={fullListHref} className="uppercase hover:text-primary">
49
- full list
54
+ {c('fullList')}
50
55
  </a>
51
56
  <span className="text-border">{' | '}</span>
52
- <span className="uppercase">{guestCount} guests</span>
57
+ <span className="uppercase">
58
+ {guestCount.label} {c('guests')}
59
+ </span>
53
60
  <span className="text-border">{' | '}</span>
54
- <span className="uppercase">record {recordCount}</span>
61
+ <span className="uppercase">
62
+ {c('record')} {recordCount.label}
63
+ </span>
55
64
  {recordAt !== null && (
56
65
  <>
57
66
  {' '}
package/src/theme.ts CHANGED
@@ -1,6 +1,39 @@
1
1
  import { defaultTheme } from '@meith/theme-default'
2
2
  import { defineTheme } from '@meith/theme-kit'
3
3
 
4
+ import {
5
+ announcementCopy,
6
+ authPageCopy,
7
+ boardIndexCopy,
8
+ boardStatsCopy,
9
+ categoryBlockCopy,
10
+ discoveryViewCopy,
11
+ errorNoticeCopy,
12
+ footerCopy,
13
+ forumDisplayCopy,
14
+ forumRowCopy,
15
+ headerCopy,
16
+ latestPostsCopy,
17
+ latestThreadsCopy,
18
+ memberProfileCopy,
19
+ navigationCopy,
20
+ noticeCopy,
21
+ paginationCopy,
22
+ panelNavCopy,
23
+ panelPageCopy,
24
+ postActionsCopy,
25
+ postBitCopy,
26
+ postFormCopy,
27
+ redirectNoticeCopy,
28
+ searchFormCopy,
29
+ searchResultsCopy,
30
+ shellCopy,
31
+ subforumListCopy,
32
+ threadRowCopy,
33
+ threadViewCopy,
34
+ userPanelCopy,
35
+ whoIsOnlineCopy,
36
+ } from './copy'
4
37
  import { Announcement } from './slots/announcement'
5
38
  import { AuthPage } from './slots/auth-page'
6
39
  import { BoardIndex } from './slots/board-index'
@@ -81,4 +114,37 @@ export const raidframeTheme = defineTheme({
81
114
  RedirectNotice,
82
115
  ErrorNotice,
83
116
  },
117
+ copy: {
118
+ Announcement: announcementCopy,
119
+ AuthPage: authPageCopy,
120
+ BoardIndex: boardIndexCopy,
121
+ BoardStats: boardStatsCopy,
122
+ CategoryBlock: categoryBlockCopy,
123
+ DiscoveryView: discoveryViewCopy,
124
+ ErrorNotice: errorNoticeCopy,
125
+ Footer: footerCopy,
126
+ ForumDisplay: forumDisplayCopy,
127
+ ForumRow: forumRowCopy,
128
+ Header: headerCopy,
129
+ LatestPosts: latestPostsCopy,
130
+ LatestThreads: latestThreadsCopy,
131
+ MemberProfile: memberProfileCopy,
132
+ Navigation: navigationCopy,
133
+ Notice: noticeCopy,
134
+ Pagination: paginationCopy,
135
+ PanelNav: panelNavCopy,
136
+ PanelPage: panelPageCopy,
137
+ PostActions: postActionsCopy,
138
+ PostBit: postBitCopy,
139
+ PostForm: postFormCopy,
140
+ RedirectNotice: redirectNoticeCopy,
141
+ SearchForm: searchFormCopy,
142
+ SearchResults: searchResultsCopy,
143
+ Shell: shellCopy,
144
+ SubforumList: subforumListCopy,
145
+ ThreadRow: threadRowCopy,
146
+ ThreadView: threadViewCopy,
147
+ UserPanel: userPanelCopy,
148
+ WhoIsOnline: whoIsOnlineCopy,
149
+ },
84
150
  })