Skip to content

Commit

Permalink
brand the command palette
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljguarino committed Jun 2, 2023
1 parent 7d32fde commit d100d22
Show file tree
Hide file tree
Showing 6 changed files with 849 additions and 608 deletions.
3 changes: 2 additions & 1 deletion assets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"@nivo/pie": "0.80.0",
"@nivo/radial-bar": "0.80.0",
"@nivo/tooltip": "0.80.0",
"@pluralsh/design-system": "1.336.2",
"@pluralsh/design-system": "^1.341.2",
"@tanstack/react-table": "8.7.9",
"@testing-library/jest-dom": "4.2.4",
"@testing-library/react": "9.3.3",
Expand Down Expand Up @@ -155,6 +155,7 @@
"stylelint": "14.16.1",
"stylelint-config-prettier": "9.0.5",
"typescript": "4.9.5",
"usehooks-ts": "^2.9.1",
"vite": "4.1.1",
"vite-plugin-pwa": "0.14.4",
"vite-plugin-rewrite-all": "1.0.1",
Expand Down
1 change: 0 additions & 1 deletion assets/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ const router = createBrowserRouter(createRoutesFromElements(rootRoutes))

export default function App() {
const mergedStyledTheme = mergeDeep(DEFAULT_THEME, styledTheme)

return (
<ApolloProvider client={client}>
<IntercomProvider appId={INTERCOM_APP_ID}>
Expand Down
239 changes: 150 additions & 89 deletions assets/src/components/CommandPalette.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { InstallationContext } from './Installations'
import { getIcon, hasIcons } from './apps/misc'
import {
ApiIcon,
AppIcon,
ComponentsIcon,
DashboardIcon,
DocumentIcon,
Expand All @@ -25,46 +24,20 @@ import {
} from '@pluralsh/design-system'
import { useNavigate } from 'react-router-dom'
import { Flex, Span } from 'honorable'

const animatorStyle = {
maxWidth: '600px',
width: '100%',
background: 'rgb(28 28 29)',
color: 'rgba(252 252 252 / 0.9)',
borderRadius: '8px',
overflow: 'hidden',
zIndex: 10000,
boxShadow: 'rgb(0 0 0 / 50%) 0px 16px 70px',
}

const searchStyle = {
padding: '12px 16px',
fontSize: '16px',
width: '100%',
boxSizing: 'border-box',
outline: 'none',
border: 'none',
background: 'rgb(28 28 29)',
color: 'rgba(252 252 252 / 0.9)',
}

const groupNameStyle = {
padding: '8px 16px',
fontSize: '10px',
textTransform: 'uppercase',
opacity: 0.5,
}
import styled, { createGlobalStyle } from 'styled-components'
import AppStatus from './apps/AppStatus'

function buildActions(applications, nav) {
return applications
.map((app) => [
{
id: app.name,
name: app.name,
app: app,
icon: hasIcons(app) ? (
<AppIcon
url={getIcon(app)}
size="xsmall"
size="xxsmall"
/>
) : null,
shortcut: [],
Expand Down Expand Up @@ -138,6 +111,94 @@ function buildActions(applications, nav) {
.flat()
}

function ItemInner({ action, ancestors }) {
return (
<>
<Flex
gap="8px"
fontSize={14}
alignItems="center"
>
{action.icon && action.icon}
<Flex flexDirection="column">
<Flex flexDirection={'row'}>
<Flex fill="horizontal">
{ancestors.length > 0 &&
ancestors.map((ancestor) => (
<Fragment key={ancestor.id}>
<Span
opacity={0.5}
marginRight={8}
>
{ancestor.name}
</Span>
<Span marginRight={8}>&rsaquo;</Span>
</Fragment>
))}
<span>{action.name}</span>
</Flex>
{action.suffix}
</Flex>
{action.subtitle && (
<span style={{ fontSize: 12 }}>{action.subtitle}</span>
)}
</Flex>
</Flex>
{action.shortcut?.length ? (
<div
aria-hidden
style={{ display: 'grid', gridAutoFlow: 'column', gap: '4px' }}
>
{action.shortcut.map((sc) => (
<kbd
key={sc}
style={{
padding: '4px 6px',
background: 'rgba(0 0 0 / .1)',
borderRadius: '4px',
fontSize: 14,
}}
>
{sc}
</kbd>
))}
</div>
) : null}
</>
)
}

const AppName = styled.div(({ theme }) => ({
...theme.partials.text.body2,
marginLeft: 8,
}))

const AppVersion = styled.div(({ theme }) => ({
...theme.partials.text.caption,
color: theme.colors['text-xlight'],
display: 'flex',
flexGrow: 1,
marginLeft: 8,
}))

const AppIcon = styled.img({
height: 26,
width: 26,
})

function AppItem({ app }) {
return (
<>
{hasIcons(app) && <AppIcon src={getIcon(app)} />}
<AppName>{app.name}</AppName>
{app.spec?.descriptor?.version && (
<AppVersion>v{app.spec.descriptor.version}</AppVersion>
)}
<AppStatus app={app} />
</>
)
}

const ResultItem = forwardRef(
({ action, active, currentRootActionId }, ref) => {
const ancestors = useMemo(() => {
Expand All @@ -156,59 +217,22 @@ const ResultItem = forwardRef(
<Flex
ref={ref}
alignItems="center"
padding="12px 16px"
padding="xsmall"
background={active ? 'fill-one-hover' : 'transparent'}
borderLeft={active ? 'border-primary' : 'transparent'}
borderLeftColor={active ? 'border-primary' : 'transparent'}
borderLeftWidth={'3px'}
borderLeftStyle={'solid'}
justifyContent="space-between"
cursor="pointer"
>
<Flex
gap="8px"
fontSize={14}
alignItems="center"
>
{action.icon && action.icon}
<Flex flexDirection="column">
<div>
{ancestors.length > 0 &&
ancestors.map((ancestor) => (
<Fragment key={ancestor.id}>
<Span
opacity={0.5}
marginRight={8}
>
{ancestor.name}
</Span>
<Span marginRight={8}>&rsaquo;</Span>
</Fragment>
))}
<span>{action.name}</span>
</div>
{action.subtitle && (
<span style={{ fontSize: 12 }}>{action.subtitle}</span>
)}
</Flex>
</Flex>
{action.shortcut?.length ? (
<div
aria-hidden
style={{ display: 'grid', gridAutoFlow: 'column', gap: '4px' }}
>
{action.shortcut.map((sc) => (
<kbd
key={sc}
style={{
padding: '4px 6px',
background: 'rgba(0 0 0 / .1)',
borderRadius: '4px',
fontSize: 14,
}}
>
{sc}
</kbd>
))}
</div>
) : null}
{action.app ? (
<AppItem app={action.app} />
) : (
<ItemInner
action={action}
ancestors={ancestors}
/>
)}
</Flex>
)
}
Expand All @@ -222,7 +246,7 @@ function RenderResults() {
items={results}
onRender={({ item, active }) =>
typeof item === 'string' ? (
<div style={groupNameStyle}>{item}</div>
<div className="group-name">{item}</div>
) : (
<ResultItem
action={item}
Expand All @@ -247,15 +271,52 @@ function useAppActions() {

function Palette() {
useAppActions()
const Provider = createGlobalStyle(({ theme }) => ({
'.cmdbar': {
maxWidth: '600px',
width: '100%',
overflow: 'hidden',
zIndex: 10000,
background: theme.colors['fill-one'],
border: theme.borders['fill-one'],
boxShadow: theme.boxShadows.modal,
borderRadius: theme.borderRadiuses.medium,
...theme.partials.text.body1,
'.group-name': {
padding: `${theme.spacing.small}px`,
textTransform: 'uppercase',
opacity: 0.5,
...theme.partials.text.overline,
},
'.search': {
...theme.partials.text.body2,
padding: `${theme.spacing['medium']}px ${theme.spacing['small']}px`,
fontSize: '16px',
width: '100%',
background: theme.colors['fill-one'],
color: theme.colors['text-xlight'],
border: 'none',
borderBottom: theme.borders['fill-two'],
outlineOffset: '-1px',
},
'.search:focus-visible': {
color: theme.colors.text,
...theme.partials.focus.outline,
},
},
}))
return (
<KBarPortal style={{ zIndex: 10000 }}>
<KBarPositioner style={{ zIndex: 10000 }}>
<KBarAnimator style={animatorStyle}>
<KBarSearch style={searchStyle} />
<RenderResults />
</KBarAnimator>
</KBarPositioner>
</KBarPortal>
<>
<Provider />
<KBarPortal style={{ zIndex: 10000 }}>
<KBarPositioner style={{ zIndex: 10000 }}>
<KBarAnimator className="cmdbar">
<KBarSearch className="search" />
<RenderResults />
</KBarAnimator>
</KBarPositioner>
</KBarPortal>
</>
)
}

Expand Down
7 changes: 4 additions & 3 deletions assets/src/components/layout/AppNav.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
AppsIcon,
Card,
Chip,
CloseIcon,
CommandIcon,
EmptyState,
ErrorIcon,
IconFrame,
Expand Down Expand Up @@ -266,13 +266,14 @@ export default function AppNav() {
<>
<Chip
backgroundColor={open ? 'fill-one-selected' : 'fill-one'}
icon={<AppsIcon />}
icon={<CommandIcon />}
clickable
onClick={() => setOpen(true)}
size="small"
userSelect="none"
whiteSpace="nowrap"
>
Apps
Cmd + K
<StatusIcon readiness={statuses.length > 0 && statuses[0].readiness} />
</Chip>
<StatusPanel
Expand Down
3 changes: 2 additions & 1 deletion assets/src/components/layout/Console.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import usePosthogIdentify from 'components/utils/Posthog'
import { A, Flex, Span } from 'honorable'
import { Outlet } from 'react-router-dom'

import { CommandPalette } from 'components/CommandPalette'

import { PluralProvider } from '../contexts/PluralContext'
import { InstallationsProvider } from '../Installations'
import { EnsureLogin } from '../login/Login'
Expand All @@ -18,7 +20,6 @@ import { ContentOverlay } from './Overlay'
import Sidebar from './Sidebar'
import Subheader from './Subheader'
import WithApplicationUpdate from './WithApplicationUpdate'
import { CommandPalette } from 'components/CommandPalette'

export const TOOLBAR_HEIGHT = '55px'
export const SIDEBAR_WIDTH = '200px'
Expand Down
Loading

0 comments on commit d100d22

Please sign in to comment.