@miketromba/issy-app 0.1.1 → 0.1.5
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.
- package/dist/app.js +304 -0
- package/dist/index.html +13 -0
- package/dist/server.js +1899 -0
- package/dist/styles.css +1 -0
- package/package.json +18 -13
- package/bunfig.toml +0 -2
- package/src/App.tsx +0 -346
- package/src/components/Badge.tsx +0 -51
- package/src/components/ConfirmModal.tsx +0 -72
- package/src/components/CreateIssueModal.tsx +0 -201
- package/src/components/EditIssueModal.tsx +0 -215
- package/src/components/FilterBar.tsx +0 -209
- package/src/components/IssueDetail.tsx +0 -184
- package/src/components/IssueList.tsx +0 -73
- package/src/components/QueryHelpModal.tsx +0 -156
- package/src/frontend.tsx +0 -20
- package/src/index.css +0 -99
- package/src/index.html +0 -12
- package/src/index.ts +0 -163
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
import hljs from 'highlight.js'
|
|
2
|
-
import { marked, Renderer } from 'marked'
|
|
3
|
-
import 'highlight.js/styles/github-dark.css'
|
|
4
|
-
import { formatDisplayDate, formatFullDate } from '@miketromba/issy-core'
|
|
5
|
-
import type { Issue } from '../App'
|
|
6
|
-
import { Badge } from './Badge'
|
|
7
|
-
|
|
8
|
-
interface IssueDetailProps {
|
|
9
|
-
issue: Issue
|
|
10
|
-
onBack?: () => void
|
|
11
|
-
onEdit?: () => void
|
|
12
|
-
onClose?: () => void
|
|
13
|
-
onReopen?: () => void
|
|
14
|
-
onDelete?: () => void
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Custom renderer with syntax highlighting
|
|
18
|
-
const renderer = new Renderer()
|
|
19
|
-
renderer.code = ({ text, lang }) => {
|
|
20
|
-
const language = lang && hljs.getLanguage(lang) ? lang : 'plaintext'
|
|
21
|
-
const highlighted = hljs.highlight(text, { language }).value
|
|
22
|
-
return `<pre><code class="hljs language-${language}">${highlighted}</code></pre>`
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
marked.setOptions({
|
|
26
|
-
gfm: true,
|
|
27
|
-
breaks: true,
|
|
28
|
-
renderer,
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
export function IssueDetail({
|
|
32
|
-
issue,
|
|
33
|
-
onBack,
|
|
34
|
-
onEdit,
|
|
35
|
-
onClose,
|
|
36
|
-
onReopen,
|
|
37
|
-
onDelete,
|
|
38
|
-
}: IssueDetailProps) {
|
|
39
|
-
const labels =
|
|
40
|
-
issue.frontmatter.labels
|
|
41
|
-
?.split(',')
|
|
42
|
-
.map((l) => l.trim())
|
|
43
|
-
.filter(Boolean) || []
|
|
44
|
-
const isOpen = issue.frontmatter.status === 'open'
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<div className="max-w-[800px] mx-auto px-4 md:px-10 py-6 md:py-8">
|
|
48
|
-
{/* Mobile back button */}
|
|
49
|
-
{onBack && (
|
|
50
|
-
<button
|
|
51
|
-
onClick={onBack}
|
|
52
|
-
className="md:hidden inline-flex items-center gap-1.5 mb-4 text-text-secondary text-sm"
|
|
53
|
-
>
|
|
54
|
-
<svg
|
|
55
|
-
width="16"
|
|
56
|
-
height="16"
|
|
57
|
-
viewBox="0 0 24 24"
|
|
58
|
-
fill="none"
|
|
59
|
-
stroke="currentColor"
|
|
60
|
-
strokeWidth="2"
|
|
61
|
-
>
|
|
62
|
-
<path d="M15 19l-7-7 7-7" />
|
|
63
|
-
</svg>
|
|
64
|
-
Back to issues
|
|
65
|
-
</button>
|
|
66
|
-
)}
|
|
67
|
-
|
|
68
|
-
<div className="mb-6">
|
|
69
|
-
<div className="flex items-start justify-between gap-3 mb-3">
|
|
70
|
-
<h1 className="text-xl md:text-2xl font-semibold text-text-primary leading-tight">
|
|
71
|
-
{issue.frontmatter.title || 'Untitled Issue'}
|
|
72
|
-
<span className="font-normal text-text-muted ml-2">
|
|
73
|
-
#{issue.id}
|
|
74
|
-
</span>
|
|
75
|
-
</h1>
|
|
76
|
-
|
|
77
|
-
{/* Action buttons */}
|
|
78
|
-
<div className="flex items-center gap-1 shrink-0">
|
|
79
|
-
{onEdit && (
|
|
80
|
-
<button
|
|
81
|
-
onClick={onEdit}
|
|
82
|
-
title="Edit issue"
|
|
83
|
-
className="p-2 text-text-muted hover:text-text-primary hover:bg-surface rounded-lg transition-colors"
|
|
84
|
-
>
|
|
85
|
-
<svg
|
|
86
|
-
width="16"
|
|
87
|
-
height="16"
|
|
88
|
-
viewBox="0 0 24 24"
|
|
89
|
-
fill="none"
|
|
90
|
-
stroke="currentColor"
|
|
91
|
-
strokeWidth="2"
|
|
92
|
-
>
|
|
93
|
-
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
|
|
94
|
-
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
|
|
95
|
-
</svg>
|
|
96
|
-
</button>
|
|
97
|
-
)}
|
|
98
|
-
|
|
99
|
-
{onDelete && (
|
|
100
|
-
<button
|
|
101
|
-
onClick={onDelete}
|
|
102
|
-
title="Delete issue"
|
|
103
|
-
className="p-2 text-text-muted hover:text-red-400 hover:bg-red-500/10 rounded-lg transition-colors"
|
|
104
|
-
>
|
|
105
|
-
<svg
|
|
106
|
-
width="16"
|
|
107
|
-
height="16"
|
|
108
|
-
viewBox="0 0 24 24"
|
|
109
|
-
fill="none"
|
|
110
|
-
stroke="currentColor"
|
|
111
|
-
strokeWidth="2"
|
|
112
|
-
>
|
|
113
|
-
<path d="M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
|
|
114
|
-
</svg>
|
|
115
|
-
</button>
|
|
116
|
-
)}
|
|
117
|
-
|
|
118
|
-
{isOpen && onClose && (
|
|
119
|
-
<button
|
|
120
|
-
onClick={onClose}
|
|
121
|
-
title="Close issue"
|
|
122
|
-
className="ml-1 px-3 py-1.5 text-xs font-medium text-text-secondary hover:text-text-primary bg-surface hover:bg-surface-elevated border border-border rounded-lg transition-colors"
|
|
123
|
-
>
|
|
124
|
-
Close
|
|
125
|
-
</button>
|
|
126
|
-
)}
|
|
127
|
-
|
|
128
|
-
{!isOpen && onReopen && (
|
|
129
|
-
<button
|
|
130
|
-
onClick={onReopen}
|
|
131
|
-
title="Reopen issue"
|
|
132
|
-
className="ml-1 px-3 py-1.5 text-xs font-medium text-green-400 hover:text-green-300 bg-green-500/10 hover:bg-green-500/20 border border-green-500/30 rounded-lg transition-colors"
|
|
133
|
-
>
|
|
134
|
-
Reopen
|
|
135
|
-
</button>
|
|
136
|
-
)}
|
|
137
|
-
</div>
|
|
138
|
-
</div>
|
|
139
|
-
|
|
140
|
-
{issue.frontmatter.description && (
|
|
141
|
-
<p className="text-[15px] text-text-secondary leading-relaxed mb-4">
|
|
142
|
-
{issue.frontmatter.description}
|
|
143
|
-
</p>
|
|
144
|
-
)}
|
|
145
|
-
|
|
146
|
-
<div className="flex flex-wrap items-center gap-2 text-sm">
|
|
147
|
-
{issue.frontmatter.priority && (
|
|
148
|
-
<Badge variant="priority" value={issue.frontmatter.priority} />
|
|
149
|
-
)}
|
|
150
|
-
|
|
151
|
-
{issue.frontmatter.status && (
|
|
152
|
-
<Badge variant="status" value={issue.frontmatter.status} />
|
|
153
|
-
)}
|
|
154
|
-
|
|
155
|
-
{issue.frontmatter.type && (
|
|
156
|
-
<Badge variant="type" value={issue.frontmatter.type} />
|
|
157
|
-
)}
|
|
158
|
-
|
|
159
|
-
{labels.map((label) => (
|
|
160
|
-
<Badge key={label} variant="label" value={label} />
|
|
161
|
-
))}
|
|
162
|
-
|
|
163
|
-
{issue.frontmatter.created && (
|
|
164
|
-
<span
|
|
165
|
-
className="text-xs text-text-muted"
|
|
166
|
-
title={formatFullDate(issue.frontmatter.created)}
|
|
167
|
-
>
|
|
168
|
-
{formatDisplayDate(issue.frontmatter.created)}
|
|
169
|
-
</span>
|
|
170
|
-
)}
|
|
171
|
-
</div>
|
|
172
|
-
</div>
|
|
173
|
-
|
|
174
|
-
<hr className="border-0 border-t border-border my-6" />
|
|
175
|
-
|
|
176
|
-
<div
|
|
177
|
-
className="prose prose-invert prose-sm max-w-none prose-a:text-accent prose-pre:border-0 prose-pre:shadow-none prose-code:bg-surface-elevated prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:before:content-none prose-code:after:content-none"
|
|
178
|
-
dangerouslySetInnerHTML={{
|
|
179
|
-
__html: marked.parse(issue.content) as string,
|
|
180
|
-
}}
|
|
181
|
-
/>
|
|
182
|
-
</div>
|
|
183
|
-
)
|
|
184
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { formatDisplayDate, formatFullDate } from '@miketromba/issy-core'
|
|
2
|
-
import type { Issue } from '../App'
|
|
3
|
-
import { Badge } from './Badge'
|
|
4
|
-
|
|
5
|
-
interface IssueListProps {
|
|
6
|
-
issues: Issue[]
|
|
7
|
-
selectedId: string | null
|
|
8
|
-
onSelect: (id: string) => void
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function IssueList({ issues, selectedId, onSelect }: IssueListProps) {
|
|
12
|
-
if (issues.length === 0) {
|
|
13
|
-
return (
|
|
14
|
-
<div className="px-5 py-6 text-text-muted text-sm">No issues found</div>
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<>
|
|
20
|
-
{issues.map((issue) => {
|
|
21
|
-
const isSelected = issue.id === selectedId
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<button
|
|
25
|
-
key={issue.id}
|
|
26
|
-
onClick={() => onSelect(issue.id)}
|
|
27
|
-
className={`block w-full px-5 py-4 border-0 border-b border-border-subtle bg-transparent text-left cursor-pointer transition-colors hover:bg-surface ${
|
|
28
|
-
isSelected ? 'bg-surface-elevated' : ''
|
|
29
|
-
}`}
|
|
30
|
-
>
|
|
31
|
-
<div className="flex items-baseline gap-2 mb-1.5">
|
|
32
|
-
<span className="text-sm font-medium text-text-primary leading-snug flex-1 min-w-0 line-clamp-2">
|
|
33
|
-
{issue.frontmatter.title || 'Untitled'}
|
|
34
|
-
</span>
|
|
35
|
-
<span className="font-mono text-xs text-text-muted shrink-0 ml-1">
|
|
36
|
-
#{issue.id}
|
|
37
|
-
</span>
|
|
38
|
-
</div>
|
|
39
|
-
|
|
40
|
-
{issue.frontmatter.description && (
|
|
41
|
-
<div className="text-[13px] text-text-muted mb-2.5 line-clamp-1">
|
|
42
|
-
{issue.frontmatter.description}
|
|
43
|
-
</div>
|
|
44
|
-
)}
|
|
45
|
-
|
|
46
|
-
<div className="flex items-center gap-2 flex-wrap">
|
|
47
|
-
{issue.frontmatter.priority && (
|
|
48
|
-
<Badge variant="priority" value={issue.frontmatter.priority} />
|
|
49
|
-
)}
|
|
50
|
-
|
|
51
|
-
{issue.frontmatter.status && (
|
|
52
|
-
<Badge variant="status" value={issue.frontmatter.status} />
|
|
53
|
-
)}
|
|
54
|
-
|
|
55
|
-
{issue.frontmatter.type && (
|
|
56
|
-
<Badge variant="type" value={issue.frontmatter.type} />
|
|
57
|
-
)}
|
|
58
|
-
|
|
59
|
-
{issue.frontmatter.created && (
|
|
60
|
-
<span
|
|
61
|
-
className="text-xs text-text-muted"
|
|
62
|
-
title={formatFullDate(issue.frontmatter.created)}
|
|
63
|
-
>
|
|
64
|
-
{formatDisplayDate(issue.frontmatter.created)}
|
|
65
|
-
</span>
|
|
66
|
-
)}
|
|
67
|
-
</div>
|
|
68
|
-
</button>
|
|
69
|
-
)
|
|
70
|
-
})}
|
|
71
|
-
</>
|
|
72
|
-
)
|
|
73
|
-
}
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
interface QueryHelpModalProps {
|
|
2
|
-
isOpen: boolean
|
|
3
|
-
onClose: () => void
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export function QueryHelpModal({ isOpen, onClose }: QueryHelpModalProps) {
|
|
7
|
-
if (!isOpen) return null
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<div
|
|
11
|
-
className="fixed inset-0 bg-black/70 flex items-center justify-center z-[1000] p-5"
|
|
12
|
-
onClick={onClose}
|
|
13
|
-
>
|
|
14
|
-
<div
|
|
15
|
-
className="bg-surface border border-border rounded-xl max-w-[600px] w-full max-h-[65vh] overflow-y-auto shadow-2xl custom-scrollbar"
|
|
16
|
-
onClick={(e) => e.stopPropagation()}
|
|
17
|
-
>
|
|
18
|
-
<div className="flex items-center justify-between px-6 py-5 border-b border-border">
|
|
19
|
-
<h2 className="text-lg font-semibold text-text-primary">
|
|
20
|
-
Query Syntax Help
|
|
21
|
-
</h2>
|
|
22
|
-
<button
|
|
23
|
-
onClick={onClose}
|
|
24
|
-
aria-label="Close"
|
|
25
|
-
className="w-8 h-8 flex items-center justify-center bg-transparent border-0 rounded-md text-text-muted text-2xl cursor-pointer transition-all hover:bg-surface-elevated hover:text-text-primary"
|
|
26
|
-
>
|
|
27
|
-
×
|
|
28
|
-
</button>
|
|
29
|
-
</div>
|
|
30
|
-
|
|
31
|
-
<div className="p-6">
|
|
32
|
-
<p className="text-text-secondary mb-6 leading-relaxed">
|
|
33
|
-
Use qualifiers to filter issues, or type freely to search by text.
|
|
34
|
-
</p>
|
|
35
|
-
|
|
36
|
-
<section className="mb-6">
|
|
37
|
-
<h3 className="text-[13px] font-semibold text-text-muted uppercase tracking-wide mb-3">
|
|
38
|
-
Qualifiers
|
|
39
|
-
</h3>
|
|
40
|
-
<div className="flex flex-col gap-2">
|
|
41
|
-
<QualifierRow
|
|
42
|
-
qualifier="is:"
|
|
43
|
-
description="Filter by status"
|
|
44
|
-
values="open, closed"
|
|
45
|
-
/>
|
|
46
|
-
<QualifierRow
|
|
47
|
-
qualifier="priority:"
|
|
48
|
-
description="Filter by priority"
|
|
49
|
-
values="high, medium, low"
|
|
50
|
-
/>
|
|
51
|
-
<QualifierRow
|
|
52
|
-
qualifier="type:"
|
|
53
|
-
description="Filter by issue type"
|
|
54
|
-
values="bug, feature, task, etc."
|
|
55
|
-
/>
|
|
56
|
-
<QualifierRow
|
|
57
|
-
qualifier="label:"
|
|
58
|
-
description="Filter by label"
|
|
59
|
-
values="any label name"
|
|
60
|
-
/>
|
|
61
|
-
<QualifierRow
|
|
62
|
-
qualifier="sort:"
|
|
63
|
-
description="Sort results"
|
|
64
|
-
values="created, priority, title"
|
|
65
|
-
/>
|
|
66
|
-
</div>
|
|
67
|
-
</section>
|
|
68
|
-
|
|
69
|
-
<section className="mb-6">
|
|
70
|
-
<h3 className="text-[13px] font-semibold text-text-muted uppercase tracking-wide mb-3">
|
|
71
|
-
Examples
|
|
72
|
-
</h3>
|
|
73
|
-
<div className="flex flex-col gap-2">
|
|
74
|
-
<ExampleRow
|
|
75
|
-
code="is:open priority:high"
|
|
76
|
-
description="High priority open issues"
|
|
77
|
-
/>
|
|
78
|
-
<ExampleRow
|
|
79
|
-
code="type:bug dashboard"
|
|
80
|
-
description='Bugs mentioning "dashboard"'
|
|
81
|
-
/>
|
|
82
|
-
<ExampleRow
|
|
83
|
-
code="is:open sort:priority"
|
|
84
|
-
description="Open issues sorted by priority"
|
|
85
|
-
/>
|
|
86
|
-
<ExampleRow
|
|
87
|
-
code="kubernetes cluster"
|
|
88
|
-
description='Issues matching "kubernetes cluster"'
|
|
89
|
-
/>
|
|
90
|
-
</div>
|
|
91
|
-
</section>
|
|
92
|
-
|
|
93
|
-
<section>
|
|
94
|
-
<h3 className="text-[13px] font-semibold text-text-muted uppercase tracking-wide mb-3">
|
|
95
|
-
Tips
|
|
96
|
-
</h3>
|
|
97
|
-
<ul className="list-none p-0 m-0 flex flex-col gap-2">
|
|
98
|
-
<li className="text-text-secondary text-[13px] pl-4 relative before:content-['•'] before:absolute before:left-0 before:text-text-muted">
|
|
99
|
-
Combine multiple qualifiers to narrow results
|
|
100
|
-
</li>
|
|
101
|
-
<li className="text-text-secondary text-[13px] pl-4 relative before:content-['•'] before:absolute before:left-0 before:text-text-muted">
|
|
102
|
-
Free text searches titles, descriptions, and content
|
|
103
|
-
</li>
|
|
104
|
-
<li className="text-text-secondary text-[13px] pl-4 relative before:content-['•'] before:absolute before:left-0 before:text-text-muted">
|
|
105
|
-
Use quotes for multi-word searches:{' '}
|
|
106
|
-
<code className="bg-surface-elevated px-1.5 py-0.5 rounded text-xs font-mono">
|
|
107
|
-
"api error"
|
|
108
|
-
</code>
|
|
109
|
-
</li>
|
|
110
|
-
<li className="text-text-secondary text-[13px] pl-4 relative before:content-['•'] before:absolute before:left-0 before:text-text-muted">
|
|
111
|
-
Qualifiers are case-insensitive
|
|
112
|
-
</li>
|
|
113
|
-
</ul>
|
|
114
|
-
</section>
|
|
115
|
-
</div>
|
|
116
|
-
</div>
|
|
117
|
-
</div>
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function QualifierRow({
|
|
122
|
-
qualifier,
|
|
123
|
-
description,
|
|
124
|
-
values,
|
|
125
|
-
}: {
|
|
126
|
-
qualifier: string
|
|
127
|
-
description: string
|
|
128
|
-
values: string
|
|
129
|
-
}) {
|
|
130
|
-
return (
|
|
131
|
-
<div className="flex gap-3 px-3 py-2.5 bg-surface-elevated rounded-md">
|
|
132
|
-
<code className="font-mono text-[13px] text-accent shrink-0 min-w-[80px]">
|
|
133
|
-
{qualifier}
|
|
134
|
-
</code>
|
|
135
|
-
<span className="text-text-secondary text-[13px] flex flex-col gap-0.5">
|
|
136
|
-
{description}
|
|
137
|
-
<span className="text-text-muted text-xs">{values}</span>
|
|
138
|
-
</span>
|
|
139
|
-
</div>
|
|
140
|
-
)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function ExampleRow({
|
|
144
|
-
code,
|
|
145
|
-
description,
|
|
146
|
-
}: {
|
|
147
|
-
code: string
|
|
148
|
-
description: string
|
|
149
|
-
}) {
|
|
150
|
-
return (
|
|
151
|
-
<div className="flex flex-col gap-1 px-3 py-2.5 bg-surface-elevated rounded-md">
|
|
152
|
-
<code className="font-mono text-[13px] text-text-primary">{code}</code>
|
|
153
|
-
<span className="text-text-muted text-xs">{description}</span>
|
|
154
|
-
</div>
|
|
155
|
-
)
|
|
156
|
-
}
|
package/src/frontend.tsx
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* issy Frontend Entry Point
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { createRoot } from 'react-dom/client'
|
|
6
|
-
import { App } from './App'
|
|
7
|
-
import './index.css'
|
|
8
|
-
|
|
9
|
-
function start() {
|
|
10
|
-
const container = document.getElementById('root')
|
|
11
|
-
if (!container) throw new Error('Root element not found')
|
|
12
|
-
const root = createRoot(container)
|
|
13
|
-
root.render(<App />)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (document.readyState === 'loading') {
|
|
17
|
-
document.addEventListener('DOMContentLoaded', start)
|
|
18
|
-
} else {
|
|
19
|
-
start()
|
|
20
|
-
}
|
package/src/index.css
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
2
|
-
@plugin "@tailwindcss/typography";
|
|
3
|
-
|
|
4
|
-
@theme {
|
|
5
|
-
/* Core palette - dark theme */
|
|
6
|
-
--color-background: #0a0b0f;
|
|
7
|
-
--color-surface: #12141a;
|
|
8
|
-
--color-surface-elevated: #1a1c24;
|
|
9
|
-
--color-border: #2a2d38;
|
|
10
|
-
--color-border-subtle: #1e2028;
|
|
11
|
-
|
|
12
|
-
/* Text hierarchy */
|
|
13
|
-
--color-text-primary: #f4f4f5;
|
|
14
|
-
--color-text-secondary: #a1a1aa;
|
|
15
|
-
--color-text-muted: #71717a;
|
|
16
|
-
|
|
17
|
-
/* Accent - warm coral */
|
|
18
|
-
--color-accent: #ff6b5b;
|
|
19
|
-
--color-accent-hover: #ff8577;
|
|
20
|
-
|
|
21
|
-
/* Status colors */
|
|
22
|
-
--color-status-open: #22c55e;
|
|
23
|
-
--color-status-closed: #6b7280;
|
|
24
|
-
|
|
25
|
-
/* Priority colors */
|
|
26
|
-
--color-priority-high: #ef4444;
|
|
27
|
-
--color-priority-medium: #f59e0b;
|
|
28
|
-
--color-priority-low: #22c55e;
|
|
29
|
-
|
|
30
|
-
/* Type colors */
|
|
31
|
-
--color-type-default: #a78bfa;
|
|
32
|
-
--color-type-bug: #f87171;
|
|
33
|
-
--color-type-feature: #60a5fa;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/* Custom scrollbar */
|
|
37
|
-
.custom-scrollbar::-webkit-scrollbar {
|
|
38
|
-
width: 6px;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.custom-scrollbar::-webkit-scrollbar-track {
|
|
42
|
-
background: var(--color-background);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.custom-scrollbar::-webkit-scrollbar-thumb {
|
|
46
|
-
background: var(--color-border);
|
|
47
|
-
border-radius: 3px;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/* Code block styling - remove borders, unify background, add dark scrollbar */
|
|
51
|
-
.prose pre {
|
|
52
|
-
border: none;
|
|
53
|
-
box-shadow: none;
|
|
54
|
-
background-color: var(--color-surface-elevated);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.prose pre code.hljs {
|
|
58
|
-
background: transparent;
|
|
59
|
-
padding: 0;
|
|
60
|
-
font-size: 13px;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.prose pre::-webkit-scrollbar {
|
|
64
|
-
height: 6px;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.prose pre::-webkit-scrollbar-track {
|
|
68
|
-
background: transparent;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.prose pre::-webkit-scrollbar-thumb {
|
|
72
|
-
background: var(--color-border);
|
|
73
|
-
border-radius: 3px;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
.prose pre::-webkit-scrollbar-thumb:hover {
|
|
77
|
-
background: var(--color-text-muted);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/* Firefox scrollbar */
|
|
81
|
-
.prose pre {
|
|
82
|
-
scrollbar-width: thin;
|
|
83
|
-
scrollbar-color: var(--color-border) transparent;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/* Line clamp utility for title */
|
|
87
|
-
.line-clamp-2 {
|
|
88
|
-
display: -webkit-box;
|
|
89
|
-
-webkit-line-clamp: 2;
|
|
90
|
-
-webkit-box-orient: vertical;
|
|
91
|
-
overflow: hidden;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
.line-clamp-1 {
|
|
95
|
-
display: -webkit-box;
|
|
96
|
-
-webkit-line-clamp: 1;
|
|
97
|
-
-webkit-box-orient: vertical;
|
|
98
|
-
overflow: hidden;
|
|
99
|
-
}
|
package/src/index.html
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>issy</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<div id="root"></div>
|
|
10
|
-
<script type="module" src="./frontend.tsx"></script>
|
|
11
|
-
</body>
|
|
12
|
-
</html>
|