PageSourceSearch

https://pressthink.org/j/rosen-archive/frontend/components/WorkInProgressBanner.js?v=3.8.36

js pressthink.org collected 2026-10-02 04:26:33 UTC 2,680 bytes, 84 lines download raw bytes

1import { useState, useEffect } from 'react';
2import { html } from '../html.js?v=3.8.36';
3import { Sparkles, X } from 'lucide-react';
4import {
5  readTourState,
6  shouldShowTourEntry,
7} from '../services/tourState.js?v=3.8.36';
8
9const BANNER_DISMISSED_KEY = 'jrda_announce_banner_dismissed';
10
11const getStorage = () => {
12  try {
13    return window.localStorage;
14  } catch {
15    return null;
16  }
17};
18
19const wasBannerDismissed = (storage) => {
20  try {
21    return storage?.getItem(BANNER_DISMISSED_KEY) === 'true';
22  } catch {
23    return false;
24  }
25};
26
27const WorkInProgressBanner = () => {
28  const [dismissed, setDismissed] = useState(true); // Start hidden to prevent flash
29
30  useEffect(() => {
31    const storage = getStorage();
32
33    // Give a first-time visitor one invitation at a time. Once they have made
34    // a choice about Start Here, this announcement can appear on a later visit.
35    if (shouldShowTourEntry(readTourState(storage))) return;
36
37    if (!wasBannerDismissed(storage)) {
38      setDismissed(false);
39    }
40  }, []);
41
42  const handleDismiss = () => {
43    setDismissed(true);
44    try {
45      getStorage()?.setItem(BANNER_DISMISSED_KEY, 'true');
46    } catch {
47      // Dismiss for this session even when Web Storage is blocked.
48    }
49  };
50
51  if (dismissed) return null;
52
53  return html`
54    <div className="archive-notice archive-announcement">
55      <div className="container mx-auto px-4 py-3">
56        <div className="flex items-center gap-3">
57          <${Sparkles} className="w-5 h-5 text-sky-600 flex-shrink-0" />
58          <div className="flex-grow">
59            <p className="text-sm text-sky-700 font-medium">
60              Jay Rosen's Internet Archive is now publicly available.
61            </p>
62            <p className="text-xs text-sky-700 mt-0.5">
63              25,000+ records spanning four decades of journalism criticism, media theory, and public life.
64            </p>
65          </div>
66          <!-- p-3 (12px) around the 20px w-5/h-5 icon = a 44x44 tap target
67               (WCAG 2.5.5). Arbitrary values like min-w-[44px] are NOT in the
68               pre-built zero-build stylesheet, so padding is used instead. No
69               sky hover-bg exists in that CSS either; the icon darkens on hover
70               and the focus ring covers keyboard users. -->
71          <button
72            onClick=${handleDismiss}
73            className="archive-action archive-action--quiet archive-announcement__close flex-shrink-0 flex items-center justify-center p-3"
74            aria-label="Dismiss banner"
75          >
76            <${X} className="w-5 h-5" />
77          </button>
78        </div>
79      </div>
80    </div>
81  `;
82};
83
84export default WorkInProgressBanner;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.