Skip to content

Commit 53709d2

Browse files
Add CLI command button to settings group (#2046)
* Add CLI command button to settings group * refactor SettingsGroup into composable blocks * don't need to export LearnMore --------- Co-authored-by: David Crespo <david.crespo@oxidecomputer.com>
1 parent 84caede commit 53709d2

File tree

6 files changed

+91
-74
lines changed

6 files changed

+91
-74
lines changed

app/components/EquivalentCliCommand.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { Button } from '~/ui/lib/Button'
1313
import { Modal } from '~/ui/lib/Modal'
1414
import useTimeout from '~/ui/lib/use-timeout'
1515

16-
export default function EquivalentCliCommand({ command }: { command: string }) {
16+
export function EquivalentCliCommand({ command }: { command: string }) {
1717
const [isOpen, setIsOpen] = useState(false)
1818
const [hasCopied, setHasCopied] = useState(false)
1919

app/pages/project/instances/instance/SerialConsolePage.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ import { Link } from 'react-router-dom'
1111
import { api } from '@oxide/api'
1212
import { PrevArrow12Icon } from '@oxide/design-system/icons/react'
1313

14-
import EquivalentCliCommand from '~/components/EquivalentCliCommand'
14+
import { EquivalentCliCommand } from '~/components/EquivalentCliCommand'
1515
import { useInstanceSelector } from '~/hooks'
1616
import { Badge, type BadgeColor } from '~/ui/lib/Badge'
1717
import { Spinner } from '~/ui/lib/Spinner'
18+
import { cliCmd } from '~/util/cli-cmd'
1819
import { pb } from '~/util/path-builder'
1920

2021
const Terminal = lazy(() => import('~/components/Terminal'))
@@ -95,10 +96,6 @@ export function SerialConsolePage() {
9596
}
9697
}, [])
9798

98-
const command = `oxide instance serial console
99-
--project ${project}
100-
--instance ${instance}`
101-
10299
return (
103100
<div className="!mx-0 flex h-full max-h-[calc(100vh-60px)] !w-full flex-col">
104101
<Link
@@ -118,7 +115,7 @@ export function SerialConsolePage() {
118115
<div className="flex-shrink-0 justify-between overflow-hidden border-t bg-default border-secondary empty:border-t-0">
119116
<div className="gutter flex h-20 items-center justify-between">
120117
<div>
121-
<EquivalentCliCommand command={command} />
118+
<EquivalentCliCommand command={cliCmd.serialConsole({ project, instance })} />
122119
</div>
123120

124121
<Badge color={statusColor[connectionStatus]}>

app/pages/project/instances/instance/tabs/ConnectTab.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,33 @@
66
* Copyright Oxide Computer Company
77
*/
88

9+
import { Link } from 'react-router-dom'
10+
11+
import { EquivalentCliCommand } from '~/components/EquivalentCliCommand'
912
import { useInstanceSelector } from '~/hooks'
13+
import { buttonStyle } from '~/ui/lib/Button'
1014
import { SettingsGroup } from '~/ui/lib/SettingsGroup'
15+
import { cliCmd } from '~/util/cli-cmd'
1116
import { pb } from '~/util/path-builder'
1217

1318
export function ConnectTab() {
1419
const { project, instance } = useInstanceSelector()
1520

1621
return (
17-
<SettingsGroup
18-
title="Serial Console"
19-
cta={pb.serialConsole({ project, instance })}
20-
ctaText="Connect"
21-
>
22-
Connect to your instance&rsquo;s serial console
23-
</SettingsGroup>
22+
<SettingsGroup.Container>
23+
<SettingsGroup.Body>
24+
<SettingsGroup.Title>Serial console</SettingsGroup.Title>
25+
Connect to your instance&rsquo;s serial console
26+
</SettingsGroup.Body>
27+
<SettingsGroup.Footer>
28+
<EquivalentCliCommand command={cliCmd.serialConsole({ project, instance })} />
29+
<Link
30+
to={pb.serialConsole({ project, instance })}
31+
className={buttonStyle({ size: 'sm' })}
32+
>
33+
Connect
34+
</Link>
35+
</SettingsGroup.Footer>
36+
</SettingsGroup.Container>
2437
)
2538
}

app/ui/lib/SettingsGroup.stories.tsx

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,40 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8+
import { Link } from 'react-router-dom'
9+
10+
import { Button, buttonStyle } from './Button'
811
import { SettingsGroup } from './SettingsGroup'
912

1013
export const Default = () => (
11-
<SettingsGroup
12-
title="Serial Console"
13-
docs={{ text: 'Serial Console', link: '/' }}
14-
cta="/"
15-
ctaText="Connect"
16-
>
17-
Connect to your instance&rsquo;s serial console
18-
</SettingsGroup>
14+
<SettingsGroup.Container>
15+
<SettingsGroup.Body>
16+
<SettingsGroup.Title>Serial console</SettingsGroup.Title>
17+
Connect to your instance&rsquo;s serial console
18+
</SettingsGroup.Body>
19+
<SettingsGroup.Footer
20+
docsLink={{ text: 'math', href: 'https://en.wikipedia.org/wiki/Mathematics' }}
21+
>
22+
<Link to="/" className={buttonStyle({ size: 'sm' })}>
23+
Connect
24+
</Link>
25+
</SettingsGroup.Footer>
26+
</SettingsGroup.Container>
1927
)
2028

2129
export const WithoutDocs = () => (
22-
<SettingsGroup title="Serial Console" cta="/" ctaText="Connect">
23-
Connect to your instance&rsquo;s serial console
24-
</SettingsGroup>
25-
)
26-
27-
export const FunctionAction = () => (
28-
<SettingsGroup title="Serial Console" cta={() => alert('hi')} ctaText="Connect">
29-
Connect to your instance&rsquo;s serial console
30-
</SettingsGroup>
30+
<SettingsGroup.Container>
31+
<SettingsGroup.Body>
32+
<SettingsGroup.Title>Serial console</SettingsGroup.Title>
33+
Connect to your instance&rsquo;s serial console
34+
</SettingsGroup.Body>
35+
<SettingsGroup.Footer>
36+
<Link to="/" className={buttonStyle({ size: 'sm' })}>
37+
Connect
38+
</Link>
39+
<Button size="sm" variant="secondary" onClick={() => {}}>
40+
Secondary
41+
</Button>
42+
</SettingsGroup.Footer>
43+
</SettingsGroup.Container>
3144
)

app/ui/lib/SettingsGroup.tsx

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,55 +5,37 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8-
import { Link } from 'react-router-dom'
98

109
import { OpenLink12Icon } from '@oxide/design-system/icons/react'
1110

12-
import { Button, buttonStyle } from '~/ui/lib/Button'
11+
import { classed } from '~/util/classed'
1312

14-
type Props = {
15-
title: string
16-
docs?: {
17-
text: string
18-
link: string
19-
}
13+
const LearnMore = ({ href, text }: { href: string; text: React.ReactNode }) => (
14+
<>
15+
Learn more about{' '}
16+
<a href={href} className="text-accent-secondary hover:text-accent">
17+
{text}
18+
<OpenLink12Icon className="ml-1 align-middle" />
19+
</a>
20+
</>
21+
)
22+
23+
type FooterProps = {
24+
/** Link text */
2025
children: React.ReactNode
21-
/** String action is a link */
22-
cta: string | (() => void)
23-
ctaText: string
26+
docsLink?: { text: string; href: string }
2427
}
2528

26-
export const SettingsGroup = ({ title, docs, children, cta, ctaText }: Props) => {
27-
return (
28-
<div className="w-full max-w-[660px] rounded-lg border text-sans-md text-secondary border-default">
29-
<div className="p-6">
30-
<div className="mb-1 text-sans-lg text-default">{title}</div>
31-
{children}
32-
</div>
33-
<div className="flex items-center justify-between border-t px-6 py-3 border-default">
34-
{/* div always present to keep the button right-aligned */}
35-
<div className="text-tertiary">
36-
{docs && (
37-
<>
38-
Learn more about{' '}
39-
<a href={docs.link} className="text-accent-secondary hover:text-accent">
40-
{docs.text}
41-
<OpenLink12Icon className="ml-1 align-middle" />
42-
</a>
43-
</>
44-
)}
45-
</div>
46-
47-
{typeof cta === 'string' ? (
48-
<Link to={cta} className={buttonStyle({ size: 'sm' })}>
49-
{ctaText}
50-
</Link>
51-
) : (
52-
<Button size="sm" onClick={cta}>
53-
{ctaText}
54-
</Button>
55-
)}
56-
</div>
29+
/** Use size=sm on buttons and links! */
30+
export const SettingsGroup = {
31+
Container: classed.div`w-full max-w-[660px] rounded-lg border text-sans-md text-secondary border-default`,
32+
Body: classed.div`p-6`,
33+
Title: classed.div`mb-1 text-sans-lg text-default`,
34+
Footer: ({ children, docsLink }: FooterProps) => (
35+
<div className="flex items-center justify-between border-t px-6 py-3 border-default">
36+
{/* div always present to keep the buttons right-aligned */}
37+
<div className="text-tertiary">{docsLink && <LearnMore {...docsLink} />}</div>
38+
<div className="flex gap-3">{children}</div>
5739
</div>
58-
)
40+
),
5941
}

app/util/cli-cmd.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
5+
*
6+
* Copyright Oxide Computer Company
7+
*/
8+
9+
export const cliCmd = {
10+
serialConsole: ({ project, instance }: { project: string; instance: string }) =>
11+
`oxide instance serial console\n--project ${project}\n--instance ${instance}`,
12+
}

0 commit comments

Comments
 (0)