mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
LogTable and LogSidePanel UI tweaks (#88)
* Tweak colors and contrast for log table row hover and selected state * Styling tweaks for LogSidePanel – header, shadow, borders, etc * Add [X] button to LogSidePanel * Use CSS modules for styling * LogTable – use chevron icon instead of `>` symbol * Use `col-resize` cursor when resizing LogTable columns * Use correct env var for HDX_API_KEY in `app` to fix client sessions   
This commit is contained in:
parent
b1a537d88c
commit
04f82d71db
8 changed files with 351 additions and 168 deletions
5
.changeset/healthy-drinks-lie.md
Normal file
5
.changeset/healthy-drinks-lie.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@hyperdx/app': minor
|
||||
---
|
||||
|
||||
LogTable and LogSidePanel UI tweaks
|
||||
|
|
@ -27,6 +27,7 @@ import SearchInput from './SearchInput';
|
|||
import TabBar from './TabBar';
|
||||
import TimelineChart from './TimelineChart';
|
||||
import SessionSubpanel from './SessionSubpanel';
|
||||
import LogSidePanelKbdShortcuts from './LogSidePanelKbdShortcuts';
|
||||
import {
|
||||
formatDistanceToNowStrictShort,
|
||||
useFirstNonNullValue,
|
||||
|
|
@ -41,6 +42,8 @@ import { CurlGenerator } from './curlGenerator';
|
|||
import { Dictionary } from './types';
|
||||
import { ZIndexContext, useZIndex } from './zIndex';
|
||||
|
||||
import styles from '../styles/LogSidePanel.module.scss';
|
||||
|
||||
const HDX_BODY_FIELD = '_hdx_body';
|
||||
|
||||
// https://github.com/reduxjs/redux-devtools/blob/f11383d294c1139081f119ef08aa1169bd2ad5ff/packages/react-json-tree/src/createStylingFromTheme.ts
|
||||
|
|
@ -1765,8 +1768,10 @@ function SidePanelHeader({
|
|||
logData,
|
||||
onPropertyAddClick,
|
||||
generateSearchUrl,
|
||||
onClose,
|
||||
}: {
|
||||
logData: any;
|
||||
onClose: VoidFunction;
|
||||
onPropertyAddClick?: (name: string, value: string) => void;
|
||||
generateSearchUrl: (
|
||||
query?: string,
|
||||
|
|
@ -1800,10 +1805,10 @@ function SidePanelHeader({
|
|||
|
||||
return (
|
||||
<div>
|
||||
<div className="d-flex justify-content-between align-items-center">
|
||||
<div className={styles.panelHeader}>
|
||||
<div>
|
||||
{logData.severity_text != null ? (
|
||||
<span className="me-2">
|
||||
<span className={styles.severityChip}>
|
||||
<LogLevel level={logData?.severity_text ?? ''} />
|
||||
</span>
|
||||
) : null}
|
||||
|
|
@ -1817,8 +1822,8 @@ function SidePanelHeader({
|
|||
<span className="text-muted">at</span>{' '}
|
||||
{format(new Date(logData.timestamp), 'MMM d HH:mm:ss.SSS')}{' '}
|
||||
<span className="text-muted">
|
||||
({formatDistanceToNowStrictShort(new Date(logData.timestamp))}{' '}
|
||||
ago)
|
||||
·{' '}
|
||||
{formatDistanceToNowStrictShort(new Date(logData.timestamp))} ago
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -1864,57 +1869,67 @@ function SidePanelHeader({
|
|||
Share Event
|
||||
</Button>
|
||||
</CopyToClipboard>
|
||||
<Button
|
||||
variant="dark"
|
||||
className="text-muted-hover d-flex align-items-center"
|
||||
size="sm"
|
||||
onClick={onClose}
|
||||
>
|
||||
<i className="bi bi-x-lg" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<div
|
||||
className="bg-hdx-dark p-3 overflow-auto"
|
||||
style={{ maxHeight: 300 }}
|
||||
>
|
||||
{stripAnsi(logData.body)}
|
||||
<div className={styles.panelDetails}>
|
||||
<div>
|
||||
<div
|
||||
className="bg-hdx-dark p-3 overflow-auto"
|
||||
style={{ maxHeight: 300 }}
|
||||
>
|
||||
{stripAnsi(logData.body)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex flex-wrap">
|
||||
{logData._service ? (
|
||||
<EventTag
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
name="service"
|
||||
value={logData._service}
|
||||
/>
|
||||
) : null}
|
||||
{logData._host ? (
|
||||
<EventTag
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
name="host"
|
||||
value={logData._host}
|
||||
/>
|
||||
) : null}
|
||||
{userEmail ? (
|
||||
<EventTag
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
name="userEmail"
|
||||
value={userEmail}
|
||||
/>
|
||||
) : null}
|
||||
{userName ? (
|
||||
<EventTag
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
name="userName"
|
||||
value={userName}
|
||||
/>
|
||||
) : null}
|
||||
{teamName ? (
|
||||
<EventTag
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
name="teamName"
|
||||
value={teamName}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex mt-2">
|
||||
{logData._service ? (
|
||||
<EventTag
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
name="service"
|
||||
value={logData._service}
|
||||
/>
|
||||
) : null}
|
||||
{logData._host ? (
|
||||
<EventTag
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
name="host"
|
||||
value={logData._host}
|
||||
/>
|
||||
) : null}
|
||||
{userEmail ? (
|
||||
<EventTag
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
name="userEmail"
|
||||
value={userEmail}
|
||||
/>
|
||||
) : null}
|
||||
{userName ? (
|
||||
<EventTag
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
name="userName"
|
||||
value={userName}
|
||||
/>
|
||||
) : null}
|
||||
{teamName ? (
|
||||
<EventTag
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
name="teamName"
|
||||
value={teamName}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -2109,6 +2124,7 @@ export default function LogSidePanel({
|
|||
// We'll need to handle this properly eventually...
|
||||
const tab = isNestedPanel ? stateTab : queryTab;
|
||||
const setTab = isNestedPanel ? setStateTab : setQueryTab;
|
||||
|
||||
const _onClose = useCallback(() => {
|
||||
// Reset tab to undefined when unmounting, so that when we open the drawer again, it doesn't open to the last tab
|
||||
// (which might not be valid, ex session replay)
|
||||
|
|
@ -2170,9 +2186,10 @@ export default function LogSidePanel({
|
|||
|
||||
return (
|
||||
<Drawer
|
||||
enableOverlay
|
||||
overlayOpacity={0.1}
|
||||
customIdSuffix={`log-side-panel-${logId}`}
|
||||
duration={0}
|
||||
overlayOpacity={0.2}
|
||||
open={logId != null}
|
||||
onClose={() => {
|
||||
if (!subDrawerOpen) {
|
||||
|
|
@ -2181,26 +2198,22 @@ export default function LogSidePanel({
|
|||
}}
|
||||
direction="right"
|
||||
size={displayedTab === 'replay' || isSmallScreen ? '80vw' : '60vw'}
|
||||
style={{ background: '#0F1216' }}
|
||||
className="border-start border-dark"
|
||||
zIndex={drawerZIndex}
|
||||
// enableOverlay={subDrawerOpen}
|
||||
>
|
||||
<ZIndexContext.Provider value={drawerZIndex}>
|
||||
<div
|
||||
className="p-3 h-100 d-flex flex-column fs-8"
|
||||
style={{ marginTop: 20 }}
|
||||
>
|
||||
{isLoading && <h3>Loading...</h3>}
|
||||
<div className={styles.panel}>
|
||||
{isLoading && <div className={styles.loadingState}>Loading...</div>}
|
||||
{logData != null && !isLoading ? (
|
||||
<>
|
||||
<SidePanelHeader
|
||||
logData={logData}
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
onClose={_onClose}
|
||||
/>
|
||||
<TabBar
|
||||
className="fs-8 mb-2 mt-4"
|
||||
className="fs-8 mb-2 mt-2"
|
||||
items={[
|
||||
{
|
||||
text: 'Parsed Properties',
|
||||
|
|
@ -2243,13 +2256,14 @@ export default function LogSidePanel({
|
|||
console.error(err);
|
||||
}}
|
||||
fallbackRender={() => (
|
||||
<div className="text-danger px-2 py-1 m-2 fs-7 font-monospace bg-danger-transparent">
|
||||
<div className="text-danger px-2 py-1 m-2 fs-7 font-monospace bg-danger-transparent p-4">
|
||||
An error occurred while rendering this event.
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
{/* Parsed Properties */}
|
||||
{displayedTab === 'parsed' ? (
|
||||
<div className="flex-grow-1 mt-1 pt-2 bg-body overflow-auto">
|
||||
<div className="flex-grow-1 px-4 bg-body overflow-auto">
|
||||
<PropertySubpanel
|
||||
logData={logData}
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
|
|
@ -2266,9 +2280,11 @@ export default function LogSidePanel({
|
|||
/>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Original Line */}
|
||||
{displayedTab === 'original' ? (
|
||||
<div
|
||||
className="mt-3 flex-grow-1 overflow-auto"
|
||||
className="flex-grow-1 px-4 overflow-auto"
|
||||
style={{ minHeight: 0 }}
|
||||
>
|
||||
<div className="my-2">
|
||||
|
|
@ -2276,9 +2292,11 @@ export default function LogSidePanel({
|
|||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Trace */}
|
||||
{displayedTab === 'trace' ? (
|
||||
<div
|
||||
className="flex-grow-1 mt-3 bg-body overflow-auto"
|
||||
className="flex-grow-1 px-4 mt-3 bg-body overflow-auto"
|
||||
style={{ minHeight: 0 }}
|
||||
>
|
||||
<TraceSubpanel
|
||||
|
|
@ -2292,15 +2310,19 @@ export default function LogSidePanel({
|
|||
/>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Debug */}
|
||||
{displayedTab === 'debug' ? (
|
||||
<div className="mt-3 overflow-auto">
|
||||
<div className="px-4 overflow-auto">
|
||||
<code>
|
||||
<pre>{JSON.stringify(logData, undefined, 4)}</pre>
|
||||
</code>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Session Replay */}
|
||||
{displayedTab === 'replay' ? (
|
||||
<div className="mt-3 overflow-hidden">
|
||||
<div className="px-4 overflow-hidden flex-grow-1">
|
||||
{rumSessionId != null ? (
|
||||
<SessionSubpanel
|
||||
start={start}
|
||||
|
|
@ -2320,6 +2342,7 @@ export default function LogSidePanel({
|
|||
</div>
|
||||
) : null}
|
||||
</ErrorBoundary>
|
||||
<LogSidePanelKbdShortcuts />
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
|||
45
packages/app/src/LogSidePanelKbdShortcuts.tsx
Normal file
45
packages/app/src/LogSidePanelKbdShortcuts.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import styles from '../styles/LogSidePanel.module.scss';
|
||||
import { CloseButton } from 'react-bootstrap';
|
||||
import { useLocalStorage } from './utils';
|
||||
import * as React from 'react';
|
||||
|
||||
const Kbd = ({ children }: { children: string }) => (
|
||||
<div className={styles.kbd}>{children}</div>
|
||||
);
|
||||
|
||||
export default function LogSidePanelKbdShortcuts() {
|
||||
const [isDismissed, setDismissed] = useLocalStorage<boolean>(
|
||||
'kbd-shortcuts-dismissed',
|
||||
false,
|
||||
);
|
||||
|
||||
const handleDismiss = React.useCallback(() => {
|
||||
setDismissed(true);
|
||||
}, []);
|
||||
|
||||
if (isDismissed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.kbdShortcuts}>
|
||||
<div className="d-flex justify-content-between align-items-center ">
|
||||
<div className="d-flex align-items-center gap-3">
|
||||
<div>
|
||||
Use <Kbd>←</Kbd>
|
||||
<Kbd>→</Kbd> arrow keys to move through events
|
||||
</div>
|
||||
<div className={styles.kbdDivider} />
|
||||
<div>
|
||||
<Kbd>ESC</Kbd> to close
|
||||
</div>
|
||||
</div>
|
||||
<CloseButton
|
||||
variant="white"
|
||||
aria-label="Hide"
|
||||
onClick={handleDismiss}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -26,6 +26,8 @@ import { useLocalStorage, usePrevious, useWindowSize } from './utils';
|
|||
import { useSearchEventStream } from './search';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
|
||||
import styles from '../styles/LogTable.module.scss';
|
||||
|
||||
type Row = Record<string, any> & { duration: number };
|
||||
type AccessorFn = (row: Row, column: string) => any;
|
||||
|
||||
|
|
@ -316,7 +318,7 @@ export const RawLogTable = memo(
|
|||
onRowExpandClick(id, sort_key);
|
||||
}}
|
||||
>
|
||||
{'> '}
|
||||
<span className="bi bi-chevron-right" />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
@ -564,7 +566,7 @@ export const RawLogTable = memo(
|
|||
|
||||
return (
|
||||
<div
|
||||
className="overflow-auto h-100 fs-8 bg-inherit py-2"
|
||||
className="overflow-auto h-100 fs-8 bg-inherit"
|
||||
onScroll={e => {
|
||||
fetchMoreOnBottomReached(e.target as HTMLDivElement);
|
||||
|
||||
|
|
@ -582,14 +584,7 @@ export const RawLogTable = memo(
|
|||
id={tableId}
|
||||
style={{ tableLayout: 'fixed' }}
|
||||
>
|
||||
<thead
|
||||
className="bg-inherit"
|
||||
style={{
|
||||
background: 'inherit',
|
||||
position: 'sticky',
|
||||
top: 0,
|
||||
}}
|
||||
>
|
||||
<thead className={styles.tableHead}>
|
||||
{table.getHeaderGroups().map(headerGroup => (
|
||||
<tr key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header, headerIndex) => {
|
||||
|
|
@ -623,7 +618,7 @@ export const RawLogTable = memo(
|
|||
<div
|
||||
onMouseDown={header.getResizeHandler()}
|
||||
onTouchStart={header.getResizeHandler()}
|
||||
className={`resizer text-gray-600 cursor-grab ${
|
||||
className={`resizer text-gray-600 cursor-col-resize ${
|
||||
header.column.getIsResizing() ? 'isResizing' : ''
|
||||
}`}
|
||||
style={{
|
||||
|
|
@ -690,8 +685,9 @@ export const RawLogTable = memo(
|
|||
}}
|
||||
role="button"
|
||||
key={virtualRow.key}
|
||||
className={cx('bg-default-dark-grey-hover', {
|
||||
'bg-dark-grey': highlightedLineId === row.original.id,
|
||||
className={cx(styles.tableRow, {
|
||||
[styles.tableRow__selected]:
|
||||
highlightedLineId === row.original.id,
|
||||
})}
|
||||
data-index={virtualRow.index}
|
||||
ref={rowVirtualizer.measureElement}
|
||||
|
|
|
|||
73
packages/app/styles/LogSidePanel.module.scss
Normal file
73
packages/app/styles/LogSidePanel.module.scss
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
@import './variables';
|
||||
|
||||
// TODO: Use variables for spacings
|
||||
$padding-x: 24px;
|
||||
|
||||
.panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 12px;
|
||||
height: 100%;
|
||||
background-color: $body-bg;
|
||||
box-shadow: 0 0 100px 40px rgba(0, 0, 0, 0.7);
|
||||
border-left: 1px solid $slate-900;
|
||||
}
|
||||
|
||||
.panelHeader {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid $slate-900;
|
||||
padding: 12px $padding-x;
|
||||
}
|
||||
|
||||
.panelDetails {
|
||||
padding: $padding-x;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.panelContent {
|
||||
padding: 0 $padding-x;
|
||||
}
|
||||
|
||||
.severityChip {
|
||||
background: $slate-800;
|
||||
padding: 4px 12px;
|
||||
border-radius: 16px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.loadingState {
|
||||
color: $slate-600;
|
||||
width: 100%;
|
||||
margin: $padding-x;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.kbdShortcuts {
|
||||
background: $slate-950;
|
||||
border-top: 1px solid $slate-900;
|
||||
padding: 12px $padding-x;
|
||||
color: $slate-300;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.kbd {
|
||||
display: inline-block;
|
||||
background: $slate-900;
|
||||
letter-spacing: 0.5px;
|
||||
border: 1px solid $slate-500;
|
||||
border-radius: 4px;
|
||||
padding: 1px 6px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.kbdDivider {
|
||||
height: 21px;
|
||||
width: 1px;
|
||||
background: $slate-800;
|
||||
}
|
||||
17
packages/app/styles/LogTable.module.scss
Normal file
17
packages/app/styles/LogTable.module.scss
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
@import './variables';
|
||||
|
||||
.tableHead {
|
||||
background: inherit;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.tableRow {
|
||||
&:hover {
|
||||
background-color: $slate-800;
|
||||
}
|
||||
&__selected {
|
||||
background-color: $slate-800;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,90 +1,4 @@
|
|||
$text-muted: #c4c4c4;
|
||||
$text-purple: #9357ff; // This isn't a bootstrap variable
|
||||
$text-light: #f8f8f2;
|
||||
$green: #50fa7b;
|
||||
$red: #ff5d5b;
|
||||
$blue: #3788f6;
|
||||
$purple: #8f57f3;
|
||||
|
||||
$gray-100: #f8f9fa;
|
||||
$body-color: $gray-100;
|
||||
|
||||
$bg-hdx-dark: #1a1d23;
|
||||
$bg-dark-grey: #1f2429;
|
||||
$bg-grey: #21272e;
|
||||
$bg-purple: #2e273b;
|
||||
$bg-purple-active: #4a4eb5;
|
||||
$body-bg: #0f1216;
|
||||
$code-color: #4bb74a;
|
||||
|
||||
$info: $purple;
|
||||
|
||||
$spacer: 1rem;
|
||||
$spacers: (
|
||||
0: 0,
|
||||
0\.5: $spacer * 0.125,
|
||||
1: $spacer * 0.25,
|
||||
2: $spacer * 0.5,
|
||||
2\.5: $spacer * 0.75,
|
||||
3: $spacer,
|
||||
4: $spacer * 1.5,
|
||||
4\.5: $spacer * 2,
|
||||
5: $spacer * 3,
|
||||
6: $spacer * 4,
|
||||
7: $spacer * 5,
|
||||
8: $spacer * 8,
|
||||
10: $spacer * 10,
|
||||
14: $spacer * 14,
|
||||
16: $spacer * 16,
|
||||
);
|
||||
|
||||
$navbar-dark-active-color: $green;
|
||||
$navbar-dark-color: rgba(#fff, 0.75);
|
||||
$navbar-dark-hover-color: rgba(#fff, 1);
|
||||
|
||||
$dropdown-dark-bg: $bg-grey;
|
||||
|
||||
$popover-bg: $bg-purple;
|
||||
|
||||
$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`
|
||||
|
||||
$h1-font-size: $font-size-base * 2.5 !default;
|
||||
$h2-font-size: $font-size-base * 2 !default;
|
||||
$h3-font-size: $font-size-base * 1.75 !default;
|
||||
$h4-font-size: $font-size-base * 1.5 !default;
|
||||
$h5-font-size: $font-size-base * 1.25 !default;
|
||||
$h6-font-size: $font-size-base !default;
|
||||
// scss-docs-end font-variables
|
||||
|
||||
// scss-docs-start font-sizes
|
||||
$font-sizes: (
|
||||
1: $h1-font-size,
|
||||
2: $h2-font-size,
|
||||
3: $h3-font-size,
|
||||
4: $h4-font-size,
|
||||
5: $h5-font-size,
|
||||
5\.5: $font-size-base * 1.125,
|
||||
6: $h6-font-size,
|
||||
7: $font-size-base * 0.875,
|
||||
7\.5: $font-size-base * 0.8125,
|
||||
8: $font-size-base * 0.75,
|
||||
8\.5: $font-size-base * 0.625,
|
||||
9: $font-size-base * 0.5,
|
||||
) !default;
|
||||
// scss-docs-end font-sizes
|
||||
|
||||
$input-bg: #ffffff1a;
|
||||
$input-border-width: 0px;
|
||||
$input-group-addon-bg: $input-bg;
|
||||
|
||||
$form-select-indicator-color: $body-color;
|
||||
|
||||
$accordion-button-bg: $bg-purple;
|
||||
$accordion-button-active-bg: $bg-purple-active;
|
||||
$accordion-button-active-color: $body-color;
|
||||
$accordion-bg: $body-bg;
|
||||
$accordion-border-radius: 5px;
|
||||
|
||||
@import './variables';
|
||||
@import '~bootstrap/scss/bootstrap';
|
||||
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500;700&display=swap');
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;700&display=swap');
|
||||
|
|
@ -164,7 +78,7 @@ html[class~='dark'] body {
|
|||
color: $text-muted;
|
||||
transition: color 0.2s ease;
|
||||
&:hover {
|
||||
color: #e5e5e5;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -237,6 +151,10 @@ body {
|
|||
cursor: grab;
|
||||
}
|
||||
|
||||
.cursor-col-resize {
|
||||
cursor: col-resize;
|
||||
}
|
||||
|
||||
.cursor-zoom-in {
|
||||
cursor: zoom-in !important;
|
||||
}
|
||||
|
|
|
|||
106
packages/app/styles/variables.scss
Normal file
106
packages/app/styles/variables.scss
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
Colors
|
||||
*/
|
||||
|
||||
$text-muted: #dadada;
|
||||
$text-purple: #9357ff; // This isn't a bootstrap variable
|
||||
$text-light: #f8f8f2;
|
||||
$green: #50fa7b;
|
||||
$red: #ff5d5b;
|
||||
$blue: #3788f6;
|
||||
$purple: #8f57f3;
|
||||
|
||||
$gray-100: #f8f9fa;
|
||||
$body-color: $gray-100;
|
||||
|
||||
$bg-hdx-dark: #1a1d23;
|
||||
$bg-dark-grey: #1f2429;
|
||||
$bg-grey: #21272e;
|
||||
$bg-purple: #2e273b;
|
||||
$bg-purple-active: #4a4eb5;
|
||||
$body-bg: #0f1216;
|
||||
$code-color: #4bb74a;
|
||||
|
||||
$info: $purple;
|
||||
|
||||
// TODO: Adjust contrast ratios
|
||||
$slate-50: #f6f7f9;
|
||||
$slate-100: #eceef2;
|
||||
$slate-200: #d5dae2;
|
||||
$slate-300: #b1bbc8;
|
||||
$slate-400: #8695aa;
|
||||
$slate-500: #677890;
|
||||
$slate-600: #526077;
|
||||
$slate-700: #434e61;
|
||||
$slate-800: #3a4352;
|
||||
$slate-900: #343a46;
|
||||
$slate-950: #1a1d23;
|
||||
|
||||
/**
|
||||
Spacing
|
||||
*/
|
||||
$spacer: 1rem;
|
||||
$spacers: (
|
||||
0: 0,
|
||||
0\.5: $spacer * 0.125,
|
||||
1: $spacer * 0.25,
|
||||
2: $spacer * 0.5,
|
||||
2\.5: $spacer * 0.75,
|
||||
3: $spacer,
|
||||
4: $spacer * 1.5,
|
||||
4\.5: $spacer * 2,
|
||||
5: $spacer * 3,
|
||||
6: $spacer * 4,
|
||||
7: $spacer * 5,
|
||||
8: $spacer * 8,
|
||||
10: $spacer * 10,
|
||||
14: $spacer * 14,
|
||||
16: $spacer * 16,
|
||||
);
|
||||
|
||||
$navbar-dark-active-color: $green;
|
||||
$navbar-dark-color: rgba(#fff, 0.75);
|
||||
$navbar-dark-hover-color: rgba(#fff, 1);
|
||||
|
||||
$dropdown-dark-bg: $bg-grey;
|
||||
|
||||
$popover-bg: $bg-purple;
|
||||
|
||||
$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`
|
||||
|
||||
$h1-font-size: $font-size-base * 2.5 !default;
|
||||
$h2-font-size: $font-size-base * 2 !default;
|
||||
$h3-font-size: $font-size-base * 1.75 !default;
|
||||
$h4-font-size: $font-size-base * 1.5 !default;
|
||||
$h5-font-size: $font-size-base * 1.25 !default;
|
||||
$h6-font-size: $font-size-base !default;
|
||||
// scss-docs-end font-variables
|
||||
|
||||
// scss-docs-start font-sizes
|
||||
$font-sizes: (
|
||||
1: $h1-font-size,
|
||||
2: $h2-font-size,
|
||||
3: $h3-font-size,
|
||||
4: $h4-font-size,
|
||||
5: $h5-font-size,
|
||||
5\.5: $font-size-base * 1.125,
|
||||
6: $h6-font-size,
|
||||
7: $font-size-base * 0.875,
|
||||
7\.5: $font-size-base * 0.8125,
|
||||
8: $font-size-base * 0.75,
|
||||
8\.5: $font-size-base * 0.625,
|
||||
9: $font-size-base * 0.5,
|
||||
) !default;
|
||||
// scss-docs-end font-sizes
|
||||
|
||||
$input-bg: #ffffff1a;
|
||||
$input-border-width: 0px;
|
||||
$input-group-addon-bg: $input-bg;
|
||||
|
||||
$form-select-indicator-color: $body-color;
|
||||
|
||||
$accordion-button-bg: $bg-purple;
|
||||
$accordion-button-active-bg: $bg-purple-active;
|
||||
$accordion-button-active-color: $body-color;
|
||||
$accordion-bg: $body-bg;
|
||||
$accordion-border-radius: 5px;
|
||||
Loading…
Reference in a new issue