Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 3x 8x 4x 4x 3x 715x 711x 4x 3x 715x 715x 715x 715x 711x | import clsx from 'clsx'
import { HashMap, Option } from 'effect'
import { Submodel } from 'foldkit'
import type { Html, HtmlBuilder } from 'foldkit/html'
import { Button } from '@foldkit/ui'
import { Message } from './message'
import { Feedback, type Model } from './model'
export type ViewInputs = Readonly<{
cellId: string
text: string
ariaLabel: string
lines: readonly [string, string]
toneClass: string
}>
const feedbackText = (feedback: Feedback): string =>
Feedback.match(feedback, {
Copied: () => 'Copied',
Failed: () => 'Copy failed',
})
const secondLineView = (
maybeFeedback: Option.Option<Feedback>,
detail: string,
h: HtmlBuilder<Message>,
): Html =>
Option.match(maybeFeedback, {
onNone: () => h.span([h.Class('block opacity-80')], [detail]),
onSome: feedback =>
h.span(
[
h.Class(
clsx('block', {
'text-ok': Feedback.guards.Copied(feedback),
'text-danger': Feedback.guards.Failed(feedback),
}),
),
],
[feedbackText(feedback)],
),
})
/** One readout cell: shows a reading, copies it on click, and announces the result. */
export const view = Submodel.defineView<Model, Message, ViewInputs>(
(model, viewInputs, h) => {
const maybeFeedback = HashMap.get(model.feedbackByCellId, viewInputs.cellId)
const [reading, detail] = viewInputs.lines
return h.span(
[h.Class('block')],
[
Button.view(
{
onClick: Message.ClickedCopy({
cellId: viewInputs.cellId,
text: viewInputs.text,
}),
toView: attributes =>
h.button(
[
...attributes.button,
h.AriaLabel(viewInputs.ariaLabel),
h.Title(`Copy ${viewInputs.text}`),
h.Class(
clsx(
'block w-full whitespace-nowrap px-3 py-1 text-left leading-5 outline-hidden hover:bg-ink/5 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus',
viewInputs.toneClass,
),
),
],
[
h.span([h.Class('block')], [reading]),
secondLineView(maybeFeedback, detail, h),
],
),
},
h,
),
h.span(
[h.Role('status'), h.AriaLive('polite'), h.Class('sr-only')],
[
Option.match(maybeFeedback, {
onNone: () => '',
onSome: feedbackText,
}),
],
),
],
)
},
)
|