@natjswenson/devlog 0.1.8 → 0.1.9

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/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  All notable changes to `@natjswenson/devlog` are documented here.
4
4
 
5
+ ## 0.1.9 (2026-06-05) — accessibility fix
6
+
7
+ **Accessibility**
8
+ - The drop-in React component (`examples/react/DevLogPage.jsx`) now exposes the expand/collapse entries as a proper disclosure control. Previously they were mouse-only — a bare `onClick` on `<article>` with no `role`, `tabIndex`, `aria-expanded`, or keyboard handler, so keyboard and screen-reader users could not operate the feed.
9
+ - The header carries `role="button"`, `tabIndex={0}`, `aria-expanded`, and `aria-controls` for screen-reader toggle semantics.
10
+ - `Enter`/`Space` toggle the focused entry (`preventDefault` on Space stops page scroll).
11
+ - `:focus-visible` outline makes keyboard focus visible.
12
+ - The toggle moved from the whole card to the header, so links inside an expanded entry are no longer nested in an interactive ancestor and text selection in the body works normally.
13
+ - Visuals are unchanged: padding/hover/cursor moved from `.devlog-entry` to `.devlog-header`, with the redundant content padding zeroed so spacing matches.
14
+
5
15
  ## 0.1.8 (2026-05-01) — final hardening pass
6
16
 
7
17
  Closes the four Low-Hardening findings from the second adversarial verification:
@@ -75,33 +75,39 @@
75
75
  }
76
76
 
77
77
  .devlog-entry {
78
- padding: 28px 0;
79
78
  border-bottom: 1px solid var(--devlog-border);
80
- cursor: pointer;
81
- transition: background var(--devlog-transition-fast);
82
79
  }
83
80
 
84
81
  .devlog-entry:first-child {
85
82
  border-top: 1px solid var(--devlog-border);
86
83
  }
87
84
 
88
- .devlog-entry:hover {
89
- background: var(--devlog-bg-surface);
90
- }
91
-
92
- .devlog-entry--expanded,
93
- .devlog-entry--expanded:hover {
94
- cursor: default;
95
- background: none;
96
- }
97
-
98
- /* ─── Entry header ──────────────────────────────────────────────────── */
85
+ /* ─── Entry header (the disclosure control) ─────────────────────────── */
99
86
 
100
87
  .devlog-header {
101
88
  display: flex;
102
89
  justify-content: space-between;
103
90
  align-items: flex-start;
104
91
  gap: 24px;
92
+ padding: 28px 0;
93
+ cursor: pointer;
94
+ transition: background var(--devlog-transition-fast);
95
+ }
96
+
97
+ .devlog-header:hover {
98
+ background: var(--devlog-bg-surface);
99
+ }
100
+
101
+ .devlog-header:focus-visible {
102
+ outline: 2px solid var(--devlog-fg);
103
+ outline-offset: -2px;
104
+ border-radius: 4px;
105
+ }
106
+
107
+ .devlog-entry--expanded .devlog-header,
108
+ .devlog-entry--expanded .devlog-header:hover {
109
+ cursor: default;
110
+ background: none;
105
111
  }
106
112
 
107
113
  .devlog-header__left {
@@ -163,8 +169,10 @@
163
169
  overflow: hidden;
164
170
  }
165
171
 
172
+ /* Header already contributes 28px of bottom padding above this region,
173
+ so the expanded body sits flush against it. */
166
174
  .devlog-content {
167
- padding-top: 24px;
175
+ padding-top: 0;
168
176
  }
169
177
 
170
178
  .devlog-content h2 {
@@ -81,6 +81,15 @@ export default function DevLogPage({
81
81
  }
82
82
  }, [expandedEntry, loadedContent, fetchEntryContent]);
83
83
 
84
+ // Enter/Space toggle the focused entry — keyboard parity with the click
85
+ // handler. preventDefault on Space stops the page from scrolling.
86
+ const handleKeyDown = useCallback((e, filename) => {
87
+ if (e.key === 'Enter' || e.key === ' ') {
88
+ e.preventDefault();
89
+ handleToggle(filename);
90
+ }
91
+ }, [handleToggle]);
92
+
84
93
  const visibleEntries = entries.slice(0, visibleCount);
85
94
  const hasMore = visibleCount < entries.length;
86
95
  const showTabs = projects && projects.length > 1;
@@ -132,14 +141,28 @@ export default function DevLogPage({
132
141
  {visibleEntries.map((entry) => {
133
142
  const isExpanded = expandedEntry === entry.file;
134
143
  const content = loadedContent.get(entry.file);
144
+ const contentId = `devlog-content-${entry.file}`;
135
145
 
136
146
  return (
137
147
  <article
138
148
  key={entry.file}
139
149
  className={`devlog-entry${isExpanded ? ' devlog-entry--expanded' : ''}`}
140
- onClick={() => handleToggle(entry.file)}
141
150
  >
142
- <div className="devlog-header">
151
+ {/* The header is the disclosure control: role=button +
152
+ aria-expanded/aria-controls give screen readers the
153
+ toggle semantics, and it's keyboard-focusable. Keeping
154
+ it separate from the content region (rather than wrapping
155
+ the whole card in onClick) means links inside an expanded
156
+ entry aren't trapped inside an interactive ancestor. */}
157
+ <div
158
+ className="devlog-header"
159
+ role="button"
160
+ tabIndex={0}
161
+ aria-expanded={isExpanded}
162
+ aria-controls={contentId}
163
+ onClick={() => handleToggle(entry.file)}
164
+ onKeyDown={(e) => handleKeyDown(e, entry.file)}
165
+ >
143
166
  <div className="devlog-header__left">
144
167
  <p className="devlog-date">{formatDate(entry.date)}</p>
145
168
  <h2 className="devlog-title">{entry.title}</h2>
@@ -150,10 +173,10 @@ export default function DevLogPage({
150
173
  </div>
151
174
  </div>
152
175
 
153
- <div className="devlog-content-wrapper">
176
+ <div className="devlog-content-wrapper" id={contentId}>
154
177
  <div className="devlog-content-inner">
155
178
  {isExpanded && content && (
156
- <div className="devlog-content" onClick={(e) => e.stopPropagation()}>
179
+ <div className="devlog-content">
157
180
  <ReactMarkdown
158
181
  remarkPlugins={[remarkGfm]}
159
182
  urlTransform={safeUrlTransform}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@natjswenson/devlog",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Daily dev log generator — Claude Code skill + preview app for publishing git-based dev logs to your site",
5
5
  "license": "MIT",
6
6
  "author": "Nate Swenson",