Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Drive table #12397

Open
wants to merge 29 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0d26d21
[dashboard/ProjectExecutionsCalendar] Fix missing `key`
somebody1234 Feb 28, 2025
f8043d0
[dashboard] Replace `gap-icon-with-text` with `gap-2`
somebody1234 Feb 28, 2025
b5ee64e
[dashboard/AssetsTable] Add background to "hidden columns" tray
somebody1234 Feb 28, 2025
951807d
Minor formatting change
somebody1234 Mar 3, 2025
b3dabf4
Fix sort arrow in "name" and "modified" being on a separate name
somebody1234 Mar 3, 2025
673b887
Format `Button/types.ts`
somebody1234 Mar 3, 2025
dc6ed86
[dashboard/Button] Replace `import *` with `import {}`
somebody1234 Mar 3, 2025
4938880
[dashboard/Breadcrumbs] Format
somebody1234 Mar 3, 2025
532930e
[dashboard/Drive] Infinite `staleTime` for root directory and parent …
somebody1234 Mar 3, 2025
c1b7331
[dashboard/Drive] Remove incorrect `staleTime` from "list directories…
somebody1234 Mar 3, 2025
5ec659a
[dashboard] Replace column sort icons with `Icon`s
somebody1234 Mar 3, 2025
65188bf
[dashboard/Button] Remove unnecessary `weight` prop from `Button`
somebody1234 Mar 3, 2025
81209bb
[dashboard/DatePicker] Fix reset button placement
somebody1234 Mar 3, 2025
e7c04af
[dashboard/DatePicker] Fix foreign placeholders (visible in "Activity…
somebody1234 Mar 3, 2025
85a9bb9
[dashboard] Fix margin to the left of short icons
somebody1234 Mar 3, 2025
e3ca1e7
[dashboard] Allow destructive code actions for "organize imports" Pre…
somebody1234 Mar 3, 2025
5e59056
[dashboard] Prettier + refactor imports
somebody1234 Mar 3, 2025
7ae9d02
[dashboard] Remove `<Text />` wrapper for button content
somebody1234 Mar 3, 2025
cfd6a5e
[dashboard/DatePicker] Fix segments always showing as placeholders
somebody1234 Mar 3, 2025
c6e79bd
[dashboard/ProjectExecution] Add truncated text and hover tooltip back
somebody1234 Mar 3, 2025
8f50c31
[dashboard/ProjectExecutionsCalendar] Avoid fading out date numbers i…
somebody1234 Mar 3, 2025
ef51cb2
[project-view] Prettier
somebody1234 Mar 3, 2025
a95b150
[dashboard/ProjectExecution] Show date instead of "Does not repeat" i…
somebody1234 Mar 3, 2025
f3f1aa6
Merge branch 'develop' into wip/sb/flat-assets-fixes
somebody1234 Mar 4, 2025
438c4f3
[dashboard/IconDisplay] Add and use component
somebody1234 Mar 5, 2025
2c3b1f2
Merge branch 'develop' into wip/sb/flat-assets-fixes
somebody1234 Mar 5, 2025
cab3917
[dashboard/IconDisplay] Fix tooltips
somebody1234 Mar 5, 2025
b40c8c9
[dashboard/IconDisplay] Add stories
somebody1234 Mar 5, 2025
e68c8b1
[dashboard/IconDisplay] Fix stories
somebody1234 Mar 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .prettierrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ overrides:
printWidth: 100
trailingComma: "all"
arrowParens: "always"
organizeImportsSkipDestructiveCodeActions: true
experimentalTernaries: true
tailwindConfig: ./app/gui/tailwind.config.ts

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from 'react'

import * as aria from '#/components/aria'
import { Text, useVisualTooltip } from '#/components/AriaComponents/Text'
import { useVisualTooltip } from '#/components/AriaComponents/Text'
import { Tooltip, TooltipTrigger } from '#/components/AriaComponents/Tooltip'
import { Icon as IconComponent } from '#/components/Icon'
import { StatelessSpinner } from '#/components/StatelessSpinner'
Expand Down Expand Up @@ -337,9 +337,7 @@ const ButtonContent = memo(function ButtonContent(props: ButtonContentProps) {
styles={styles}
hideLoader={hideLoader}
/>
<Text color="inherit" truncate="1" className={styles.text()}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We used to have a span with className={styles.text()}, haven't we?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, i tried extracting the css directly and it doesn't seem to work.
try running this commit in dev (staging env) and create a project execution (no repeats to minimize load, but long timezone to (try to) trigger the truncate class):

438c4f3

{children}
</Text>
{children}
{hasAddon(addonEnd) && <div className={styles.addonEnd()}>{addonEnd}</div>}
</>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/** @file A button that copies text to the clipboard. */
import * as React from 'react'

import Error from '#/assets/cross.svg'
import CopyIcon from '#/assets/duplicate.svg'
import Done from '#/assets/tick.svg'
Expand All @@ -12,10 +10,6 @@ import * as textProvider from '#/providers/TextProvider'
import { Button } from './Button'
import type { ButtonProps } from './types'

// ==================
// === CopyButton ===
// ==================

/** Props for a {@link CopyButton}. */
export interface CopyButtonProps<IconType extends string>
extends Omit<ButtonProps<IconType>, 'icon' | 'loading' | 'onPress'> {
Expand Down
55 changes: 22 additions & 33 deletions app/gui/src/dashboard/components/AriaComponents/Button/types.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,46 @@
/**
* @file
*
* Reusable types for the Button component
*/
import type * as aria from '#/components/aria'
/** @file Types for a `Button`. */
import type {
ButtonProps as AriaButtonProps,
ButtonRenderProps as AriaButtonRenderProps,
LinkRenderProps as AriaLinkRenderProps,
LinkProps,
Placement,
PressEvent,
} from '#/components/aria'
import type { ExtractFunction } from '#/utilities/tailwindVariants'
import type { ReactElement, ReactNode } from 'react'
import type { Addon, IconProp, TestIdProps } from '../types'
import type { BUTTON_STYLES, ButtonVariants } from './variants'

/**
* Position of a joined button
*/
/** Position of a joined button. */
export type PrivateJoinedButtonPosition = ButtonVariants['position']

/**
* Whether the button is joined
*/
/** Whether the button is joined. */
export type PrivateJoinedButton = ButtonVariants['isJoined']

/**
* Props for a joined button unlike other button props,
*/
/** Props for a joined button unlike other button props. */
export interface PrivateJoinedButtonProps {
readonly position: PrivateJoinedButtonPosition
readonly isJoined: NonNullable<PrivateJoinedButton>
}

/**
* Render props for a button.
*/
export interface ButtonRenderProps extends aria.ButtonRenderProps {
/** Render props for a button. */
export interface ButtonRenderProps extends AriaButtonRenderProps {
readonly isLoading: boolean
}

/**
* Render props for a link.
*/
export interface LinkRenderProps extends aria.LinkRenderProps {
/** Render props for a link. */
export interface LinkRenderProps extends AriaLinkRenderProps {
readonly isLoading: boolean
}

/** Props for a Button. */
export type ButtonProps<IconType extends string = string> =
| (BaseButtonProps<IconType, ButtonRenderProps> &
Omit<aria.ButtonProps, 'children' | 'isPending' | 'onPress'> &
Omit<AriaButtonProps, 'children' | 'isPending' | 'onPress'> &
PropsWithoutHref)
| (BaseButtonProps<IconType, LinkRenderProps> &
Omit<aria.LinkProps, 'children' | 'onPress'> &
Omit<LinkProps, 'children' | 'onPress'> &
PropsWithHref)

/** Props for a button with an href. */
Expand All @@ -68,7 +61,7 @@ export interface BaseButtonProps<IconType extends string, Render>
readonly hideLoader?: boolean
/** Falls back to `aria-label`. Pass `false` to explicitly disable the tooltip. */
readonly tooltip?: ReactElement | string | false | null
readonly tooltipPlacement?: aria.Placement
readonly tooltipPlacement?: Placement
/** The icon to display in the button */
readonly icon?: IconProp<IconType, Render>
/** When `true`, icon will be shown only when hovered. */
Expand All @@ -81,7 +74,7 @@ export interface BaseButtonProps<IconType extends string, Render>
// prettier-ignore
readonly onPress?:
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
| ((event: aria.PressEvent) => Promise<unknown> | unknown)
| ((event: PressEvent) => Promise<unknown> | unknown)
| null
| undefined
readonly contentClassName?: string
Expand All @@ -100,16 +93,12 @@ export interface BaseButtonProps<IconType extends string, Render>
readonly addonEnd?: Addon<Render>
}

/**
* A type that makes all properties of a type optional
*/
/** A new type `undefined` added to all properties of a type. */
type WithUndefined<T> = {
[K in keyof T]: T[K] | undefined
}

/**
* Props that are shared between buttons in a button group.
*/
/** Props that are shared between buttons in a button group. */
export interface ButtonGroupSharedButtonProps extends WithUndefined<ButtonVariants> {
readonly isDisabled?: boolean | undefined
readonly isLoading?: boolean | undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ export const BUTTON_STYLES = tv({
wrapper: 'relative block max-w-full',
loader: 'absolute inset-0 flex items-center justify-center',
content: 'flex items-center',
text: 'w-full max-w-full',
icon: 'h-[1.906cap] w-[1.906cap] flex-none aspect-square flex items-center justify-center',
addonStart: 'flex items-center justify-center macos:-mb-0.5',
addonEnd: 'flex items-center justify-center macos:-mb-0.5',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { Meta, StoryObj } from '@storybook/react'
import { IconDisplay, type IconDisplayProps } from './IconDisplay'

type Props = IconDisplayProps<string>
type Story = StoryObj<Props>

export default {
title: 'Components/IconDisplay',
component: IconDisplay,
render: (args) => <IconDisplay {...args} />,
tags: ['autodocs'],
args: { icon: 'time', children: 'aaaaaaaa' } satisfies Props,
// `text-primary` is required to make icons show up.
decorators: [(Story, context) => <div className="text-primary">{Story(context)}</div>],
parameters: {
layout: 'centered',
},
} as Meta<Props>

export const Default: Story = {}

export const Overflowing: Story = {
args: {
icon: 'sort',
children: 'very long example label that overflows the max width',
} satisfies Props,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/** @file A text display with an icon. */
import { Icon } from '#/components/Icon'
import { tv, type VariantProps } from '#/utilities/tailwindVariants'
import { Text, WithVisualTooltip, type IconProp, type TextProps, type TooltipElementType } from '..'

const ICON_DISPLAY_STYLES = tv({
base: 'flex items-center gap-2 max-w-48 min-w-4 px-1',
slots: {
icon: '-mb-0.5',
// For some reason `min-w-0` is required for the ellipsis to appear.
container: 'flex mx-auto min-w-0',
text: 'block truncate',
},
variants: {
variant: {
custom: '',
link: 'inline-block px-0 py-0 rounded-sm text-primary/50 underline border-0',
primary: 'bg-primary text-white',
accent: 'bg-accent text-white',
ghost: 'text-primary',
submit: 'bg-invite text-white opacity-80',
outline: 'border-0.5 rounded-full border-primary/20 text-primary',
},
},
defaultVariants: {
variant: 'custom',
},
})

/** Render props for {@link IconDisplay}. */
export interface IconDisplayRenderProps {
/** Defaults to `true`. */
readonly isCurrent?: boolean
/** Defaults to `false`. */
readonly isDisabled?: boolean
}

/** Props for an {@link IconDisplay}. */
export interface IconDisplayProps<IconType extends string>
extends Omit<TextProps, 'children' | 'variant' | 'variants'>,
IconDisplayRenderProps,
VariantProps<typeof ICON_DISPLAY_STYLES> {
readonly icon: IconProp<IconType, Required<IconDisplayRenderProps>>
readonly children:
| TooltipElementType
| ((renderProps: Required<IconDisplayRenderProps>) => TooltipElementType)
}

/** A text display with an icon. */
export function IconDisplay<IconType extends string>(props: IconDisplayProps<IconType>) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when I told about patterns I meant only the ICON_DISPLAY_STYLES part,

Copy link
Contributor Author

@somebody1234 somebody1234 Mar 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess, but i do want a dedicated component to avoid having to rewrite the markup (and get it right) every time, unless you have a better idea

const {
icon,
isCurrent = true,
isDisabled = false,
children,
variant,
variants = ICON_DISPLAY_STYLES,
tooltip,
...textProps
} = props
const renderProps = { isCurrent, isDisabled }

const styles = variants({ variant })

const renderedChildren = typeof children === 'function' ? children(renderProps) : children

return (
<div className={styles.base()}>
<WithVisualTooltip tooltip={tooltip} tooltipPlacement="left">
<Icon className={styles.icon()} size="medium" renderProps={renderProps}>
{icon}
</Icon>
</WithVisualTooltip>
<div className={styles.container()}>
<Text className={styles.text()} truncate="1" {...textProps} tooltip={renderedChildren}>
{renderedChildren}
</Text>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/** Barrel file for `IconDisplay`. */
export * from './IconDisplay'
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const DATE_PICKER_STYLES = tv({
dateInput: 'flex justify-start grow order-2',
dateSegment: 'rounded placeholder-shown:text-primary/30 focus:bg-primary/10 px-[0.5px]',
calendarButton: 'order-1 rotate-90',
resetButton: '',
resetButton: 'order-2',
calendarPopover: '',
calendarDialog: 'text-primary text-xs mx-2',
calendarContainer: '',
Expand All @@ -80,6 +80,43 @@ const DATE_PICKER_STYLES = tv({
},
})

/** Return the date segment using English placeholders. */
function normalizeDateSegment(segment: DateSegmentType): DateSegmentType {
if (segment.text !== segment.placeholder) {
return segment
}
switch (segment.type) {
case 'era': {
return { ...segment, text: 'AD', placeholder: 'AD' }
}
case 'year': {
return { ...segment, text: 'yyyy', placeholder: 'yyyy' }
}
case 'month': {
return { ...segment, text: 'mm', placeholder: 'mm' }
}
case 'day': {
return { ...segment, text: 'dd', placeholder: 'dd' }
}
case 'hour': {
return { ...segment, text: 'HH', placeholder: 'HH' }
}
case 'minute': {
return { ...segment, text: 'MM', placeholder: 'MM' }
}
case 'second': {
return { ...segment, text: 'SS', placeholder: 'SS' }
}
case 'timeZoneName': {
return { ...segment, text: 'UTC+XX', placeholder: 'UTC+XX' }
}
case 'dayPeriod':
case 'literal': {
return segment
}
}
}

/** Props for a {@link DatePicker}. */
export interface DatePickerProps<
Schema extends TSchema,
Expand Down Expand Up @@ -175,7 +212,7 @@ export const DatePicker = forwardRef(function DatePicker<
segments[segment.type] === false ?
<></>
: <DateSegment
segment={segment}
segment={normalizeDateSegment(segment)}
className={styles.dateSegment({
className:
segment.type === 'literal' && segment.text === ' ' ? 'w-1.5' : '',
Expand Down
26 changes: 10 additions & 16 deletions app/gui/src/dashboard/components/AriaComponents/Separator.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
/**
* @file
*
* The separator component.
*/
import * as React from 'react'

import * as aria from '#/components/aria'

import * as twv from '#/utilities/tailwindVariants'
/** @file A visual separator. */
import {
Separator as AriaSeparator,
type SeparatorProps as AriaSeparatorProps,
} from '#/components/aria'
import { tv, type VariantProps } from '#/utilities/tailwindVariants'

/** The props for {@link Separator} component. */
export interface SeparatorProps
extends aria.SeparatorProps,
twv.VariantProps<typeof SEPARATOR_STYLES> {
export interface SeparatorProps extends AriaSeparatorProps, VariantProps<typeof SEPARATOR_STYLES> {
readonly className?: string | undefined
}

/** The styles for the {@link Separator} component. */
export const SEPARATOR_STYLES = twv.tv({
export const SEPARATOR_STYLES = tv({
base: 'rounded-full border-none',
variants: {
size: {
Expand Down Expand Up @@ -75,7 +69,7 @@ export const SEPARATOR_STYLES = twv.tv({
],
})

/** A separator component. */
/** A visual separator. */
export function Separator(props: SeparatorProps) {
const {
orientation = 'horizontal',
Expand All @@ -88,5 +82,5 @@ export function Separator(props: SeparatorProps) {

const styles = variants({ orientation, variant, size, className })

return <aria.Separator orientation={orientation} className={styles} {...rest} />
return <AriaSeparator orientation={orientation} className={styles} {...rest} />
}
Loading
Loading