diff options
| author | Adam <[email protected]> | 2025-12-17 03:47:44 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2025-12-17 03:47:49 -0600 |
| commit | 494e6fff019bb502fff88a07d6c519c063af9a02 (patch) | |
| tree | cda9a1f68c013c7a542cbc4f82c7b7b63f9fa0a1 /packages/ui/src/components | |
| parent | 0c7a297b1d3d9cdf8a060c4ed75160152da2b981 (diff) | |
| download | opencode-494e6fff019bb502fff88a07d6c519c063af9a02.tar.gz opencode-494e6fff019bb502fff88a07d6c519c063af9a02.zip | |
feat(desktop): share sessions
Diffstat (limited to 'packages/ui/src/components')
| -rw-r--r-- | packages/ui/src/components/icon.tsx | 1 | ||||
| -rw-r--r-- | packages/ui/src/components/popover.css | 95 | ||||
| -rw-r--r-- | packages/ui/src/components/popover.tsx | 44 | ||||
| -rw-r--r-- | packages/ui/src/components/text-field.tsx | 10 |
4 files changed, 145 insertions, 5 deletions
diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx index b8e8106e8..94d9544d6 100644 --- a/packages/ui/src/components/icon.tsx +++ b/packages/ui/src/components/icon.tsx @@ -52,6 +52,7 @@ const icons = { copy: `<path d="M6.2513 6.24935V2.91602H17.0846V13.7493H13.7513M13.7513 6.24935V17.0827H2.91797V6.24935H13.7513Z" stroke="currentColor" stroke-linecap="round"/>`, check: `<path d="M5 11.9657L8.37838 14.7529L15 5.83398" stroke="currentColor" stroke-linecap="square"/>`, photo: `<path d="M16.6665 16.6666L11.6665 11.6666L9.99984 13.3333L6.6665 9.99996L3.08317 13.5833M2.9165 2.91663H17.0832V17.0833H2.9165V2.91663ZM13.3332 7.49996C13.3332 8.30537 12.6803 8.95829 11.8748 8.95829C11.0694 8.95829 10.4165 8.30537 10.4165 7.49996C10.4165 6.69454 11.0694 6.04163 11.8748 6.04163C12.6803 6.04163 13.3332 6.69454 13.3332 7.49996Z" stroke="currentColor" stroke-linecap="square"/>`, + share: `<path d="M10.0013 12.0846L10.0013 3.33464M13.7513 6.66797L10.0013 2.91797L6.2513 6.66797M17.0846 10.418V17.0846H2.91797V10.418" stroke="currentColor" stroke-linecap="square"/>`, } export interface IconProps extends ComponentProps<"svg"> { diff --git a/packages/ui/src/components/popover.css b/packages/ui/src/components/popover.css new file mode 100644 index 000000000..74d7f5a39 --- /dev/null +++ b/packages/ui/src/components/popover.css @@ -0,0 +1,95 @@ +[data-slot="popover-trigger"] { + display: inline-flex; +} + +[data-component="popover-content"] { + z-index: 50; + min-width: 200px; + max-width: 320px; + border-radius: var(--radius-md); + border: 1px solid var(--border-weak-base); + background-color: var(--surface-raised-stronger-non-alpha); + box-shadow: var(--shadow-md); + transform-origin: var(--kb-popover-content-transform-origin); + + &:focus-within { + outline: none; + } + + &[data-closed] { + animation: popover-close 0.15s ease-out; + } + + &[data-expanded] { + animation: popover-open 0.15s ease-out; + } + + [data-slot="popover-header"] { + display: flex; + padding: 12px; + padding-bottom: 0; + justify-content: space-between; + align-items: center; + gap: 8px; + + [data-slot="popover-title"] { + flex: 1; + color: var(--text-strong); + margin: 0; + + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + } + + [data-slot="popover-close-button"] { + flex-shrink: 0; + } + } + + [data-slot="popover-description"] { + padding: 0 12px; + margin: 0; + color: var(--text-base); + + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + } + + [data-slot="popover-body"] { + padding: 12px; + } + + [data-slot="popover-arrow"] { + fill: var(--surface-raised-stronger-non-alpha); + } +} + +@keyframes popover-open { + from { + opacity: 0; + transform: scale(0.96); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes popover-close { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.96); + } +} diff --git a/packages/ui/src/components/popover.tsx b/packages/ui/src/components/popover.tsx new file mode 100644 index 000000000..3262098e5 --- /dev/null +++ b/packages/ui/src/components/popover.tsx @@ -0,0 +1,44 @@ +import { Popover as Kobalte } from "@kobalte/core/popover" +import { ComponentProps, JSXElement, ParentProps, Show, splitProps } from "solid-js" +import { IconButton } from "./icon-button" + +export interface PopoverProps extends ParentProps, Omit<ComponentProps<typeof Kobalte>, "children"> { + trigger: JSXElement + title?: JSXElement + description?: JSXElement + class?: ComponentProps<"div">["class"] + classList?: ComponentProps<"div">["classList"] +} + +export function Popover(props: PopoverProps) { + const [local, rest] = splitProps(props, ["trigger", "title", "description", "class", "classList", "children"]) + + return ( + <Kobalte gutter={4} {...rest}> + <Kobalte.Trigger as="div" data-slot="popover-trigger"> + {local.trigger} + </Kobalte.Trigger> + <Kobalte.Portal> + <Kobalte.Content + data-component="popover-content" + classList={{ + ...(local.classList ?? {}), + [local.class ?? ""]: !!local.class, + }} + > + {/* <Kobalte.Arrow data-slot="popover-arrow" /> */} + <Show when={local.title}> + <div data-slot="popover-header"> + <Kobalte.Title data-slot="popover-title">{local.title}</Kobalte.Title> + <Kobalte.CloseButton data-slot="popover-close-button" as={IconButton} icon="close" variant="ghost" /> + </div> + </Show> + <Show when={local.description}> + <Kobalte.Description data-slot="popover-description">{local.description}</Kobalte.Description> + </Show> + <div data-slot="popover-body">{local.children}</div> + </Kobalte.Content> + </Kobalte.Portal> + </Kobalte> + ) +} diff --git a/packages/ui/src/components/text-field.tsx b/packages/ui/src/components/text-field.tsx index 63ffb2594..77f014b6b 100644 --- a/packages/ui/src/components/text-field.tsx +++ b/packages/ui/src/components/text-field.tsx @@ -56,6 +56,10 @@ export function TextField(props: TextFieldProps) { setTimeout(() => setCopied(false), 2000) } + function handleClick() { + if (local.copyable) handleCopy() + } + return ( <Kobalte data-component="input" @@ -65,6 +69,7 @@ export function TextField(props: TextFieldProps) { value={local.value} onChange={local.onChange} onKeyDown={local.onKeyDown} + onClick={handleClick} required={local.required} disabled={local.disabled} readOnly={local.readOnly} @@ -96,8 +101,3 @@ export function TextField(props: TextFieldProps) { </Kobalte> ) } - -/** @deprecated Use TextField instead */ -export const Input = TextField -/** @deprecated Use TextFieldProps instead */ -export type InputProps = TextFieldProps |
