Skip to content

Commit

Permalink
feat(ui): add auto-links to text, heading, field description and work…
Browse files Browse the repository at this point in the history
…flow descriptions
  • Loading branch information
psychedelicious committed Feb 28, 2025
1 parent 51d6610 commit 94771ea
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 6 deletions.
2 changes: 2 additions & 0 deletions invokeai/frontend/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"idb-keyval": "^6.2.1",
"jsondiffpatch": "^0.6.0",
"konva": "^9.3.15",
"linkify-react": "^4.2.0",
"linkifyjs": "^4.2.0",
"lodash-es": "^4.17.21",
"lru-cache": "^11.0.1",
"mtwist": "^1.0.2",
Expand Down
20 changes: 20 additions & 0 deletions invokeai/frontend/web/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions invokeai/frontend/web/src/common/components/linkify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { SystemStyleObject } from '@invoke-ai/ui-library';
import type { Opts as LinkifyOpts } from 'linkifyjs';

export const linkifySx: SystemStyleObject = {
a: {
fontWeight: 'semibold',
},
'a:hover': {
textDecoration: 'underline',
},
};

export const linkifyOptions: LinkifyOpts = {
target: '_blank',
rel: 'noopener noreferrer',
validate: (value) => /^https?:\/\//.test(value),
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Text } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
import { linkifyOptions, linkifySx } from 'common/components/linkify';
import { selectWorkflowDescription } from 'features/nodes/store/workflowSlice';
import Linkify from 'linkify-react';
import { memo } from 'react';

export const ActiveWorkflowDescription = memo(() => {
Expand All @@ -11,8 +13,8 @@ export const ActiveWorkflowDescription = memo(() => {
}

return (
<Text color="base.300" fontStyle="italic" pb={2}>
{description}
<Text color="base.300" fontStyle="italic" pb={2} sx={linkifySx}>
<Linkify options={linkifyOptions}>{description}</Linkify>
</Text>
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { HeadingProps, SystemStyleObject } from '@invoke-ai/ui-library';
import { Text } from '@invoke-ai/ui-library';
import { linkifyOptions, linkifySx } from 'common/components/linkify';
import Linkify from 'linkify-react';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';

Expand All @@ -9,13 +11,14 @@ const headingSx: SystemStyleObject = {
'&[data-is-empty="true"]': {
opacity: 0.3,
},
...linkifySx,
};

export const HeadingElementContent = memo(({ content, ...rest }: { content: string } & HeadingProps) => {
const { t } = useTranslation();
return (
<Text sx={headingSx} data-is-empty={content === ''} {...rest}>
{content || t('workflows.builder.headingPlaceholder')}
<Linkify options={linkifyOptions}>{content || t('workflows.builder.headingPlaceholder')}</Linkify>
</Text>
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { FormHelperText, Textarea } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import { linkifyOptions, linkifySx } from 'common/components/linkify';
import { useEditable } from 'common/hooks/useEditable';
import { useInputFieldDescription } from 'features/nodes/hooks/useInputFieldDescription';
import { useInputFieldTemplate } from 'features/nodes/hooks/useInputFieldTemplate';
import { fieldDescriptionChanged } from 'features/nodes/store/nodesSlice';
import type { NodeFieldElement } from 'features/nodes/types/workflow';
import Linkify from 'linkify-react';
import { memo, useCallback, useRef } from 'react';

export const NodeFieldElementDescriptionEditable = memo(({ el }: { el: NodeFieldElement }) => {
Expand Down Expand Up @@ -36,7 +38,11 @@ export const NodeFieldElementDescriptionEditable = memo(({ el }: { el: NodeField
});

if (!editable.isEditing) {
return <FormHelperText onDoubleClick={editable.startEditing}>{editable.value}</FormHelperText>;
return (
<FormHelperText onDoubleClick={editable.startEditing} sx={linkifySx}>
<Linkify options={linkifyOptions}>{editable.value}</Linkify>
</FormHelperText>
);
}

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import type { SystemStyleObject } from '@invoke-ai/ui-library';
import { Flex, FormControl, FormHelperText } from '@invoke-ai/ui-library';
import { linkifyOptions, linkifySx } from 'common/components/linkify';
import { InputFieldRenderer } from 'features/nodes/components/flow/nodes/Invocation/fields/InputFieldRenderer';
import { useContainerContext } from 'features/nodes/components/sidePanel/builder/contexts';
import { NodeFieldElementLabel } from 'features/nodes/components/sidePanel/builder/NodeFieldElementLabel';
import { useInputFieldDescription } from 'features/nodes/hooks/useInputFieldDescription';
import { useInputFieldTemplate } from 'features/nodes/hooks/useInputFieldTemplate';
import type { NodeFieldElement } from 'features/nodes/types/workflow';
import { NODE_FIELD_CLASS_NAME } from 'features/nodes/types/workflow';
import Linkify from 'linkify-react';
import { memo, useMemo } from 'react';

const sx: SystemStyleObject = {
Expand Down Expand Up @@ -43,7 +45,11 @@ export const NodeFieldElementViewMode = memo(({ el }: { el: NodeFieldElement })
settings={data.settings}
/>
</Flex>
{showDescription && _description && <FormHelperText>{_description}</FormHelperText>}
{showDescription && _description && (
<FormHelperText sx={linkifySx}>
<Linkify options={linkifyOptions}>{_description}</Linkify>
</FormHelperText>
)}
</FormControl>
</Flex>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { SystemStyleObject, TextProps } from '@invoke-ai/ui-library';
import { Text } from '@invoke-ai/ui-library';
import { linkifyOptions, linkifySx } from 'common/components/linkify';
import Linkify from 'linkify-react';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';

Expand All @@ -9,13 +11,14 @@ const textSx: SystemStyleObject = {
'&[data-is-empty="true"]': {
opacity: 0.3,
},
...linkifySx,
};

export const TextElementContent = memo(({ content, ...rest }: { content: string } & TextProps) => {
const { t } = useTranslation();
return (
<Text sx={textSx} data-is-empty={content === ''} {...rest}>
{content || t('workflows.builder.textPlaceholder')}
<Linkify options={linkifyOptions}>{content || t('workflows.builder.textPlaceholder')}</Linkify>
</Text>
);
});
Expand Down

0 comments on commit 94771ea

Please sign in to comment.