#505 - Data view theming

This commit is contained in:
Elio Struyf
2023-02-09 13:32:34 +01:00
parent d48e63ba32
commit bc88df98ee
9 changed files with 114 additions and 49 deletions
@@ -27,7 +27,7 @@ export const Button: React.FunctionComponent<IButtonProps> = ({
)
} ${secondary ?
getColors(`bg-red-300 hover:bg-red-400`, `bg-[var(--vscode-button-secondaryBackground)] text-[--vscode-button-secondaryForeground] hover:bg-[var(--vscode-button-secondaryHoverBackground)]`) :
getColors(`bg-teal-600 hover:bg-teal-700`, `bg-[var(--frontmatter-button-background)] text-[--vscode-button-foreground] hover:bg-[var(--frontmatter-button-hoverBackground)]`)
getColors(`bg-teal-600 hover:bg-teal-700`, `bg-[var(--frontmatter-button-background)] text-[var(--vscode-button-foreground)] hover:bg-[var(--frontmatter-button-hoverBackground)]`)
}
`}
onClick={onClick}
@@ -6,6 +6,7 @@ import { AutoFields, AutoForm, ErrorsField } from '../../../components/uniforms-
// import { AutoFields, AutoForm, ErrorsField } from 'uniforms-antd';
import { ErrorBoundary } from '@sentry/react';
import { DataFormControls } from './DataFormControls';
import useThemeColors from '../../hooks/useThemeColors';
export interface IDataFormProps {
schema: any;
@@ -21,6 +22,7 @@ export const DataForm: React.FunctionComponent<IDataFormProps> = ({
onClear
}: React.PropsWithChildren<IDataFormProps>) => {
const [bridge, setBridge] = useState<JSONSchemaBridge | null>(null);
const { getColors } = useThemeColors();
const ajv = new Ajv({ allErrors: true, useDefaults: true });
@@ -47,9 +49,9 @@ export const DataForm: React.FunctionComponent<IDataFormProps> = ({
<ErrorBoundary>
<div className="autoform">
{model ? (
<h2 className="text-gray-500 dark:text-whisper-900">Modify the data</h2>
<h2 className={getColors(`text-gray-500 dark:text-whisper-900`, `text-[var(--frontmatter-secondary-text)]`)}>Modify the data</h2>
) : (
<h2 className="text-gray-500 dark:text-whisper-900">Add new data</h2>
<h2 className={getColors(`text-gray-500 dark:text-whisper-900`, `text-[var(--frontmatter-secondary-text)]`)}>Add new data</h2>
)}
<AutoForm
@@ -1,6 +1,7 @@
import * as React from 'react';
import { useForm } from 'uniforms';
import { SubmitField } from 'uniforms-unstyled';
import useThemeColors from '../../hooks/useThemeColors';
import { Button } from '../Common/Button';
export interface IDataFormControlsProps {
@@ -13,9 +14,10 @@ export const DataFormControls: React.FunctionComponent<IDataFormControlsProps> =
onClear
}: React.PropsWithChildren<IDataFormControlsProps>) => {
const { formRef } = useForm();
const { getColors } = useThemeColors();
return (
<div className="text-right border-t border-gray-200 dark:border-vulcan-300">
<div className={`text-right border-t ${getColors(`border-gray-200 dark:border-vulcan-300`, `border-[var(--frontmatter-border)]`)}`}>
<SubmitField value={model ? `Update` : `Add`} />
<Button
@@ -21,6 +21,7 @@ import 'react-toastify/dist/ReactToastify.css';
import { DataType } from '../../../models/DataType';
import { TelemetryEvent } from '../../../constants';
import { NavigationItem } from '../Layout';
import useThemeColors from '../../hooks/useThemeColors';
export interface IDataViewProps { }
@@ -31,6 +32,7 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
const [dataEntries, setDataEntries] = useState<any | any[] | null>(null);
const settings = useRecoilValue(SettingsSelector);
const { getColors } = useThemeColors();
const setSchema = (dataFile: DataFile) => {
setSelectedData(dataFile);
@@ -173,15 +175,27 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
<div className="relative w-full flex-grow mx-auto overflow-hidden">
<div className={`flex w-64 flex-col absolute inset-y-0`}>
<aside
className={`flex flex-col flex-grow overflow-y-auto border-r border-gray-200 dark:border-vulcan-300 py-6 px-4 overflow-auto`}
className={`flex flex-col flex-grow overflow-y-auto border-r py-6 px-4 overflow-auto ${getColors(
'border-gray-200 dark:border-vulcan-300',
'border-[var(--frontmatter-border)]'
)
}`}
>
<h2 className={`text-lg text-gray-500 dark:text-whisper-900`}>
<h2 className={`text-lg ${getColors(
`text-gray-500 dark:text-whisper-900`,
`text-[var(--frontmatter-text)]`
)
}`}>
Select your data type
</h2>
<nav className={`flex-1 py-4 -mx-4 `}>
<nav className={`flex-1 py-4 -mx-4`}>
<div
className={`divide-y divide-gray-200 dark:divide-vulcan-300 border-t border-b border-gray-200 dark:border-vulcan-300`}
className={`divide-y border-t border-b ${getColors(
`divide-gray-200 dark:divide-vulcan-300 border-gray-200 dark:border-vulcan-300`,
`divide-[var(--frontmatter-border)] border-[var(--frontmatter-border)]`
)
}`}
>
{dataFiles &&
dataFiles.length > 0 &&
@@ -205,9 +219,17 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
<>
{!selectedData.singleEntry && (
<div
className={`w-1/3 py-6 px-4 flex-1 border-r border-gray-200 dark:border-vulcan-300 overflow-auto`}
className={`w-1/3 py-6 px-4 flex-1 border-r overflow-auto ${getColors(
`border-gray-200 dark:border-vulcan-300`,
`border-[var(--frontmatter-border)]`
)
}`}
>
<h2 className={`text-lg text-gray-500 dark:text-whisper-900`}>
<h2 className={`text-lg ${getColors(
`text-gray-500 dark:text-whisper-900`,
`text-[var(--frontmatter-text)]`
)
}`}>
Your {selectedData?.title?.toLowerCase() || ''} data items
</h2>
@@ -233,7 +255,7 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
</>
) : (
<div className={`flex flex-col items-center justify-center`}>
<p className={`text-gray-500 dark:text-whisper-900`}>
<p className={getColors(`text-gray-500 dark:text-whisper-900`, `text-[var(--frontmatter-text)]`)}>
No {selectedData.title.toLowerCase()} data entries found
</p>
</div>
@@ -245,7 +267,7 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
className={`${selectedData.singleEntry ? 'w-full' : 'w-2/3'
} py-6 px-4 overflow-auto`}
>
<h2 className={`text-lg text-gray-500 dark:text-whisper-900`}>
<h2 className={`text-lg ${getColors(`text-gray-500 dark:text-whisper-900`, `text-[var(--frontmatter-text)]`)}`}>
Create or modify your {selectedData.title.toLowerCase()} data
</h2>
{selectedData ? (
@@ -267,12 +289,16 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
</div>
) : (
<div className="w-full h-full flex items-center justify-center">
<div className="flex flex-col items-center text-gray-500 dark:text-whisper-900">
<div className={`flex flex-col items-center ${getColors(
'text-gray-500 dark:text-whisper-900',
'text-[var(--frontmatter-text)]'
)
}`}>
<DatabaseIcon className="w-32 h-32" />
<p className="text-3xl mt-2">No data files found</p>
<p className="text-xl mt-4">
<a
className={`text-teal-700 hover:text-teal-900`}
className={getColors(`text-teal-700 hover:text-teal-900`, `text-[var(--frontmatter-link)] hover:text-[var(--frontmatter-link-hover)]`)}
href={`https://frontmatter.codes/docs/dashboard#data-files-view`}
title={`Read more to get started using data files`}
>
@@ -281,7 +307,8 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
</p>
</div>
</div>
)}
)
}
<SponsorMsg
beta={settings?.beta}
@@ -290,6 +317,6 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
/>
<ToastContainer />
</div>
</div >
);
};
@@ -1,15 +1,18 @@
import { ExclamationCircleIcon } from '@heroicons/react/outline';
import * as React from 'react';
import useThemeColors from '../../hooks/useThemeColors';
export interface IEmptyViewProps {}
export interface IEmptyViewProps { }
export const EmptyView: React.FunctionComponent<IEmptyViewProps> = (
props: React.PropsWithChildren<IEmptyViewProps>
) => {
const { getColors } = useThemeColors();
return (
<div className="flex flex-col items-center justify-center w-full">
<ExclamationCircleIcon className={`w-1/12 text-gray-500 dark:text-whisper-900 opacity-90`} />
<h2 className={`text-xl text-gray-500 dark:text-whisper-900`}>Select your date type first</h2>
<ExclamationCircleIcon className={`w-1/12 opacity-90 ${getColors(`text-gray-500 dark:text-whisper-900`, `text-[var(--frontmatter-secondary-text)]`)}`} />
<h2 className={`text-xl ${getColors(`text-gray-500 dark:text-whisper-900`, `text-[var(--frontmatter-secondary-text)]`)}`}>Select your date type first</h2>
</div>
);
};
@@ -1,14 +1,20 @@
import * as React from 'react';
import { SortableContainer } from 'react-sortable-hoc';
import useThemeColors from '../../hooks/useThemeColors';
export interface ISortableContainerProps {}
export interface ISortableContainerProps { }
export const Container = SortableContainer(
({ children }: React.PropsWithChildren<ISortableContainerProps>) => (
<ul
className={`-mx-4 divide-y divide-gray-200 dark:divide-vulcan-300 border-t border-b border-gray-200 dark:border-vulcan-300`}
>
{children}
</ul>
)
({ children }: React.PropsWithChildren<ISortableContainerProps>) => {
const { getColors } = useThemeColors();
return (
<ul
className={`-mx-4 divide-y border-t border-b ${getColors(`divide-gray-200 dark:divide-vulcan-300 border-gray-200 dark:border-vulcan-300`, `divide-[var(--frontmatter-list-border)] border-[var(--frontmatter-list-border)]`)
}`}
>
{children}
</ul>
);
}
);
@@ -1,6 +1,7 @@
import { PencilIcon, SelectorIcon, TrashIcon, XIcon } from '@heroicons/react/outline';
import * as React from 'react';
import { SortableHandle, SortableElement } from 'react-sortable-hoc';
import useThemeColors from '../../hooks/useThemeColors';
import { Alert } from '../Modals/Alert';
export interface ISortableItemProps {
@@ -12,7 +13,7 @@ export interface ISortableItemProps {
onDeleteItem: (index: number) => void;
}
const DragHandle = SortableHandle(() => <SelectorIcon className={`w-6 h-6 cursor-move`} />);
const DragHandle = SortableHandle(() => <SelectorIcon className={`w-6 h-6 cursor-move hover:text-[var(--frontmatter-link-hover)]`} />);
export const SortableItem = SortableElement(
({
@@ -23,6 +24,7 @@ export const SortableItem = SortableElement(
onDeleteItem
}: ISortableItemProps) => {
const [showAlert, setShowAlert] = React.useState(false);
const { getColors } = useThemeColors();
const deleteItemConfirm = () => {
setShowAlert(true);
@@ -32,9 +34,12 @@ export const SortableItem = SortableElement(
<>
<li
data-test={`${selectedIndex}-${crntIndex}`}
className={`sortable_item py-2 px-2 w-full flex justify-between content-center hover:bg-gray-200 dark:hover:bg-vulcan-400 ${
selectedIndex === crntIndex ? `bg-gray-300 dark:bg-vulcan-300` : ``
}`}
className={`sortable_item py-2 px-2 w-full flex justify-between content-center cursor-pointer ${selectedIndex === crntIndex ? getColors(`bg-gray-300 dark:bg-vulcan-300`, `bg-[var(--frontmatter-list-selected-background)] text-[var(--frontmatter-list-selected-text)]`) : ``
} ${getColors(
'hover:bg-gray-200 dark:hover:bg-vulcan-400',
'hover:bg-[var(--frontmatter-list-hover-background)]'
)
}`}
>
<div
className="flex items-center w-full"
@@ -47,7 +52,12 @@ export const SortableItem = SortableElement(
<div className={`space-x-2 flex items-center`}>
<button
type="button"
className={`text-gray-500 dark:text-whisper-900 hover:text-gray-600 dark:hover:text-whisper-500`}
className={
getColors(
`text-gray-500 dark:text-whisper-900 hover:text-gray-600 dark:hover:text-whisper-500`,
`text-[var(--frontmatter-secondary-text)] hover:text-[var(--frontmatter-link-hover)]`
)
}
title={`Edit "${value}"`}
onClick={() => onSelectedIndexChange(crntIndex)}
>
@@ -56,7 +66,12 @@ export const SortableItem = SortableElement(
</button>
<button
type="button"
className={`text-gray-500 dark:text-whisper-900 hover:text-gray-600 dark:hover:text-whisper-500`}
className={
getColors(
`text-gray-500 dark:text-whisper-900 hover:text-gray-600 dark:hover:text-whisper-500`,
`text-[var(--frontmatter-secondary-text)] hover:text-[var(--frontmatter-link-hover)]`
)
}
title={`Delete "${value}"`}
onClick={() => deleteItemConfirm()}
>
@@ -12,25 +12,23 @@ export const NavigationItem: React.FunctionComponent<INavigationItemProps> = ({
children
}: React.PropsWithChildren<INavigationItemProps>) => {
const { getColors } = useThemeColors();
return (
<button
type="button"
className={`navigationitem px-4 py-2 flex items-center text-sm font-medium w-full text-left cursor-pointer ${
getColors(
'hover:bg-gray-200 dark:hover:bg-vulcan-400 hover:text-vulcan-500 dark:hover:text-whisper-500',
'hover:bg-[var(--vscode-list-hoverBackground)] hover:text-[var(--vscode-list-hoverForeground)]'
)
} ${
isSelected
className={`navigationitem px-4 py-2 flex items-center text-sm font-medium w-full text-left cursor-pointer ${getColors(
'hover:bg-gray-200 dark:hover:bg-vulcan-400 hover:text-vulcan-500 dark:hover:text-whisper-500',
'hover:bg-[var(--frontmatter-list-hover-background)] hover:text-[var(--frontmatter-list-selected-text)]'
)
} ${isSelected
? getColors(
'bg-gray-300 dark:bg-vulcan-300 text-vulcan-500 dark:text-whisper-500',
'bg-[var(--vscode-list-activeSelectionBackground)] text-[var(--vscode-list-activeSelectionForeground)]'
'bg-gray-300 dark:bg-vulcan-300 text-vulcan-500 dark:text-whisper-500',
'bg-[var(--frontmatter-list-selected-background)] text-[var(--frontmatter-list-selected-text)]'
) : getColors(
'text-gray-500 dark:text-whisper-900',
'text-[var(--vscode-tab-inactiveForeground)]'
'text-[var(--frontmatter-list-text)]'
)
}`}
}`}
onClick={onClick}
>
{children}
+16 -4
View File
@@ -42,11 +42,23 @@ const preserveColor = (color: string | undefined) => {
const updateCssVariables = () => {
const styles = getComputedStyle(document.documentElement);
const panelBorder = styles.getPropertyValue('--vscode-panel-border');
if (panelBorder) {
document.documentElement.style.setProperty('--frontmatter-border', preserveColor(panelBorder) || "var(--vscode-panel-border)");
}
// Text
document.documentElement.style.setProperty('--frontmatter-text', 'var(--vscode-editor-foreground)');
document.documentElement.style.setProperty('--frontmatter-secondary-text', 'var(--vscode-editorHint-foreground)');
document.documentElement.style.setProperty('--frontmatter-link', 'var(--vscode-textLink-foreground)');
document.documentElement.style.setProperty('--frontmatter-link-hover', 'var(--vscode-textLink-activeForeground)');
// List
document.documentElement.style.setProperty('--frontmatter-list-text', 'var(--vscode-editor-foreground)');
document.documentElement.style.setProperty('--frontmatter-list-background', 'var(--vscode-list-activeSelectionBackground)');
document.documentElement.style.setProperty('--frontmatter-list-hover-background', 'var(--vscode-list-hoverBackground)');
document.documentElement.style.setProperty('--frontmatter-list-selected-background', 'var(--vscode-list-activeSelectionBackground)');
document.documentElement.style.setProperty('--frontmatter-list-selected-text', 'var(--vscode-list-activeSelectionForeground)');
// Borders
document.documentElement.style.setProperty('--frontmatter-border', 'var(--vscode-panel-border)');
// Other colors which should be preserved (no opacity)
const buttonBackground = styles.getPropertyValue('--vscode-button-background');
if (buttonBackground) {
document.documentElement.style.setProperty('--frontmatter-button-background', preserveColor(buttonBackground) || "var(--vscode-button-background)");