position ui and owliver update
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ArrowDownRight, ArrowUpRight, Check, ChevronRight, TriangleAlert } from 'lucide-react';
|
||||
import {
|
||||
ArrowDownRight, ArrowRight, ArrowUpRight, Check, ChevronRight, TriangleAlert,
|
||||
} from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { ProgressBar, toneForScore } from '@/components/ds/Progress';
|
||||
@@ -280,11 +282,17 @@ ListBlock.displayName = 'ListBlock';
|
||||
* position they were working on. This is the default for a
|
||||
* recommended person: inspecting a candidate is part of the
|
||||
* conversation, not a trip to another page.
|
||||
* `to` leaves for a route the app already has. Reserved for the explicit
|
||||
* "open the full record" case.
|
||||
* `to` leaves for a route the app already has, with the whole card as the
|
||||
* target. Reserved for items whose only meaning is "open this".
|
||||
* `action` a named link inside the card — `{ label, to }`. For an item that
|
||||
* has *both* a conversation and a record: the card keeps asking
|
||||
* Owliver, and the link is the one explicit way to leave. Reading a
|
||||
* card can then never navigate by accident, which matters most where
|
||||
* the body is an explanation worth reading.
|
||||
*
|
||||
* `hint` is for an item that can do neither — it says why, instead of looking
|
||||
* clickable and doing nothing.
|
||||
* clickable and doing nothing. An item may carry a hint *and* an action: the
|
||||
* hint explains the record, the action opens it.
|
||||
*/
|
||||
const InsightsBlock = React.memo(({ block, onPrompt }) => (
|
||||
<div className="space-y-2">
|
||||
@@ -298,7 +306,8 @@ const InsightsBlock = React.memo(({ block, onPrompt }) => (
|
||||
'transition-colors hover:border-krow-blue/50',
|
||||
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-krow-blue/50'
|
||||
);
|
||||
const actionable = Boolean(item.prompt && onPrompt) || Boolean(item.to);
|
||||
const asksOwliver = Boolean(item.prompt && onPrompt);
|
||||
const actionable = asksOwliver || Boolean(item.to);
|
||||
|
||||
const body = (
|
||||
<>
|
||||
@@ -315,7 +324,37 @@ const InsightsBlock = React.memo(({ block, onPrompt }) => (
|
||||
</>
|
||||
);
|
||||
|
||||
if (item.prompt && onPrompt) {
|
||||
/* A named link cannot live inside a button, so when an item has both, the
|
||||
card is a plain container: the readable area is its own button and the
|
||||
action sits beside it. One click target each, never nested. */
|
||||
if (item.action?.to) {
|
||||
return (
|
||||
<div key={i} className={surface}>
|
||||
{asksOwliver ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onPrompt(item.prompt)}
|
||||
className="block w-full rounded-lg text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-krow-blue/50"
|
||||
>
|
||||
{body}
|
||||
</button>
|
||||
) : body}
|
||||
|
||||
<div className="mt-2 flex justify-end">
|
||||
<Link
|
||||
to={item.action.to}
|
||||
className="inline-flex items-center gap-0.5 rounded text-caption font-semibold text-krow-blue transition-colors hover:underline
|
||||
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-krow-blue/50"
|
||||
>
|
||||
{item.action.label}
|
||||
<ArrowRight className="h-3 w-3" aria-hidden="true" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (asksOwliver) {
|
||||
return (
|
||||
<button key={i} type="button" onClick={() => onPrompt(item.prompt)} className={interactive}>
|
||||
{body}
|
||||
|
||||
Reference in New Issue
Block a user