diff --git a/app/components/Sidebar.tsx b/app/components/Sidebar.tsx index f9042feac7..9ecd99d849 100644 --- a/app/components/Sidebar.tsx +++ b/app/components/Sidebar.tsx @@ -28,7 +28,6 @@ const modKey = /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'cmd' : 'ctrl' const JumpToButton = () => ( - ), diff --git a/app/components/form/SideModalForm.tsx b/app/components/form/SideModalForm.tsx index f5ae750370..96abc8724e 100644 --- a/app/components/form/SideModalForm.tsx +++ b/app/components/form/SideModalForm.tsx @@ -84,7 +84,7 @@ export function SideModalForm({ {submitError.error.message} )} - - diff --git a/app/components/form/fields/NetworkInterfaceField.tsx b/app/components/form/fields/NetworkInterfaceField.tsx index 20814f6a6e..33417eb8b5 100644 --- a/app/components/form/fields/NetworkInterfaceField.tsx +++ b/app/components/form/fields/NetworkInterfaceField.tsx @@ -107,7 +107,7 @@ export function NetworkInterfaceField({ /> )}
-
diff --git a/app/forms/firewall-rules-create.tsx b/app/forms/firewall-rules-create.tsx index 706c95ef47..d591479cab 100644 --- a/app/forms/firewall-rules-create.tsx +++ b/app/forms/firewall-rules-create.tsx @@ -181,13 +181,14 @@ export const CommonFields = ({ error, control }: CommonFieldsProps) => {
- - -
{error?.error.message}
+ {error?.error.message && ( + <> + +
{error.error.message}
+ + )} ) } diff --git a/app/pages/LoginPage.tsx b/app/pages/LoginPage.tsx index 095dcc27f1..5fe857033c 100644 --- a/app/pages/LoginPage.tsx +++ b/app/pages/LoginPage.tsx @@ -62,7 +62,6 @@ export default function LoginPage() { diff --git a/app/pages/OrgsPage.tsx b/app/pages/OrgsPage.tsx index 3f98ac5bc4..baa3a8c448 100644 --- a/app/pages/OrgsPage.tsx +++ b/app/pages/OrgsPage.tsx @@ -87,7 +87,7 @@ export default function OrgsPage() { }>Organizations - + New Organization diff --git a/app/pages/ProjectsPage.tsx b/app/pages/ProjectsPage.tsx index 0ab93bb7af..9e14bfaf6e 100644 --- a/app/pages/ProjectsPage.tsx +++ b/app/pages/ProjectsPage.tsx @@ -97,10 +97,7 @@ export default function ProjectsPage() { }>Projects - + New Project diff --git a/app/pages/SiloAccessPage.tsx b/app/pages/SiloAccessPage.tsx index 5b7e80761d..8d11e695d3 100644 --- a/app/pages/SiloAccessPage.tsx +++ b/app/pages/SiloAccessPage.tsx @@ -147,7 +147,7 @@ export function SiloAccessPage() { - diff --git a/app/pages/project/access/ProjectAccessPage.tsx b/app/pages/project/access/ProjectAccessPage.tsx index 82f8b6daf6..47e576660c 100644 --- a/app/pages/project/access/ProjectAccessPage.tsx +++ b/app/pages/project/access/ProjectAccessPage.tsx @@ -178,7 +178,7 @@ export function ProjectAccessPage() { - diff --git a/app/pages/project/disks/DisksPage.tsx b/app/pages/project/disks/DisksPage.tsx index f7aa37379a..63536fbef4 100644 --- a/app/pages/project/disks/DisksPage.tsx +++ b/app/pages/project/disks/DisksPage.tsx @@ -122,7 +122,7 @@ export function DisksPage() { New Disk diff --git a/app/pages/project/instances/InstancesPage.tsx b/app/pages/project/instances/InstancesPage.tsx index e69bd77562..9ebc802a3b 100644 --- a/app/pages/project/instances/InstancesPage.tsx +++ b/app/pages/project/instances/InstancesPage.tsx @@ -95,7 +95,7 @@ export function InstancesPage() { New Instance diff --git a/app/pages/project/instances/instance/tabs/NetworkingTab.tsx b/app/pages/project/instances/instance/tabs/NetworkingTab.tsx index 68241c77cf..f516a45dda 100644 --- a/app/pages/project/instances/instance/tabs/NetworkingTab.tsx +++ b/app/pages/project/instances/instance/tabs/NetworkingTab.tsx @@ -150,7 +150,6 @@ export function NetworkingTab() {
-
diff --git a/app/pages/project/instances/instance/tabs/StorageTab.tsx b/app/pages/project/instances/instance/tabs/StorageTab.tsx index 92125c8ca2..032bb2d28a 100644 --- a/app/pages/project/instances/instance/tabs/StorageTab.tsx +++ b/app/pages/project/instances/instance/tabs/StorageTab.tsx @@ -133,7 +133,6 @@ export function StorageTab() {
{createModalOpen && ( diff --git a/app/pages/project/networking/VpcPage/tabs/VpcRoutersTab.tsx b/app/pages/project/networking/VpcPage/tabs/VpcRoutersTab.tsx index 541632d6fd..bebbeb6a8f 100644 --- a/app/pages/project/networking/VpcPage/tabs/VpcRoutersTab.tsx +++ b/app/pages/project/networking/VpcPage/tabs/VpcRoutersTab.tsx @@ -36,7 +36,7 @@ export const VpcRoutersTab = () => { return ( <>
- {creating && setCreating(false)} />} diff --git a/app/pages/project/networking/VpcPage/tabs/VpcSubnetsTab.tsx b/app/pages/project/networking/VpcPage/tabs/VpcSubnetsTab.tsx index 9c41bd6db8..28328170d6 100644 --- a/app/pages/project/networking/VpcPage/tabs/VpcSubnetsTab.tsx +++ b/app/pages/project/networking/VpcPage/tabs/VpcSubnetsTab.tsx @@ -35,7 +35,7 @@ export const VpcSubnetsTab = () => { return ( <>
- {creating && setCreating(false)} />} diff --git a/app/pages/project/networking/VpcsPage.tsx b/app/pages/project/networking/VpcsPage.tsx index 2a368e13d8..b2b8898ce2 100644 --- a/app/pages/project/networking/VpcsPage.tsx +++ b/app/pages/project/networking/VpcsPage.tsx @@ -94,7 +94,7 @@ export function VpcsPage() { New Vpc diff --git a/app/pages/project/snapshots/SnapshotsPage.tsx b/app/pages/project/snapshots/SnapshotsPage.tsx index 3bb070a9c1..b4eff69370 100644 --- a/app/pages/project/snapshots/SnapshotsPage.tsx +++ b/app/pages/project/snapshots/SnapshotsPage.tsx @@ -67,10 +67,7 @@ export function SnapshotsPage() { }>Snapshots - + New Snapshot diff --git a/app/pages/system/SilosPage.tsx b/app/pages/system/SilosPage.tsx index 0d6295e1d5..898cfbeae9 100644 --- a/app/pages/system/SilosPage.tsx +++ b/app/pages/system/SilosPage.tsx @@ -80,7 +80,7 @@ export default function SilosPage() { }>Silos - + New silo diff --git a/libs/ui/lib/bulk-action-menu/BulkActionMenu.tsx b/libs/ui/lib/bulk-action-menu/BulkActionMenu.tsx index a0cb383bb8..5f89fe5477 100644 --- a/libs/ui/lib/bulk-action-menu/BulkActionMenu.tsx +++ b/libs/ui/lib/bulk-action-menu/BulkActionMenu.tsx @@ -24,7 +24,6 @@ export function BulkActionMenu({ children, selectedCount }: BulkActionMenuProps) BulkActionMenu.Button = (props: Omit) => ( - - - ))} -
- ))} +
+ {variants.map((variant) => ( + <> + + + + ))} +
))}
diff --git a/libs/ui/lib/button/Button.tsx b/libs/ui/lib/button/Button.tsx index 2ceec3a0ab..9e68e813aa 100644 --- a/libs/ui/lib/button/Button.tsx +++ b/libs/ui/lib/button/Button.tsx @@ -3,17 +3,14 @@ import type { MouseEventHandler } from 'react' import { forwardRef } from 'react' import { Spinner, Tooltip, Wrap } from '@oxide/ui' -import { assertUnreachable } from '@oxide/util' import './button.css' export const buttonSizes = ['sm', 'icon', 'base'] as const -export const variants = ['default', 'ghost', 'link'] as const -export const colors = ['primary', 'secondary', 'destructive', 'notice'] as const +export const variants = ['primary', 'secondary', 'ghost', 'danger'] as const export type ButtonSize = typeof buttonSizes[number] export type Variant = typeof variants[number] -export type Color = typeof colors[number] const sizeStyle: Record = { sm: 'h-8 px-3 text-mono-sm svg:w-4', @@ -22,85 +19,22 @@ const sizeStyle: Record = { base: 'h-10 px-3 text-mono-md svg:w-5', } -const colorStyle = (variant: Variant, color: Color): string => { - const style: `${Variant} ${Color}` = `${variant} ${color}` - switch (style) { - case 'default primary': - return 'btn-primary' - case 'default secondary': - return 'btn-secondary-solid' - case 'default destructive': - return 'btn-destructive' - case 'default notice': - return 'btn-notice' - case 'ghost primary': - return 'btn-primary-ghost' - case 'ghost secondary': - return 'btn-secondary' - case 'ghost destructive': - return 'btn-destructive-ghost' - case 'ghost notice': - return 'btn-notice-ghost' - case 'link primary': - return 'btn-primary-link' - case 'link secondary': - return 'btn-secondary-link' - case 'link notice': - return 'btn-notice-link' - case 'link destructive': - return 'btn-destructive-link' - default: - assertUnreachable(`Invalid button state ${style}`, style) - } -} - -const ringStyle = (color: Color) => - color === 'destructive' - ? 'focus:ring-destructive-secondary' - : color === 'notice' - ? 'focus:ring-notice-secondary' - : 'focus:ring-accent-secondary' - -const baseStyle = ` - rounded inline-flex items-center justify-center align-top - disabled:cursor-not-allowed focus:ring-2 -` - type ButtonStyleProps = { size?: ButtonSize variant?: Variant - color?: Color } -export type ButtonProps = Pick< - React.ComponentProps<'button'>, - | 'className' - | 'onClick' - | 'aria-disabled' - | 'disabled' - | 'children' - | 'type' - | 'title' - | 'form' -> & - ButtonStyleProps & { - innerClassName?: string - loading?: boolean - disabledReason?: string - } - export const buttonStyle = ({ size = 'base', - variant = 'default', - color = 'primary', + variant = 'primary', }: ButtonStyleProps = {}) => { return cn( - 'ox-button', - `variant-${variant}`, - baseStyle, + 'ox-button rounded inline-flex items-center justify-center align-top disabled:cursor-not-allowed focus:ring-2', + `btn-${variant}`, sizeStyle[size], - ringStyle(color), - colorStyle(variant, color) + variant === 'danger' + ? 'focus:ring-destructive-secondary' + : 'focus:ring-accent-secondary' ) } @@ -114,6 +48,14 @@ const noop: MouseEventHandler = (e) => { e.preventDefault() } +export interface ButtonProps + extends React.ComponentPropsWithRef<'button'>, + ButtonStyleProps { + innerClassName?: string + loading?: boolean + disabledReason?: string +} + // Use `forwardRef` so the ref points to the DOM element (not the React Component) // so it can be focused using the DOM API (eg. this.buttonRef.current.focus()) export const Button = forwardRef( @@ -123,7 +65,6 @@ export const Button = forwardRef( children, size, variant, - color, className, loading, innerClassName, @@ -131,15 +72,16 @@ export const Button = forwardRef( onClick, 'aria-disabled': ariaDisabled, disabledReason, - form, - title, + // needs to be a spread because we pass this component to Reach + // with the `as` prop and get passed arbitrary ) diff --git a/libs/ui/lib/button/button.css b/libs/ui/lib/button/button.css index aa1ed82d07..c148d5cbf9 100644 --- a/libs/ui/lib/button/button.css +++ b/libs/ui/lib/button/button.css @@ -1,6 +1,3 @@ -/** - * Default - */ .btn-primary { @apply text-accent bg-accent-secondary hover:bg-accent-secondary-hover disabled:text-accent-disabled disabled:bg-accent-secondary; } @@ -9,58 +6,26 @@ @apply text-accent; } -/* Using `-solid` since ghost version is used as default secondary button state */ -.btn-secondary-solid { +.btn-secondary { @apply text-secondary bg-secondary hover:bg-secondary-hover disabled:text-quaternary disabled:bg-secondary; } -.btn-secondary-solid:disabled > .spinner, -.btn-secondary-solid.visually-disabled > .spinner { +.btn-secondary:disabled > .spinner, +.btn-secondary.visually-disabled > .spinner { @apply text-secondary; } -.btn-destructive { +.btn-danger { @apply text-destructive bg-destructive-secondary hover:bg-destructive-secondary-hover disabled:text-destructive-disabled disabled:bg-destructive-secondary; } -.btn-destructive:disabled > .spinner, -.btn-destructive.visually-disabled > .spinner { +.btn-danger:disabled > .spinner, +.btn-danger.visually-disabled > .spinner { @apply text-destructive; } -.btn-notice { - @apply text-notice bg-notice-secondary hover:bg-notice-secondary-hover disabled:text-notice-disabled disabled:bg-notice-secondary; -} -.btn-notice:disabled > .spinner, -.btn-notice.visually-disabled > .spinner { - @apply text-notice; -} - -/** - * Ghost - */ -.btn-primary-ghost { +.btn-ghost { @apply border text-secondary border-default hover:bg-hover disabled:bg-transparent; } -/* Removing `-ghost` so this version is default `btn-secondary` */ -.btn-secondary { - @apply border text-secondary border-default hover:bg-hover disabled:bg-transparent disabled:text-disabled disabled:border-tertiary; -} - -.btn-destructive-ghost { - @apply border text-destructive border-destructive-secondary hover:bg-destructive-secondary disabled:bg-transparent; -} - -.btn-notice-ghost { - @apply border text-notice border-notice-secondary hover:bg-notice-secondary disabled:bg-transparent; -} - -/** - * Link - */ -.btn-link-accent { - @apply text-accent hover:underline disabled:no-underline; -} - /** * A class to make it very visually obvious that a button style is missing */ diff --git a/libs/ui/styles/themes/selection.css b/libs/ui/styles/themes/selection.css index 978e53988c..fa31bf0cfe 100644 --- a/libs/ui/styles/themes/selection.css +++ b/libs/ui/styles/themes/selection.css @@ -16,7 +16,7 @@ & .ox-badge:not(.variant-ghost), & .ox-tag, - & .ox-button:not(.variant-ghost):not(.variant-link), + & .ox-button:not(.btn-ghost), & .ox-avatar, & .ox-radio-card { --content-accent: var(--content-inverse); diff --git a/libs/util/index.ts b/libs/util/index.ts index 571c642dc4..64e03bc917 100644 --- a/libs/util/index.ts +++ b/libs/util/index.ts @@ -2,6 +2,5 @@ export * from './classed' export * from './str' export * from './object' export * from './children' -export * from './unreachable' export * from './array' export * from './units' diff --git a/libs/util/unreachable.ts b/libs/util/unreachable.ts deleted file mode 100644 index 66f0b8eaaf..0000000000 --- a/libs/util/unreachable.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function assertUnreachable(message: string, ..._: never[]): never { - throw new Error(message) -}