@estiva-app/ui 0.5.0 → 0.6.0

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/src/Tooltip.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  import { useCallback, useLayoutEffect, useRef, useState, type CSSProperties, type ReactNode } from 'react'
2
2
  import { createPortal } from 'react-dom'
3
3
  import { cn } from './cn'
4
+ import { Kbd } from './Kbd'
4
5
 
5
6
  /**
6
7
  * Peek's Tooltip and WithTooltip (2026-08-28), verbatim, in one file.
@@ -13,19 +14,26 @@ import { cn } from './cn'
13
14
  */
14
15
  export interface TooltipProps {
15
16
  label: string
17
+ /** The key that does the same thing, drawn as the `Kbd` chip after the label.
18
+ * Pass it already formatted for the platform — this renders, it does not
19
+ * decide whether the modifier is a glyph or a word. */
20
+ shortcut?: string
16
21
  className?: string
17
22
  }
18
23
 
19
- export function Tooltip({ label, className }: TooltipProps) {
24
+ export function Tooltip({ label, shortcut, className }: TooltipProps) {
20
25
  return (
21
- <div role="tooltip" className={cn('bg-bg-elevated border border-border-default rounded-lg h-[30px] flex items-center justify-center px-2 shadow-lg', className)}>
26
+ <div role="tooltip" className={cn('bg-bg-elevated border border-border-default rounded-lg h-[30px] flex items-center justify-center gap-1.5 px-2 shadow-lg', className)}>
22
27
  <span className="text-caption text-text-primary whitespace-nowrap">{label}</span>
28
+ {shortcut && <Kbd>{shortcut}</Kbd>}
23
29
  </div>
24
30
  )
25
31
  }
26
32
 
27
33
  export interface WithTooltipProps {
28
34
  label: string
35
+ /** Passed straight to the surface — see `TooltipProps.shortcut`. */
36
+ shortcut?: string
29
37
  placement?: 'top' | 'bottom'
30
38
  /** Extra classes on the wrapper — e.g. `min-w-0 shrink` so a truncating label keeps truncating inside it. */
31
39
  wrapperClassName?: string
@@ -35,7 +43,7 @@ export interface WithTooltipProps {
35
43
  const GAP = 6
36
44
  const VIEWPORT_PAD = 8
37
45
 
38
- export function WithTooltip({ label, placement = 'top', wrapperClassName, children }: WithTooltipProps) {
46
+ export function WithTooltip({ label, shortcut, placement = 'top', wrapperClassName, children }: WithTooltipProps) {
39
47
  const [show, setShow] = useState(false)
40
48
  const ref = useRef<HTMLDivElement>(null)
41
49
  const tooltipRef = useRef<HTMLDivElement>(null)
@@ -69,7 +77,7 @@ export function WithTooltip({ label, placement = 'top', wrapperClassName, childr
69
77
  {show &&
70
78
  createPortal(
71
79
  <div ref={tooltipRef} style={style}>
72
- <Tooltip label={label} />
80
+ <Tooltip label={label} shortcut={shortcut} />
73
81
  </div>,
74
82
  document.body,
75
83
  )}
package/src/TopBar.mdx CHANGED
@@ -44,7 +44,7 @@ import { TopBar, IdentityMenu, SearchInput } from '@estiva-app/ui'
44
44
 
45
45
  <TopBar
46
46
  logo="Estiva"
47
- search={<SearchInput shortcut="K" className="w-[290px]" />}
47
+ search={<SearchInput shortcut="Ctrl+K" className="w-[290px]" />}
48
48
  right={<IdentityMenu me={me} signedIn={signedIn} />}
49
49
  />
50
50
  ```
@@ -54,7 +54,7 @@ const Behind = ({ children }: { children: ReactNode }) => (
54
54
  export const Solid: Story = {
55
55
  render: (args) => (
56
56
  <Below>
57
- <TopBar {...args} logo="Estiva" search={<SearchInput shortcut="K" className="w-[290px]" />} right={face} />
57
+ <TopBar {...args} logo="Estiva" search={<SearchInput shortcut="Ctrl+K" className="w-[290px]" />} right={face} />
58
58
  </Below>
59
59
  ),
60
60
  }
@@ -72,7 +72,7 @@ export const SolidNoSearch: Story = {
72
72
  export const Floating: Story = {
73
73
  render: (args) => (
74
74
  <Behind>
75
- <TopBar {...args} variant="floating" menu={menuButton} search={<SearchInput shortcut="K" className="w-[290px]" />} right={face} />
75
+ <TopBar {...args} variant="floating" menu={menuButton} search={<SearchInput shortcut="Ctrl+K" className="w-[290px]" />} right={face} />
76
76
  </Behind>
77
77
  ),
78
78
  }
package/src/index.ts CHANGED
@@ -18,6 +18,7 @@ export { Checkbox, type CheckboxProps } from './Checkbox'
18
18
  export { Chip, type ChipProps, type ChipType } from './Chip'
19
19
  export { ChipInput, InputChip, type ChipInputOption, type ChipInputProps, type InputChipProps } from './ChipInput'
20
20
  export { IconButton, type IconButtonProps, type IconButtonVariant } from './IconButton'
21
+ export { Kbd, type KbdProps } from './Kbd'
21
22
  export { IdentityMenu, IdentityPanel, type Identity, type IdentityMenuProps, type IdentityPanelProps } from './IdentityMenu'
22
23
  export { Tooltip, WithTooltip, type TooltipProps, type WithTooltipProps } from './Tooltip'
23
24
  export { Field, useFieldControlId, type FieldProps } from './Field'
@@ -31,7 +32,7 @@ export { EditableText, type EditableTextProps } from './EditableText'
31
32
  export { EmptyState, type EmptyStateProps } from './EmptyState'
32
33
  export { SkeletonBar, SkeletonList, SkeletonRow } from './Skeleton'
33
34
  export { Breadcrumb, type BreadcrumbProps, type Crumb } from './Breadcrumb'
34
- export { EnterHint, Menu, MenuItem, MenuRow, MenuSection, MenuSub, type MenuItemProps, type MenuProps, type MenuSubProps } from './Menu'
35
+ export { EnterHint, Menu, MenuItem, MenuPanel, MenuRow, MenuSection, MenuSub, type MenuItemProps, type MenuPanelProps, type MenuProps, type MenuSubProps } from './Menu'
35
36
  export { clampBox, fitMenu, fitSubmenu } from './fit'
36
37
  export { NavItem, type NavItemProps } from './NavItem'
37
38
  export { Person, type PersonProps } from './Person'
@@ -63,7 +63,15 @@ export const estivaContent = [own('./dist/*.js'), own('./src/*.{ts,tsx}')]
63
63
  export default {
64
64
 
65
65
  darkMode: 'class',
66
- plugins: [plugin(({ addVariant }) => addVariant('signal', '.signal &'))],
66
+ // `signal` is Peek's shipped theme (a class); `ship` is Ship's (an attribute,
67
+ // see tokens.css). Both exist so a treatment can be given to the two apps
68
+ // without changing the plain light/dark themes the docs render in.
69
+ plugins: [
70
+ plugin(({ addVariant }) => {
71
+ addVariant('signal', '.signal &')
72
+ addVariant('ship', "[data-theme='ship'] &")
73
+ }),
74
+ ],
67
75
  theme: {
68
76
  extend: {
69
77
  fontFamily: {