feat: Improve MarkdownViewer styles for headings and code blocks

This commit updates the styles in the MarkdownViewer component to improve the visual hierarchy of headings and code blocks. It adds margin-bottom to h3, h4, and h5 headings to create better spacing between them and the content. Additionally, it removes unnecessary code in the code block rendering logic to simplify the component. These changes enhance the readability and aesthetics of the rendered Markdown content.
This commit is contained in:
Simon Larsen
2024-07-15 07:36:16 -06:00
parent 0f0f2c1b81
commit 39b5982d67
3 changed files with 81 additions and 22 deletions

View File

@@ -38,27 +38,27 @@ const Alert: FunctionComponent<ComponentProps> = (
type = props.type;
}
let className: string = "text-blue";
let bgClassName: string = "bg-blue";
let className: string = "text-gray";
let bgClassName: string = "bg-gray";
if (AlertType.DANGER === type) {
className = "text-red";
bgClassName = "bg-red";
bgClassName = "bg-gray";
} else if (AlertType.INFO === type) {
className = "text-blue";
bgClassName = "bg-blue";
className = "text-gray";
bgClassName = "bg-gray";
} else if (AlertType.WARNING === type) {
className = "text-yellow";
bgClassName = "bg-yellow";
bgClassName = "bg-gray";
} else if (AlertType.SUCCESS === type) {
className = "text-green";
bgClassName = "bg-green";
bgClassName = "bg-gray";
}
return (
<div
id={props.id}
className={`rounded-md ${bgClassName}-50 p-4`}
className={`rounded-md ${bgClassName}-700 p-4`}
data-testid={props.dataTestId}
onClick={() => {
props.onClick && props.onClick();
@@ -76,10 +76,10 @@ const Alert: FunctionComponent<ComponentProps> = (
{!props.doNotShowIcon && (
<div className="flex-shrink-0">
{AlertType.DANGER === type && (
<Icon icon={IconProp.Alert} className="h-5 w-5 text-red-400" />
<Icon icon={IconProp.Alert} className="h-5 w-5 text-red-200" />
)}
{AlertType.WARNING === type && (
<Icon icon={IconProp.Alert} className="h-5 w-5 text-yellow-400" />
<Icon icon={IconProp.Alert} className="h-5 w-5 text-yellow-200" />
)}
{AlertType.SUCCESS === type && (
<Icon
@@ -88,14 +88,14 @@ const Alert: FunctionComponent<ComponentProps> = (
/>
)}
{AlertType.INFO === type && (
<Icon icon={IconProp.Info} className="h-5 w-5 text-blue-400" />
<Icon icon={IconProp.Info} className="h-5 w-5 text-gray-200" />
)}
</div>
)}
<div
className={`ml-3 flex-1 md:flex md:justify-between ${props.className}`}
>
<p className={props.textClassName || `text-sm ${className}-600`}>
<p className={props.textClassName || `text-sm ${className}-200`}>
<span className="font-medium">
{props.strongTitle} {props.title && props.strongTitle ? "-" : ""}{" "}
</span>
@@ -108,7 +108,7 @@ const Alert: FunctionComponent<ComponentProps> = (
props.onClose && props.onClose();
}}
role={"alert-close-button"}
className={`whitespace-nowrap font-medium ${className}-500 hover:${className}-600`}
className={`whitespace-nowrap font-medium ${className}-200 hover:${className}-50`}
>
Close
<span aria-hidden="true"> &rarr;</span>

View File

@@ -35,13 +35,13 @@ const MarkdownViewer: FunctionComponent<ComponentProps> = (
);
},
h3: ({ ...props }: any) => {
return <h3 className="text-xl mt-8" {...props} />;
return <h3 className="text-xl mt-8 mb-5" {...props} />;
},
h4: ({ ...props }: any) => {
return <h4 className="text-lg mt-5" {...props} />;
return <h4 className="text-lg mt-5 mb-3" {...props} />;
},
h5: ({ ...props }: any) => {
return <h5 className="text-lg mt-2" {...props} />;
return <h5 className="text-lg mt-2 mb-1" {...props} />;
},
h6: ({ ...props }: any) => {
return <h6 className="text-base mt-1" {...props} />;
@@ -79,24 +79,28 @@ const MarkdownViewer: FunctionComponent<ComponentProps> = (
},
code: (props: any) => {
const { children, className, ...rest } = props;
// eslint-disable-next-line wrap-regex
const match: RegExpExecArray | null = /language-(\w+)/.exec(
className || "",
);
const content: string = String(children).replace(/\n$/, "");
const content: string = String(children as string).replace(
/\n$/,
"",
);
return match ? (
<SyntaxHighlighter
{...rest}
PreTag="div"
// eslint-disable-next-line react/no-children-prop
children={content}
language={match[1]}
style={a11yDark}
/>
) : (
<code {...rest} className={className}>
{children}
</code>
<code {...rest}>{children}</code>
);
},
}}

View File

@@ -13,11 +13,19 @@ import React, {
Fragment,
FunctionComponent,
ReactElement,
useEffect,
useState,
} from "react";
import CopilotLastRunAt from "../../../../Components/Copilot/LastRunMessage";
import ModelAPI from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import PageMap from "../../../../Utils/PageMap";
import ServiceCopilotCodeRepository from "Model/Models/ServiceCopilotCodeRepository";
import ErrorMessage from "CommonUI/src/Components/ErrorMessage/ErrorMessage";
import API from "CommonUI/src/Utils/API/API";
import Alert, { AlertType } from "CommonUI/src/Components/Alerts/Alert";
import RouteMap, { RouteUtil } from "../../../../Utils/RouteMap";
const StatusPageView: FunctionComponent<
const CopilotPageView: FunctionComponent<
PageComponentProps
> = (): ReactElement => {
const modelId: ObjectID = Navigation.getLastParamAsObjectID();
@@ -25,10 +33,57 @@ const StatusPageView: FunctionComponent<
const [codeRepository, setCodeRepository] =
useState<CopilotCodeRepository | null>(null);
const [serviceCount, setServiceCount] = useState<number | null>(null);
const [error, setError] = useState<string | null>(null);
type FetchServiceCount = () => Promise<void>;
const fetchServiceCount: FetchServiceCount = async (): Promise<void> => {
try {
const count: number = await ModelAPI.count<ServiceCopilotCodeRepository>({
modelType: ServiceCopilotCodeRepository,
query: {
codeRepositoryId: modelId,
},
});
setServiceCount(count);
} catch (error: unknown) {
setError(API.getFriendlyMessage(error));
}
};
useEffect(() => {
fetchServiceCount().catch((error: unknown) => {
setError(API.getFriendlyMessage(error));
});
}, []);
if (error) {
return <ErrorMessage error={error} />;
}
return (
<Fragment>
{/* CopilotCodeRepository View */}
{serviceCount !== null && serviceCount === 0 && (
<Alert
className="cursor-pointer"
type={AlertType.WARNING}
strongTitle="Next Step"
title="Pleas click here to add services to this code-repository."
onClick={() => {
return Navigation.navigate(
RouteUtil.populateRouteParams(
RouteMap[PageMap.AI_COPILOT_CODE_REPOSITORY_VIEW_SERVICES]!,
{ modelId: modelId },
),
);
}}
/>
)}
<CopilotLastRunAt
codeRepositoryId={modelId}
lastRunAt={codeRepository?.lastCopilotRunDateTime}
@@ -226,4 +281,4 @@ const StatusPageView: FunctionComponent<
);
};
export default StatusPageView;
export default CopilotPageView;