mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-01-13 15:52:56 +01:00
initial ux ui improvements and revised dashboard
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
|
||||
.Title {
|
||||
font-family: var(--font-family);
|
||||
color: #aaa;
|
||||
color: var(--theme-color-fg-muted);
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
.Version {
|
||||
font-family: var(--font-family);
|
||||
color: #c4c4c4;
|
||||
color: var(--theme-color-fg-default-shy);
|
||||
font-size: 11px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
}
|
||||
|
||||
.language-javascript {
|
||||
color: #eee;
|
||||
background-color: #444;
|
||||
color: var(--theme-color-fg-highlight);
|
||||
background-color: var(--theme-color-bg-4);
|
||||
display: block;
|
||||
padding: 5px;
|
||||
overflow: scroll;
|
||||
|
||||
@@ -2,20 +2,25 @@
|
||||
|
||||
.Root {
|
||||
border: 0;
|
||||
font-size: 14px;
|
||||
font-weight: var(--font-weight-semibold);
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
font-size: var(--font-size-base);
|
||||
font-weight: var(--font-weight-medium);
|
||||
line-height: var(--line-height-tight);
|
||||
padding: var(--spacing-button-padding-y) var(--spacing-button-padding-x);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--spacing-button-gap);
|
||||
cursor: pointer;
|
||||
min-height: length.$global-input-size;
|
||||
min-width: 70px;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
transition: background-color var(--speed-turbo) var(--easing-base), color var(--speed-turbo) var(--easing-base);
|
||||
border-radius: var(--radius-md);
|
||||
transition: background-color var(--transition-default) var(--transition-ease),
|
||||
color var(--transition-default) var(--transition-ease),
|
||||
border-color var(--transition-default) var(--transition-ease),
|
||||
box-shadow var(--transition-default) var(--transition-ease), transform var(--transition-fast) var(--transition-ease);
|
||||
|
||||
&.is-size-small {
|
||||
min-height: length.$global-input-size-small;
|
||||
@@ -25,13 +30,22 @@
|
||||
&.is-variant-cta {
|
||||
color: var(--theme-color-on-primary);
|
||||
background-color: var(--theme-color-primary);
|
||||
box-shadow: var(--shadow-sm);
|
||||
|
||||
path {
|
||||
fill: var(--theme-color-on-primary);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:hover:not(:disabled) {
|
||||
background-color: var(--theme-color-primary-highlight);
|
||||
box-shadow: var(--shadow-default);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
&:active:not(:disabled) {
|
||||
background-color: var(--theme-color-primary-dim);
|
||||
box-shadow: none;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,14 +119,22 @@
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
background-color: var(--theme-color-bg-3) !important;
|
||||
color: var(--theme-color-fg-muted);
|
||||
transform: none !important;
|
||||
box-shadow: none !important;
|
||||
|
||||
path {
|
||||
fill: var(--theme-color-fg-muted);
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--theme-color-focus-ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
&.has-left-spacing {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
@@ -30,12 +30,16 @@
|
||||
|
||||
.InputArea {
|
||||
height: length.$global-input-size;
|
||||
padding: 4px 5px;
|
||||
padding: var(--spacing-input-padding-y) var(--spacing-input-padding-x);
|
||||
position: relative;
|
||||
display: flex;
|
||||
cursor: text;
|
||||
border: 1px solid var(--theme-color-border-default);
|
||||
border-radius: var(--radius-default);
|
||||
transition: margin-bottom var(--speed-quick) var(--easing-base),
|
||||
background-color var(--speed-quick) var(--easing-base);
|
||||
background-color var(--transition-default) var(--transition-ease),
|
||||
border-color var(--transition-default) var(--transition-ease),
|
||||
box-shadow var(--transition-default) var(--transition-ease);
|
||||
|
||||
.Root.is-variant-default & {
|
||||
background-color: var(--theme-color-bg-3);
|
||||
@@ -44,8 +48,15 @@
|
||||
background-color: var(--theme-color-bg-4);
|
||||
}
|
||||
|
||||
&:hover:not(.is-focused):not(.is-readonly) {
|
||||
border-color: var(--theme-color-border-strong);
|
||||
}
|
||||
|
||||
&.is-focused {
|
||||
background-color: var(--theme-color-bg-1);
|
||||
border-color: var(--theme-color-focus-ring);
|
||||
box-shadow: 0 0 0 2px rgba(210, 31, 60, 0.15);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
|
||||
&.has-backdrop {
|
||||
background-color: var(--theme-color-bg-1-transparent);
|
||||
|
||||
/* Optional: Subtle blur for modern feel */
|
||||
/* Note: May have performance implications on older hardware */
|
||||
/* backdrop-filter: blur(4px); */
|
||||
/* -webkit-backdrop-filter: blur(4px); */
|
||||
}
|
||||
|
||||
&.is-locking-scroll {
|
||||
@@ -23,8 +28,22 @@
|
||||
}
|
||||
|
||||
.VisibleDialog {
|
||||
filter: drop-shadow(0 4px 15px var(--theme-color-bg-1-transparent-2));
|
||||
box-shadow: 0 0 10px -5px var(--theme-color-bg-1-transparent-2);
|
||||
/* Modern elevated shadow */
|
||||
box-shadow: var(--shadow-popup);
|
||||
|
||||
/* Border for definition against backdrop */
|
||||
border: 1px solid var(--theme-color-border-subtle);
|
||||
|
||||
/* Modern rounded corners */
|
||||
border-radius: var(--radius-lg);
|
||||
|
||||
/* Overflow handling */
|
||||
overflow: hidden;
|
||||
|
||||
/* Size constraints */
|
||||
max-height: 90vh;
|
||||
max-width: 90vw;
|
||||
|
||||
position: absolute;
|
||||
width: var(--width);
|
||||
pointer-events: all;
|
||||
@@ -53,10 +72,28 @@
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: var(--background);
|
||||
border-radius: 2px;
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
pointer-events: none; // Allow clicks to pass through to content
|
||||
}
|
||||
|
||||
/* Custom scrollbar styling for dialog content */
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: var(--theme-color-bg-3);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--theme-color-bg-5);
|
||||
border-radius: var(--radius-full);
|
||||
|
||||
&:hover {
|
||||
background: var(--theme-color-fg-muted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.Arrow {
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--theme-color-bg-4);
|
||||
|
||||
/* Modern rounded corners */
|
||||
border-radius: var(--radius-lg);
|
||||
|
||||
/* Border for definition */
|
||||
border: 1px solid var(--theme-color-border-subtle);
|
||||
|
||||
/* Elevated shadow */
|
||||
box-shadow: var(--shadow-popup);
|
||||
|
||||
max-width: 810px;
|
||||
max-height: 90vh;
|
||||
width: 80vw;
|
||||
@@ -22,40 +32,58 @@
|
||||
|
||||
.CloseButtonContainer {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
top: var(--spacing-2);
|
||||
right: var(--spacing-2);
|
||||
}
|
||||
|
||||
.Header {
|
||||
padding: 20px 40px 16px;
|
||||
padding: var(--spacing-5) var(--spacing-10) var(--spacing-4);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
&.has-divider {
|
||||
border-bottom: 1px solid var(--theme-color-bg-3);
|
||||
border-bottom: 1px solid var(--theme-color-border-subtle);
|
||||
}
|
||||
}
|
||||
|
||||
.Footer {
|
||||
padding: 20px 40px 16px;
|
||||
padding: var(--spacing-5) var(--spacing-10) var(--spacing-4);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
&.has-divider {
|
||||
border-top: 1px solid var(--theme-color-bg-3);
|
||||
border-top: 1px solid var(--theme-color-border-subtle);
|
||||
}
|
||||
}
|
||||
|
||||
.TitleWrapper {
|
||||
padding-top: 20px;
|
||||
padding-right: 40px;
|
||||
padding-top: var(--spacing-5);
|
||||
padding-right: var(--spacing-10);
|
||||
}
|
||||
|
||||
.Content {
|
||||
padding: 0 40px 40px;
|
||||
padding-top: 16px;
|
||||
padding: 0 var(--spacing-10) var(--spacing-10);
|
||||
padding-top: var(--spacing-4);
|
||||
overflow-x: hidden;
|
||||
overflow-y: overlay;
|
||||
|
||||
/* Custom scrollbar styling */
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: var(--theme-color-bg-3);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--theme-color-bg-5);
|
||||
border-radius: var(--radius-full);
|
||||
|
||||
&:hover {
|
||||
background: var(--theme-color-fg-muted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* TabBar - Modern, clean horizontal tab navigation
|
||||
*/
|
||||
|
||||
.Root {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
border-bottom: 1px solid var(--theme-color-border-default);
|
||||
}
|
||||
|
||||
.Tab {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 20px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: var(--theme-color-fg-default-shy);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
transition: all 0.2s ease;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
|
||||
// Bottom border indicator
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: transparent;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
&:hover:not(.is-disabled) {
|
||||
color: var(--theme-color-fg-default);
|
||||
background: var(--theme-color-bg-hover);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
box-shadow: inset 0 0 0 2px var(--theme-color-primary);
|
||||
}
|
||||
|
||||
&:focus:not(:focus-visible) {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
color: var(--theme-color-primary);
|
||||
font-weight: 600;
|
||||
|
||||
&::after {
|
||||
background: var(--theme-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
color: var(--theme-color-fg-disabled);
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.Tab-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.Tab-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
// Size variants
|
||||
.is-size-small {
|
||||
.Tab {
|
||||
padding: 8px 16px;
|
||||
font-size: 13px;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.Tab-icon {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.is-size-medium {
|
||||
.Tab {
|
||||
padding: 12px 20px;
|
||||
font-size: 14px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.Tab-icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.is-size-large {
|
||||
.Tab {
|
||||
padding: 16px 24px;
|
||||
font-size: 15px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.Tab-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* TabBar - Storybook Stories
|
||||
*/
|
||||
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { IconName } from '@noodl-core-ui/components/common/Icon';
|
||||
|
||||
import { TabBar, TabBarItem } from './TabBar';
|
||||
|
||||
const meta: Meta<typeof TabBar> = {
|
||||
title: 'Layout/TabBar',
|
||||
component: TabBar,
|
||||
parameters: {
|
||||
layout: 'padded'
|
||||
},
|
||||
tags: ['autodocs']
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof TabBar>;
|
||||
|
||||
// Basic tabs without icons
|
||||
const basicItems: TabBarItem[] = [
|
||||
{ id: 'projects', label: 'Projects' },
|
||||
{ id: 'learn', label: 'Learn' },
|
||||
{ id: 'templates', label: 'Templates' }
|
||||
];
|
||||
|
||||
// Tabs with icons
|
||||
const iconItems: TabBarItem[] = [
|
||||
{ id: 'projects', label: 'Projects', icon: IconName.Folder },
|
||||
{ id: 'learn', label: 'Learn', icon: IconName.Book },
|
||||
{ id: 'templates', label: 'Templates', icon: IconName.Components }
|
||||
];
|
||||
|
||||
// Tabs with disabled state
|
||||
const disabledItems: TabBarItem[] = [
|
||||
{ id: 'projects', label: 'Projects', icon: IconName.Folder },
|
||||
{ id: 'learn', label: 'Learn', icon: IconName.Book },
|
||||
{ id: 'templates', label: 'Templates', icon: IconName.Components, disabled: true },
|
||||
{ id: 'marketplace', label: 'Marketplace', icon: IconName.Package, disabled: true }
|
||||
];
|
||||
|
||||
// Interactive wrapper for stories
|
||||
function TabBarDemo({ items, size }: { items: TabBarItem[]; size?: 'small' | 'medium' | 'large' }) {
|
||||
const [activeId, setActiveId] = useState(items[0].id);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<TabBar items={items} activeItemId={activeId} onChange={setActiveId} size={size} />
|
||||
<div style={{ padding: '20px', color: 'var(--theme-color-fg-default)' }}>
|
||||
<strong>Active Tab:</strong> {activeId}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const Basic: Story = {
|
||||
render: () => <TabBarDemo items={basicItems} />
|
||||
};
|
||||
|
||||
export const WithIcons: Story = {
|
||||
render: () => <TabBarDemo items={iconItems} />
|
||||
};
|
||||
|
||||
export const WithDisabled: Story = {
|
||||
render: () => <TabBarDemo items={disabledItems} />
|
||||
};
|
||||
|
||||
export const SmallSize: Story = {
|
||||
render: () => <TabBarDemo items={iconItems} size="small" />
|
||||
};
|
||||
|
||||
export const MediumSize: Story = {
|
||||
render: () => <TabBarDemo items={iconItems} size="medium" />
|
||||
};
|
||||
|
||||
export const LargeSize: Story = {
|
||||
render: () => <TabBarDemo items={iconItems} size="large" />
|
||||
};
|
||||
|
||||
export const ManyTabs: Story = {
|
||||
render: () => {
|
||||
const manyItems: TabBarItem[] = [
|
||||
{ id: '1', label: 'Projects', icon: IconName.Folder },
|
||||
{ id: '2', label: 'Learn', icon: IconName.Book },
|
||||
{ id: '3', label: 'Templates', icon: IconName.Components },
|
||||
{ id: '4', label: 'Marketplace', icon: IconName.Package },
|
||||
{ id: '5', label: 'Settings', icon: IconName.Settings },
|
||||
{ id: '6', label: 'Help', icon: IconName.Question }
|
||||
];
|
||||
return <TabBarDemo items={manyItems} />;
|
||||
}
|
||||
};
|
||||
|
||||
export const KeyboardNavigation: Story = {
|
||||
render: () => (
|
||||
<div>
|
||||
<TabBarDemo items={iconItems} />
|
||||
<div style={{ padding: '20px', color: 'var(--theme-color-fg-default-shy)', fontSize: '13px' }}>
|
||||
<p>
|
||||
<strong>Keyboard shortcuts:</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li>Arrow Left/Right: Navigate between tabs</li>
|
||||
<li>Home: Go to first tab</li>
|
||||
<li>End: Go to last tab</li>
|
||||
<li>Tab: Focus next element</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
124
packages/noodl-core-ui/src/components/layout/TabBar/TabBar.tsx
Normal file
124
packages/noodl-core-ui/src/components/layout/TabBar/TabBar.tsx
Normal file
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* TabBar - Modern horizontal tab navigation component
|
||||
*
|
||||
* A clean, accessible tab bar for switching between views.
|
||||
* Supports keyboard navigation, icons, and state persistence.
|
||||
*
|
||||
* @module noodl-core-ui/components/layout
|
||||
*/
|
||||
|
||||
import classNames from 'classnames';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
|
||||
import { Icon, IconName } from '@noodl-core-ui/components/common/Icon';
|
||||
import { UnsafeStyleProps } from '@noodl-core-ui/types/global';
|
||||
|
||||
import css from './TabBar.module.scss';
|
||||
|
||||
export interface TabBarItem {
|
||||
id: string;
|
||||
label: string;
|
||||
icon?: IconName;
|
||||
disabled?: boolean;
|
||||
testId?: string;
|
||||
}
|
||||
|
||||
export interface TabBarProps extends UnsafeStyleProps {
|
||||
items: TabBarItem[];
|
||||
activeItemId: string;
|
||||
onChange: (itemId: string) => void;
|
||||
/**
|
||||
* Size variant for the tab bar
|
||||
*/
|
||||
size?: 'small' | 'medium' | 'large';
|
||||
}
|
||||
|
||||
export function TabBar({
|
||||
items,
|
||||
activeItemId,
|
||||
onChange,
|
||||
size = 'medium',
|
||||
UNSAFE_className,
|
||||
UNSAFE_style
|
||||
}: TabBarProps) {
|
||||
const tabRefs = useRef<{ [key: string]: HTMLButtonElement | null }>({});
|
||||
|
||||
/**
|
||||
* Handle keyboard navigation
|
||||
*/
|
||||
const handleKeyDown = (event: React.KeyboardEvent, currentIndex: number) => {
|
||||
const enabledItems = items.filter((item) => !item.disabled);
|
||||
const currentEnabledIndex = enabledItems.findIndex((item) => item.id === items[currentIndex].id);
|
||||
|
||||
let newIndex = currentEnabledIndex;
|
||||
|
||||
switch (event.key) {
|
||||
case 'ArrowLeft':
|
||||
event.preventDefault();
|
||||
newIndex = currentEnabledIndex > 0 ? currentEnabledIndex - 1 : enabledItems.length - 1;
|
||||
break;
|
||||
case 'ArrowRight':
|
||||
event.preventDefault();
|
||||
newIndex = currentEnabledIndex < enabledItems.length - 1 ? currentEnabledIndex + 1 : 0;
|
||||
break;
|
||||
case 'Home':
|
||||
event.preventDefault();
|
||||
newIndex = 0;
|
||||
break;
|
||||
case 'End':
|
||||
event.preventDefault();
|
||||
newIndex = enabledItems.length - 1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
const newItem = enabledItems[newIndex];
|
||||
if (newItem) {
|
||||
onChange(newItem.id);
|
||||
tabRefs.current[newItem.id]?.focus();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(css['Root'], css[`is-size-${size}`], UNSAFE_className)}
|
||||
style={UNSAFE_style}
|
||||
role="tablist"
|
||||
aria-label="Main navigation"
|
||||
>
|
||||
{items.map((item, index) => {
|
||||
const isActive = item.id === activeItemId;
|
||||
const isDisabled = item.disabled;
|
||||
|
||||
return (
|
||||
<button
|
||||
key={item.id}
|
||||
ref={(el) => {
|
||||
tabRefs.current[item.id] = el;
|
||||
}}
|
||||
className={classNames(css['Tab'], {
|
||||
[css['is-active']]: isActive,
|
||||
[css['is-disabled']]: isDisabled
|
||||
})}
|
||||
onClick={() => !isDisabled && onChange(item.id)}
|
||||
onKeyDown={(e) => handleKeyDown(e, index)}
|
||||
disabled={isDisabled}
|
||||
role="tab"
|
||||
aria-selected={isActive}
|
||||
aria-disabled={isDisabled}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
data-test={item.testId}
|
||||
>
|
||||
{item.icon && (
|
||||
<span className={css['Tab-icon']}>
|
||||
<Icon icon={item.icon} />
|
||||
</span>
|
||||
)}
|
||||
<span className={css['Tab-label']}>{item.label}</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export { TabBar } from './TabBar';
|
||||
export type { TabBarItem, TabBarProps } from './TabBar';
|
||||
@@ -1,37 +1,37 @@
|
||||
.Root {
|
||||
background-color: var(--theme-color-bg-4);
|
||||
|
||||
&.has-bottom-border {
|
||||
border-bottom: 1px solid var(--theme-color-bg-4);
|
||||
}
|
||||
}
|
||||
|
||||
.Header {
|
||||
padding: 8px 10px;
|
||||
background-color: var(--theme-color-bg-3);
|
||||
}
|
||||
|
||||
.Content {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&.has-y-padding {
|
||||
padding-top: 65px;
|
||||
padding-bottom: 65px;
|
||||
}
|
||||
|
||||
&.is-centering-children {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.Title {
|
||||
color: #ccc;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: var(--font-family);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
.Root {
|
||||
background-color: var(--theme-color-bg-4);
|
||||
|
||||
&.has-bottom-border {
|
||||
border-bottom: 1px solid var(--theme-color-bg-4);
|
||||
}
|
||||
}
|
||||
|
||||
.Header {
|
||||
padding: 8px 10px;
|
||||
background-color: var(--theme-color-bg-3);
|
||||
}
|
||||
|
||||
.Content {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&.has-y-padding {
|
||||
padding-top: 65px;
|
||||
padding-bottom: 65px;
|
||||
}
|
||||
|
||||
&.is-centering-children {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.Title {
|
||||
color: var(--theme-color-fg-default-shy);
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: var(--font-family);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,26 @@
|
||||
.Root {
|
||||
/* Typography */
|
||||
font-family: var(--font-family);
|
||||
padding: 14px;
|
||||
max-width: 160px;
|
||||
font-size: var(--font-size-sm);
|
||||
line-height: var(--line-height-normal);
|
||||
|
||||
/* Background and styling */
|
||||
background-color: var(--theme-color-bg-4);
|
||||
color: var(--theme-color-fg-default);
|
||||
|
||||
/* Spacing */
|
||||
padding: var(--spacing-3-5);
|
||||
border-radius: var(--radius-default);
|
||||
|
||||
/* Elevated appearance */
|
||||
box-shadow: var(--shadow-md);
|
||||
border: 1px solid var(--theme-color-border-default);
|
||||
|
||||
/* Ensure tooltip is above everything */
|
||||
z-index: var(--z-tooltip);
|
||||
|
||||
/* Size constraint */
|
||||
max-width: 250px;
|
||||
|
||||
span {
|
||||
text-align: center;
|
||||
@@ -10,9 +29,11 @@
|
||||
}
|
||||
|
||||
.FineType {
|
||||
padding: 0 8px 8px;
|
||||
margin-top: -6px;
|
||||
padding: 0 var(--spacing-2) var(--spacing-2);
|
||||
margin-top: calc(-1 * var(--spacing-1-5));
|
||||
text-align: center;
|
||||
font-size: var(--font-size-xs);
|
||||
color: var(--theme-color-fg-default-shy);
|
||||
}
|
||||
|
||||
.Trigger {
|
||||
|
||||
@@ -2,6 +2,19 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
/* Background */
|
||||
background-color: var(--theme-color-bg-2);
|
||||
|
||||
/* Subtle border for definition */
|
||||
border: 1px solid var(--theme-color-border-subtle);
|
||||
border-radius: var(--radius-md);
|
||||
|
||||
/* Consistent padding */
|
||||
padding: var(--spacing-panel-padding);
|
||||
|
||||
/* Panel gap between children */
|
||||
gap: var(--spacing-panel-gap);
|
||||
}
|
||||
|
||||
.Inner {
|
||||
@@ -21,6 +34,24 @@
|
||||
&.has-content-scroll {
|
||||
overflow-y: overlay;
|
||||
z-index: 0;
|
||||
|
||||
/* Custom scrollbar styling */
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: var(--theme-color-bg-3);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--theme-color-bg-5);
|
||||
border-radius: var(--radius-full);
|
||||
|
||||
&:hover {
|
||||
background: var(--theme-color-fg-muted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-fill {
|
||||
@@ -36,12 +67,12 @@
|
||||
z-index: -1;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
top: var(--spacing-1);
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 10px 15px var(--theme-color-bg-2);
|
||||
box-shadow: var(--shadow-sm) var(--theme-color-bg-2);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
/* consistency */
|
||||
flex: 0 0 36px;
|
||||
min-height: 36px;
|
||||
padding: 0 10px 0 16px;
|
||||
padding: 0 var(--spacing-2-5) 0 var(--spacing-4);
|
||||
|
||||
user-select: none;
|
||||
|
||||
@@ -63,13 +63,17 @@
|
||||
&.is-collapsable {
|
||||
padding-right: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--theme-color-bg-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.Body {
|
||||
/* allow scrolling */
|
||||
overflow: hidden overlay;
|
||||
padding-top: 8px;
|
||||
padding-top: var(--spacing-2);
|
||||
|
||||
&.is-variant-in-modal {
|
||||
padding: 0;
|
||||
@@ -80,10 +84,28 @@
|
||||
}
|
||||
|
||||
&.has-bottom-spacing {
|
||||
padding-bottom: 12px;
|
||||
padding-bottom: var(--spacing-3);
|
||||
}
|
||||
|
||||
&.has-gutter {
|
||||
padding: 15px;
|
||||
padding: var(--spacing-section-padding);
|
||||
}
|
||||
|
||||
/* Custom scrollbar styling */
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: var(--theme-color-bg-3);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--theme-color-bg-5);
|
||||
border-radius: var(--radius-full);
|
||||
|
||||
&:hover {
|
||||
background: var(--theme-color-fg-muted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
|
||||
|
||||
&.actionable {
|
||||
color: #9F9F9F !important;
|
||||
color: var(--theme-color-fg-default) !important;
|
||||
cursor: pointer;
|
||||
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
@@ -21,12 +21,12 @@
|
||||
|
||||
.Text {
|
||||
/* Color is slightly different in the popout */
|
||||
color: #7a7a7a;
|
||||
color: var(--theme-color-fg-muted);
|
||||
|
||||
/* TODO: Bug there Text doesnt have a font family */
|
||||
font-family: 'OpenSans';
|
||||
|
||||
&.actionable {
|
||||
color: #9F9F9F !important;
|
||||
color: var(--theme-color-fg-default) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
height: 100%;
|
||||
cursor: nwse-resize;
|
||||
|
||||
fill: #7a7a7a;
|
||||
fill: var(--theme-color-fg-muted);
|
||||
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
Reference in New Issue
Block a user