Merge pull request #12988 from ToolJet/feat/ui-revamp-surface

feat: Changes background color to match new design
This commit is contained in:
Johnson Cherian 2025-07-09 11:26:20 +05:30 committed by GitHub
commit ded4aabfad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
55 changed files with 1340 additions and 1006 deletions

View file

@ -113,6 +113,7 @@ class AppComponent extends React.Component {
const featureAccess = await licenseService.getFeatureAccess();
const isBasicPlan = !featureAccess?.licenseStatus?.isLicenseValid || featureAccess?.licenseStatus?.isExpired;
this.setState({ showBanner: isBasicPlan });
this.updateColorScheme();
}
// check if its getting routed from editor
checkPreviousRoute = (route) => {
@ -122,7 +123,7 @@ class AppComponent extends React.Component {
return false;
};
componentDidUpdate(prevProps) {
componentDidUpdate(prevProps, prevState) {
// Check if the current location is the dashboard (homepage)
if (
this.props.location.pathname === `/${getWorkspaceIdOrSlugFromURL()}` &&
@ -135,18 +136,24 @@ class AppComponent extends React.Component {
}
// Update margin when showBanner changes
this.updateMargin();
// Update color scheme if darkMode changed
if (prevState.darkMode !== this.state.darkMode) {
this.updateColorScheme();
}
}
switchDarkMode = (newMode) => {
this.setState({ darkMode: newMode });
this.props.updateIsTJDarkMode(newMode);
localStorage.setItem('darkMode', newMode);
this.updateColorScheme(newMode);
};
isEditorOrViewerFromPath = () => {
const pathname = this.props.location.pathname;
if (pathname.includes('/apps/')) {
return 'editor';
} else if (pathname.includes('/applications/') || pathname.includes('/embed-apps/')) {
}
if (pathname.includes('/applications/') || pathname.includes('/embed-apps/')) {
return 'viewer';
}
return '';
@ -157,6 +164,14 @@ class AppComponent extends React.Component {
isExistingPlanUser = (date) => {
return new Date(date) < new Date('2025-04-24'); //show banner if user created before 2 april (24 for testing)
};
updateColorScheme = (darkModeValue) => {
const isDark = darkModeValue !== undefined ? darkModeValue : this.state.darkMode;
if (isDark) {
document.documentElement.style.setProperty('color-scheme', 'dark');
} else {
document.documentElement.style.removeProperty('color-scheme');
}
};
render() {
const { updateAvailable, darkMode, isEditorOrViewer, showBanner } = this.state;
const mergedProps = {
@ -290,22 +305,19 @@ class AppComponent extends React.Component {
}
/>
)}
<Route
path="/:workspaceId/workspace-settings/*"
element={<WorkspaceSettings {...mergedProps} />}
></Route>
<Route path="/:workspaceId/workspace-settings/*" element={<WorkspaceSettings {...mergedProps} />} />
<Route
path="settings/*"
element={
<InstanceSettings switchDarkMode={this.switchDarkMode} darkMode={darkMode} {...this.props} />
}
></Route>
/>
<Route
path="/:workspaceId/settings/*"
element={
<InstanceSettings {...this.props} darkMode={darkMode} switchDarkMode={this.switchDarkMode} />
}
></Route>
/>
<Route
exact
path="/:workspaceId/modules"
@ -428,7 +440,7 @@ class AppComponent extends React.Component {
/>
</Routes>
</BreadCrumbContext.Provider>
<div id="modal-div"></div>
<div id="modal-div" />
</div>
<Toast toastOptions={toastOptions} />

View file

@ -202,7 +202,7 @@ export default function AppCard({
placement="bottom"
show={appType === 'module' && props.basicPlan}
>
<div className="card homepage-app-card" ref={cardRef}>
<div className="card homepage-app-card card--clickable" ref={cardRef}>
<div
className={appType === 'module' && props.basicPlan ? 'disabled-module' : ''}
key={app?.id}

View file

@ -26,8 +26,8 @@ const AppList = (props) => {
</>
)}
{!props.isLoading && props.meta.total_count > 0 && (
<div className="container px-0">
<div className="row homepage-app-card-list-item-wrap">
<div className="">
<div className="homepage-app-card-list-item-wrap">
{props.apps.map((app) => {
return (
<div className="homepage-app-card-list-item" key={app.id}>

View file

@ -119,7 +119,7 @@ export const AppMenu = function AppMenu({
</div>
}
>
<div className={'cursor-pointer menu-ico'} data-cy={`app-card-menu-icon`}>
<div className={'cursor-pointer menu-ico menu-icon--trigger'} data-cy={`app-card-menu-icon`}>
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"

View file

@ -14,6 +14,8 @@ import _ from 'lodash';
import { validateName, handleHttpErrorMessages, getWorkspaceId } from '@/_helpers/utils';
import { useNavigate, useLocation } from 'react-router-dom';
import FolderSkeleton from '@/_ui/FolderSkeleton/FolderSkeleton';
import { Button } from '@/components/ui/Button/Button';
export const Folders = function Folders({
folders,
foldersLoading,
@ -246,24 +248,36 @@ export const Folders = function Folders({
<div className="d-flex folder-header-icons-wrap">
{canCreateFolder && (
<>
<div
className="folder-create-btn"
<Button
size="medium"
variant="ghost"
iconOnly
ariaLabel="Create new folder"
onClick={() => {
setNewFolderName('');
setShowForm(true);
}}
data-cy="create-new-folder-button"
>
<SolidIcon name="plus" width="14" fill={darkMode ? '#ECEDEE' : '#11181C'} />
</div>
<div
className="folder-create-btn"
<SolidIcon name="plus" width="14" fill={darkMode ? '#CFD3D8E6' : '#6A727C'} />
</Button>
<Button
size="medium"
variant="ghost"
iconOnly
ariaLabel="Search for folders"
onClick={() => {
setShowInput(true);
}}
data-cy="create-new-folder-button"
>
<SolidIcon name="search" width="14" fill={darkMode ? '#ECEDEE' : '#11181C'} />
</div>
<SolidIcon
name="search"
width="14"
fill={darkMode ? '#CFD3D8E6' : '#6A727C'}
className="tw-relative tw-top-[2px]"
/>
</Button>
</>
)}
</div>
@ -287,8 +301,7 @@ export const Folders = function Folders({
className={cx(
`list-group-item border-0 list-group-item-action d-flex align-items-center all-apps-link tj-text-xsm`,
{
'bg-light-indigo': _.isEmpty(activeFolder) && !darkMode,
'bg-dark-indigo': _.isEmpty(activeFolder) && darkMode,
'tw-bg-interactive-default': _.isEmpty(activeFolder),
}
)}
style={{ height: '32px' }}
@ -314,8 +327,7 @@ export const Folders = function Folders({
className={cx(
`folder-list-group-item rounded-2 list-group-item h-4 mb-1 list-group-item-action no-border d-flex align-items-center`,
{
'bg-light-indigo': activeFolder.id === folder.id && !darkMode,
'bg-dark-indigo': activeFolder.id === folder.id && darkMode,
'tw-bg-interactive-default': activeFolder.id === folder.id,
}
)}
onClick={() => {

View file

@ -1,5 +1,5 @@
import React from 'react';
import { SearchBox } from '@/_components/SearchBox';
import { SearchBox } from '@/_components/PageSearchBox';
import { useTranslation } from 'react-i18next';
export default function HomeHeader({ onSearchSubmit, darkMode, appType }) {
@ -14,17 +14,15 @@ export default function HomeHeader({ onSearchSubmit, darkMode, appType }) {
: t('globals.workflowsSearchItem', 'Search workflows in this workspace');
return (
<div className="row">
<div className="home-search-holder">
<SearchBox
dataCy={`home-page`}
className="border-0 homepage-search"
onSubmit={onSearchSubmit}
darkMode={darkMode}
placeholder={placeholderText}
width={'100%'}
/>
</div>
<div className="home-search-holder">
<SearchBox
dataCy={'home-page'}
className="border-0 homepage-search"
onSubmit={onSearchSubmit}
darkMode={darkMode}
placeholder={placeholderText}
width={'100%'}
/>
</div>
);
}

View file

@ -1652,12 +1652,7 @@ class HomePageComponent extends React.Component {
<OrganizationList customStyle={{ marginBottom: isAdmin || isBuilder ? '' : '0px' }} />
</div>
<div
className={cx('col home-page-content', {
'bg-light-gray': !this.props.darkMode,
})}
data-cy="home-page-content"
>
<div className={cx('col home-page-content')} data-cy="home-page-content">
<div className="w-100 mb-5 container home-page-content-container">
{featuresLoaded && !isLoading ? (
<>
@ -1684,15 +1679,12 @@ class HomePageComponent extends React.Component {
{(meta?.total_count > 0 || appSearchKey) && (
<>
{!(isLoading && !appSearchKey) && (
<>
<HomeHeader
onSearchSubmit={this.onSearchSubmit}
darkMode={this.props.darkMode}
appType={this.props.appType}
disabled={this.props.appType === 'module' && invalidLicense}
/>
<div className="liner"></div>
</>
<HomeHeader
onSearchSubmit={this.onSearchSubmit}
darkMode={this.props.darkMode}
appType={this.props.appType}
disabled={this.props.appType === 'module' && invalidLicense}
/>
)}
<div className="filter-container">
<span>{currentFolder?.count ?? meta?.total_count} APPS</span>

View file

@ -0,0 +1,295 @@
.home-page-sidebar {
height: calc(100vh - 48px) !important; //64 is navbar height
.folder-list-user {
height: calc(100vh - 116px) !important; //64 is navbar height + 52 px footer
}
}
.app-list {
margin: 24px 0;
}
.home-search-holder {
height: 48px;
width: 100%;
margin-top: 32px;
}
.homepage-app-card-list-item-wrap {
column-gap: 24px;
row-gap: 24px;
flex-wrap: wrap;
display: flex;
}
.homepage-app-card-list-item {
max-width: 272px;
flex-basis: 33%;
padding: 0 !important;
}
.homepage-dropdown-style {
min-width: 11rem;
display: block;
align-items: center;
margin: 0;
line-height: 1.4285714;
width: 100%;
padding: 0.5rem 0.75rem !important;
font-weight: 400;
white-space: nowrap;
border: 0;
cursor: pointer;
font-size: 12px;
}
.homepage-dropdown-style:hover {
background: rgba(101, 109, 119, 0.06);
}
.menu-icon--trigger {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
background-color: var(--background-surface-layer-01);
box-shadow: none;
transition: all 0.15s ease-in-out;
will-change: background-color, box-shadow;
&:hover {
background-color: var(--background-surface-layer-02);
box-shadow: var(--elevation-000-box-shadow);
}
}
.home-app-card-header {
margin-bottom: 32px;
}
.homepage-app-card {
height: 160px;
padding: 16px;
.app-icon-main {
background: var(--indigo3) !important;
border-radius: 6px !important;
display: flex;
justify-content: center;
align-items: center;
width: 48px;
height: 48px;
will-change: height, width;
transition: all 0.15s ease-in-out;
}
.appcard-buttons-wrap {
visibility: hidden;
opacity: 0;
height: 0;
}
.home-app-card-header {
.menu-ico {
visibility: hidden !important;
}
}
&:hover {
.home-app-card-header {
margin-bottom: 12px;
.menu-ico {
visibility: visible !important;
}
}
.app-creation-time-container {
margin-bottom: 0px;
}
.app-card-name {
margin-bottom: 0px;
}
.app-creation-time {
// display: none;
}
.appcard-buttons-wrap {
display: flex;
visibility: visible;
opacity: 1;
padding: 0px;
gap: 12px;
width: 240px;
height: 28px;
flex-direction: row;
transition: all 0.15s ease-in-out;
will-change: opacity, visibility;
div {
a {
text-decoration: none;
}
}
}
.app-icon-main {
width: 36px;
height: 36px;
}
}
}
.home-page-content-container {
max-width: 880px;
@media only screen and (max-width: 768px) {
margin-bottom: 0rem !important;
.liner {
width: unset !important;
}
.app-list {
overflow-y: auto;
height: calc(100vh - 26rem);
.skeleton-container {
display: flex;
flex-direction: column;
.col {
display: flex;
justify-content: center;
margin-bottom: 1rem;
}
.card-skeleton-container {
width: 304px;
}
}
}
.menu-ico {
display: none !important;
}
}
}
.home-page-footer {
height: 52px;
background-color: var(--page-weak) !important;
border-top: 1px solid var(--border-weak) !important;
width: calc(100% - 336px) !important;
@media only screen and (max-width: 768px) {
position: unset;
width: 100%;
.col-4,
.col-5 {
display: none;
}
.pagination-container {
display: flex !important;
align-items: center;
justify-content: center;
}
}
}
@media only screen and (min-width: 1728px) {
.homepage-app-card-list-item {
// max-width: 304px;
max-width: calc(33.3% - 16px);
.edit-button,
.launch-button {
width: 129px !important;
}
}
.home-page-content-container {
max-width: 976px;
}
.liner {
width: 976px;
}
}
@media only screen and (min-width: 1584px) and (max-width: 1727px) {
.homepage-app-card-list-item {
max-width: calc(33.3% - 16px);
}
.edit-button,
.launch-button {
width: 113px !important;
}
}
@media only screen and (min-width: 1312px) and (max-width: 1583px) {
.homepage-app-card-list-item {
// max-width: 264px;
max-width: calc(33.3% - 16px);
.edit-button,
.launch-button {
width: 109px !important;
}
}
}
@media only screen and (min-width: 993px) and (max-width: 1311px) {
.home-page-content-container {
max-width: 568px;
}
.homepage-app-card-list-item-wrap {
row-gap: 20px;
}
.homepage-app-card-list-item {
// max-width: 269px;
max-width: calc(50% - 12px);
flex-basis: 50%;
flex-grow: 1;
flex-shrink: 0;
.edit-button,
.launch-button {
width: 111.5px !important;
}
}
.liner {
width: 568px;
}
}
@media only screen and (max-width: 992px) {
.homepage-app-card-list-item-wrap {
display: flex;
justify-content: center;
width: 100%;
gap: 24px;
}
.homepage-app-card-list-item {
// max-width: 304px !important;
max-width: calc(50% - 12px);
flex-basis: 100%;
.edit-button,
.launch-button {
width: 129px !important;
}
}
}

View file

@ -52,7 +52,7 @@ export const MarketplaceCard = ({ id, name, repo, description, version, isInstal
return (
<div className="col-sm-6 col-lg-4">
<div className="plugins-card card-borderless">
<div className="card plugins-card card-borderless">
<div className="card-body card-body-alignment">
<div className="row align-items-center">
<div className="col-auto">

View file

@ -169,7 +169,7 @@ function SettingsPage(props) {
<div className="page-wrapper profile-page-content-wrap">
<div style={{ height: `calc(100vh - 2.5rem - 64px)` }}>
<div className="container-xl">
<div className="profile-page-card">
<div className="card profile-page-card">
<div className="card-header">
<h3 className="card-title" data-cy="card-title-profile">
{t('header.profileSettingPage.profile', 'Profile')}
@ -244,8 +244,7 @@ function SettingsPage(props) {
<div></div>
</div>
</div>
<br />
<div className="profile-page-card">
<div className="card profile-page-card tw-mt-16">
<div className="card-header">
<h3 className="card-title" data-cy="card-title-change-password">
{t('header.profileSettingPage.changePassword', 'Change password')}

View file

@ -368,6 +368,12 @@ function TableSchema({
isDisabled={
isEditMode && columnDetails[index]?.constraints_type?.is_primary_key === true ? true : false
}
classNames={{
control: (state) => cx({
'!tw-border-border-default': true,
}),
}}
/>
</div>
</ToolTip>

View file

@ -548,7 +548,7 @@
}
.empty-foreignkey-container {
border: 1px dashed #d7dbdf;
border: 1px dashed var(--border-default);
height: 40px;
width: 270px !important;
border-radius: 100px !important;

View file

@ -148,8 +148,8 @@ const Header = ({
return (
<>
<div className="database-table-header-wrapper">
<div className="card border-0">
<div className="card-body tj-db-operations-header">
<div className="border-0">
<div className="tj-db-operations-header">
<div className="row align-items-center">
<div className="col-8 align-items-center gap-1" style={{ padding: '0 16px' }}>
<>

View file

@ -97,8 +97,8 @@
z-index: 1;
position: sticky;
left: 66px;
border-right: 2px solid var(--light-slate-08, #C1C8CD);
background-color: white;
border-right: 2px solid var(--border-weak);
background-color: var(--surfaces-surface-01);
}
th {
@ -145,14 +145,14 @@
th:nth-child(2) {
z-index: 2;
left: 66px;
border-right: 2px solid var(--light-slate-08, #C1C8CD);
border-right: 2px solid var(--border-weak);
}
.dark-background {
td:nth-child(1),
td:nth-child(2) {
background-color: #2B394A;
background-color: var(--surfaces-surface-01);
}
}
@ -283,26 +283,6 @@
background-color: #2B2F30 !important;
}
.empty-table-description {
font-size: 14px !important;
line-height: 20px !important;
margin-top: 5px !important;
}
.empty-table-container {
display: flex;
align-items: center;
justify-content: center;
height: calc(100% - 95px);
}
.tjdb-create-new-table {
width: 180px !important;
margin: 0px auto !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
}
.keyPress-actions {

View file

@ -8,6 +8,7 @@ import { ListItem } from '../TableListItem';
import { BreadCrumbContext } from '../../App/App';
import Search from '../Search';
import SolidIcon from '@/_ui/Icon/SolidIcons';
import { Button } from '@/components/ui/Button/Button';
const List = () => {
const {
@ -83,15 +84,23 @@ const List = () => {
<>
<span>All tables ({filteredTables.length})</span>
<div
className="folder-create-btn search-icon-wrap"
<Button
size="medium"
variant="ghost"
iconOnly
ariaLabel="Search for folders"
onClick={() => {
setShowInput(true);
}}
data-cy="create-new-folder-button"
>
<SolidIcon name="search" width="14" fill={darkMode ? '#ECEDEE' : '#11181C'} />
</div>
<SolidIcon
name="search"
width="14"
fill={darkMode ? '#CFD3D8E6' : '#6A727C'}
className="tw-relative tw-top-[2px]"
/>
</Button>
</>
) : (
<Search

View file

@ -7,6 +7,7 @@ import { BreadCrumbContext } from '@/App/App';
import { useNavigate } from 'react-router-dom';
import { pageTitles, fetchAndSetWindowTitle } from '@white-label/whiteLabelling';
import { hasBuilderRole } from '@/_helpers/utils';
import './styles/styles.scss';
export const TooljetDatabaseContext = createContext({
organizationId: null,

View file

@ -0,0 +1,249 @@
.layout-header .tj-dashboard-header-wrap {
display: flex;
align-items: center;
justify-content: space-between;
background-color: var(--page-weak);
padding-top: 8px;
padding-bottom: 8px;
padding-left: 40px;
height: 48px;
border-bottom: 1px solid var(--border-weak);
@media only screen and (max-width: 768px) {
border-bottom: none;
}
}
.tooljet-database {
.search-icon-wrap svg {
position: relative;
top: 1px;
left: 1px;
}
.create-new-table-btn {
width: 248px;
button {
height: 40px !important;
}
}
.tooljet-database-sidebar {
max-width: 288px;
background: var(--page-weak);
border-right: 1px solid var(--border-weak);
height: calc(100vh - 48px) !important;
.sidebar-container {
height: 40px !important;
margin: 12px auto 0;
display: flex;
justify-content: center;
}
.sidebar-container-with-banner {
height: 40px !important;
padding-top: 1px !important;
margin: 0 auto;
display: flex;
justify-content: center;
}
}
// TABLE
.table-left-sidebar {
display: flex;
flex-direction: column;
overflow-y: auto;
}
.toojet-db-table-footer {
height: 52px;
background: var(--page-weak) !important;
width: calc(100vw - 336px);
}
.toojet-db-table-footer-collapse {
height: 52px;
background: var(--page-weak) !important;
width: calc(100vw - 48px);
}
.toojet-db-table-footer-collapse {
height: 52px;
background: var(--page-weak) !important;
width: calc(100vw - 48px);
}
.database-page-content-wrap {
background-color: var(--page-weak);
height: calc(100vh - 64px) !important;
}
.instance-settings-wrapper {
}
.database-page-content-wrap {
height: calc(100vh - 64px) !important;
}
.empty-table-description {
font-size: 14px !important;
line-height: 20px !important;
margin-top: 5px !important;
}
.empty-table-container {
display: flex;
align-items: center;
justify-content: center;
height: calc(100% - 95px);
}
.tjdb-create-new-table {
width: 180px !important;
margin: 0px auto !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
}
.tj-db-operations-header {
height: 56px;
padding: 0 !important;
display: flex;
align-items: center;
background-color: var(--page-weak);
.row {
margin-left: 0px;
width: 98%;
}
.col-8 {
padding-left: 0px;
display: flex;
gap: 12px;
align-items: center;
}
}
.add-new-column-btn {
margin-left: 16px;
height: 28px;
border-radius: 6px;
padding: 0 !important;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
color: var(--slate12);
border: none;
}
.tj-db-filter-btn {
width: 100%;
height: 28px;
display: flex;
border-radius: 6px;
background: transparent;
color: var(--slate12);
border: none;
display: flex;
align-items: center;
justify-content: center;
}
.tj-db-filter-btn-applied,
.tj-db-sort-btn-applied {
display: flex !important;
flex-direction: row !important;
justify-content: center !important;
align-items: center !important;
width: 100% !important;
height: 28px !important;
background: var(--grass2) !important;
border-radius: 6px !important;
}
.tj-db-filter-btn-applied,
.tj-db-filter-clear-icon {
background-color: var(--indigo4) !important;
color: var(--indigo9) !important;
&:hover {
background-color: var(--button-secondary-pressed) !important;
}
}
.tj-db-filter-clear-icon {
border-radius: 0px 6px 6px 0px;
}
.tj-db-filter-btn-active,
.tj-db-sort-btn-active {
display: flex !important;
flex-direction: row !important;
justify-content: center !important;
align-items: center !important;
width: 100% !important;
height: 28px !important;
border-radius: 6px !important;
background: var(--indigo4) !important;
color: var(--indigo9) !important;
}
.tj-db-filter-btn-active {
background: var(--button-outline-pressed) !important;
color: var(--text-default) !important;
}
.tj-db-filter-btn-active-filter {
display: flex !important;
flex-direction: row !important;
justify-content: center !important;
align-items: center !important;
width: 100% !important;
height: 28px !important;
border-radius: 6px !important;
background: var(--button-secondary-pressed) !important;
color: var(--text-brand) !important;
}
.tj-db-header-add-new-row-btn {
height: 28px;
background: transparent;
border-radius: 6px !important;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 6px;
border: none;
padding: span {
}
}
.tj-db-sort-btn {
width: 100%;
height: 28px;
background: transparent;
color: var(--slate12);
border: none;
display: flex;
align-items: center;
justify-content: center;
margin: 0;
}
.edit-row-btn {
background: transparent;
color: var(--slate12);
border: none;
display: flex;
align-items: center;
justify-content: center;
}
}

View file

@ -38,7 +38,7 @@ export const NotificationCenter = ({ darkMode }) => {
const overlay = (
<div
className={`notification-center dropdown-menu dropdown-menu-arrow dropdown-menu-end dropdown-menu-card ${
className={`notification-center dropdown-menu dropdown-menu-arrow dropdown-menu-end !tw-rounded-lg dropdown-menu-card ${
darkMode && 'dark-theme'
}`}
data-bs-popper="static"

View file

@ -0,0 +1,111 @@
import React, { useState, useEffect, forwardRef } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import useDebounce from '@/_hooks/useDebounce';
import { useMounted } from '@/_hooks/use-mount';
import SolidIcon from '@/_ui/Icon/SolidIcons';
import './_styles/page-search-box.scss';
export const SearchBox = forwardRef(
(
{
width = '200px',
onSubmit,
className,
debounceDelay = 300,
darkMode = false,
placeholder = 'Search',
customClass = '',
dataCy = '',
callBack,
onClearCallback,
autoFocus = false,
showClearButton,
initialValue = '',
clearTextOnBlur = true,
},
ref
) => {
const [searchText, setSearchText] = useState('');
const debouncedSearchTerm = useDebounce(searchText, debounceDelay);
const [isFocused, setFocussed] = useState(false);
const handleChange = (e) => {
setSearchText(e.target.value);
callBack?.(e);
};
const clearSearchText = () => {
setSearchText('');
onClearCallback?.();
};
const handleClickOutside = (event) => {
if (ref?.current && !ref.current.contains(event.target) && clearTextOnBlur) {
clearSearchText();
// Your function to be triggered
}
};
const mounted = useMounted();
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside);
if (mounted) {
onSubmit?.(debouncedSearchTerm);
}
return () => {
// Cleanup event listener on component unmount
document.removeEventListener('mousedown', handleClickOutside);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [debouncedSearchTerm, onSubmit]);
useEffect(() => {
initialValue !== undefined && setSearchText(initialValue);
}, [initialValue]);
return (
<div className={`ghost-search-box-wrapper ${customClass}`}>
<div className="input-icon">
{!isFocused && (
<span className="input-icon-addon">
<SolidIcon name="search" width="14" />
</span>
)}
<input
style={{ width }}
type="text"
value={searchText}
onChange={handleChange}
className={cx('form-control ghost-search', {
'dark-theme-placeholder': darkMode,
[className]: !!className,
})}
placeholder={placeholder}
onFocus={() => setFocussed(true)}
onBlur={() => setFocussed(false)}
data-cy={`${dataCy}-search-bar`}
autoFocus={autoFocus}
ref={ref}
/>
{searchText.length >= 0 ? (
<span className="input-icon-addon end" onMouseDown={clearSearchText}>
<div className="d-flex tj-common-search-input-clear-icon" title="clear">
<SolidIcon name="remove" />
</div>
</span>
) : (
''
)}
</div>
</div>
);
}
);
SearchBox.propTypes = {
onSubmit: PropTypes.func.isRequired,
debounceDelay: PropTypes.number,
width: PropTypes.string,
};

View file

@ -4,6 +4,7 @@ import cx from 'classnames';
import useDebounce from '@/_hooks/useDebounce';
import { useMounted } from '@/_hooks/use-mount';
import SolidIcon from '@/_ui/Icon/SolidIcons';
import './_styles/search-box.scss';
export const SearchBox = forwardRef(
(

View file

@ -0,0 +1,85 @@
.ghost-search-box-wrapper {
.form-control.ghost-search {
background: none !important;
color: var(--slate12);
height: 48px;
border: none !important;
border-radius: 0 !important;
border-bottom: 1px solid var(--border-weak) !important;
transition: border-bottom 0.2s ease-in-out;
&:hover {
background: none !important;
border-bottom: 1px solid var(--border-accent-weak) !important;
color: var(--slate12);
}
&:focus {
background: none !important;
border: none !important;
border-bottom: 1px solid var(--border-accent-strong) !important;
}
}
.input-icon {
.input-icon-addon {
padding-right: 6px;
display: flex;
}
}
}
/**
* Search Box
*/
.ghost-search-box-wrapper {
input {
width: 200px;
border-radius: 5px !important;
color: var(--slate12);
background-color: var(--base);
}
.input-icon .form-control:not(:first-child),
.input-icon .form-select:not(:last-child) {
padding-left: 28px !important;
}
input:focus {
width: 200px;
background-color: var(--base);
}
.input-icon .input-icon-addon {
display: flex;
}
.input-icon .input-icon-addon.end {
pointer-events: auto;
.tj-common-search-input-clear-icon {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 4px;
width: 20px;
height: 20px;
background: var(--indigo3) !important;
border-radius: 4px;
}
div {
border-radius: 12px;
color: #ffffff;
padding: 1px;
cursor: pointer;
svg {
height: 14px;
width: 14px;
}
}
}
}

View file

@ -0,0 +1,65 @@
.search-box-wrapper {
input {
width: 200px;
border-radius: 5px !important;
color: var(--text-primary);
background-color: var(--surfaces-surface-01) !important;
border: 1px solid var(--border-weak) !important;
}
.input-icon .form-control:not(:first-child),
.input-icon .form-select:not(:last-child) {
padding-left: 28px !important;
}
input:focus {
width: 200px;
background-color: var(--surfaces-surface-02);
}
.input-icon .input-icon-addon {
display: flex;
}
.input-icon .input-icon-addon.end {
pointer-events: auto;
.tj-common-search-input-clear-icon {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 4px;
width: 20px;
height: 20px;
background: var(--indigo3) !important;
border-radius: 4px;
}
div {
border-radius: 12px;
color: #ffffff;
padding: 1px;
cursor: pointer;
svg {
height: 14px;
width: 14px;
}
}
}
}
.searchbox-wrapper {
margin-top: 0 !important;
.search-icon {
margin: 0.30rem
}
input {
border-radius: 8px !important;
padding-left: 1.75rem !important;
border-radius: 8px !important;
}
}

View file

@ -109,6 +109,17 @@
//upgrade
--upgrade-default: #FFAF41;
--upgrade-weak: #FFAF4140;
// Shadows
--elevation-000-box-shadow: 0px 1px 0px 0px rgba(0, 0, 0, 0.10);
--elevation-200-box-shadow: 0px 2px 4px 0px rgba(48, 50, 51, 0.10), 0px 0px 1px 0px rgba(48, 50, 51, 0.05);
--elevation-300-box-shadow: 0px 4px 8px 0px rgba(48, 50, 51, 0.10), 0px 0px 1px 0px rgba(48, 50, 51, 0.05);
--elevation-400-box-shadow: 0px 8px 16px 0px rgba(48, 50, 51, 0.10), 0px 0px 1px 0px rgba(48, 50, 51, 0.05);
--elevation-500-box-shadow: 0px 16px 24px 0px rgba(48, 50, 51, 0.09), 0px 0px 1px 0px rgba(48, 50, 51, 0.05);
--elevation-600-box-shadow: 0px 24px 40px 0px rgba(48, 50, 51, 0.08), 0px 0px 1px 0px rgba(48, 50, 51, 0.05);
--elevation-700-box-shadow: 0px 32px 50px 0px rgba(48, 50, 51, 0.08), 0px 0px 1px 0px rgba(48, 50, 51, 0.05);
--elevation-100-box-shadow: 0px 1px 1px 0px rgba(48, 50, 51, 0.10), 0px 0px 1px 0px rgba(48, 50, 51, 0.05);
}
.dark-theme {
@ -222,4 +233,15 @@
//upgrade
--upgrade-default: #FFAF41;
--upgrade-weak: #FFAF4140;
//box-shadow
--elevation-000-box-shadow: 0px 1px 0px 0px rgba(0, 0, 0, 0.40);
--elevation-100-box-shadow: 0px 1px 1px 0px #000, 0px 0px 1px 0px rgba(0, 0, 0, 0.90);
--elevation-200-box-shadow: 0px 2px 4px 0px #000, 0px 0px 1px 0px rgba(0, 0, 0, 0.90);
--elevation-300-box-shadow: 0px 4px 8px 0px #000, 0px 0px 1px 0px rgba(0, 0, 0, 0.90);
--elevation-400-box-shadow: 0px 8px 16px 0px #000, 0px 0px 1px 0px rgba(0, 0, 0, 0.90);
--elevation-500-box-shadow: 0px 16px 24px 0px rgba(0, 0, 0, 0.99), 0px 0px 1px 0px rgba(0, 0, 0, 0.90);
--elevation-600-box-shadow: 0px 24px 40px 0px rgba(0, 0, 0, 0.98), 0px 0px 1px 0px rgba(0, 0, 0, 0.90);
--elevation-700-box-shadow: 0px 32px 50px 0px rgba(0, 0, 0, 0.98), 0px 0px 1px 0px rgba(0, 0, 0, 0.90);
}

View file

@ -120,7 +120,7 @@
--interactive-overlays-column-resize: #1B1F244D;
//interactive
--interactive-default: #CCD1D54D;
--interactive-default: #88909914;
--interactive-hover: #ACB2B959;
@ -211,7 +211,7 @@
--interactive-overlays-column-resize: #FFFFFF80;
//interactive
--interactive-default: #A1A7AE1F;
--interactive-default: #858C940D;
--interactive-hover: #A1A7AE29;

View file

@ -3,15 +3,14 @@
}
.drawer {
background: var(--base);
background: var(--surfaces-surface-01);
width: 540px;
height: 100%;
position: fixed;
border: 1px solid var(--slate5);
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
border: 1px solid var(--border-weak);
box-shadow: var(--elevation-400-box-shadow);
transition: transform var(--transition-speed) ease;
z-index: 1000;
background: var(--base);
overflow-y: auto;
&.left {

View file

@ -1,80 +1,94 @@
// for selects and dropdowns across app dashboard
.react-select__control {
background-color: var(--base) !important;
border: 1px solid var(--slate7) !important;
background-color: var(--surfaces-surface-01) !important;
border: 1px solid var(--border-weak) !important;
&:active {
border: 1px solid var(--indigo9);
}
&:active {
border: 1px solid var(--indigo9);
}
}
.react-select__menu-portal {
z-index: 100 !important;
z-index: 100 !important;
.react-select__option {
color: var(--slate12);
z-index: 100;
}
.react-select__option {
color: var(--text-default);
height: 32px;
z-index: 100;
padding: 4px 8px;
}
}
.react-select__single-value {
color: var(--slate12) ;
color: var(--text-default);
}
.react-select__menu {
background-color: var(--base) !important;
border: 1px solid var(--slate3) !important;
box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03) !important;
margin: 0px !important;
z-index: 100;
background-color: var(--surfaces-surface-01) !important;
border: 1px solid var(--border-weak) !important;
box-shadow: var(--elevation-00-box-shadow) !important;
margin: 0px !important;
z-index: 100;
.react-select__menu-list {
background-color: var(--base) !important;
overflow-y: auto;
.react-select__menu-list {
background-color: var(--surfaces-surface-01) !important;
padding: 4px;
overflow-y: auto;
.react-select__option {
background-color: var(--base) !important;
.react-select__option {
background-color: var(--surfaces-surface-01) !important;
border-radius: 6px;
&:hover {
background-color: var(--slate3) !important;
}
> div {
color: var(--text-default) !important;
background-color: transparent !important;
}
&:hover {
background-color: var(--interactive-hover) !important;
> div {
background-color: transparent !important;
}
}
}
}
}
.org-select-container {
height: 52px;
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid var(--slate5);
margin-bottom: var(--dynamic-margin, 0px); //please Remove after Basicplan banner is removed..
height: 52px;
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid var(--border-weak);
margin-bottom: var(
--dynamic-margin,
0px
); //please Remove after Basicplan banner is removed..
}
.tj-org-select {
.react-select__control {
width: 262px;
height: 32px;
border: none !important;
background-color: var(--page-default) !important;
.react-select__control {
width: 262px;
height: 32px;
border: none !important;
background-color: var(--surfaces-surface-01) !important;
&:hover {
background: var(--slate2) !important;
}
&:active {
background: var(--slate3) !important;
}
&:hover {
background: var(--slate2) !important;
}
.tj-text-xsm {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 200px;
&:active {
background: var(--slate3) !important;
}
}
.tj-text-xsm {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 200px;
}
}
.users-filter-dropdown,
@ -85,59 +99,58 @@
.select-order-field,
.select-column-field,
.records-dropdown-field {
.react-select__control {
border: 1px solid var(--slate7) !important;
}
.react-select__control {
border: 1px solid var(--border-default) !important;
}
}
.css-1ms6gku-MenuPortal,
.css-169zxdi-MenuList {
.react-select__option {
border-radius: 6px;
}
.react-select__option {
border-radius: 6px;
}
}
.css-nw08ma-menu {
box-shadow: none !important;
box-shadow: none !important;
}
.react-select__menu-portal {
z-index: 9999 !important;
z-index: 9999 !important;
}
// following is the styles for table select column type menu list and options styles. If its same for all the select elements in the editor, then we can make it common and not specific for table select
.table-select-custom-menu-list{
.react-select__menu-list{
padding: 2px;
// this is needed otherwise :active state doesn't look nice, gap is required
display: flex;
flex-direction: column;
gap: 4px !important;
background-color: var(--base) !important;
overflow-y: auto;
.table-select-custom-menu-list {
.react-select__menu-list {
padding: 2px;
// this is needed otherwise :active state doesn't look nice, gap is required
display: flex;
flex-direction: column;
gap: 4px !important;
background-color: var(--surfaces-surface-01) !important;
overflow-y: auto;
}
.react-select__option {
display: flex;
justify-content: space-between;
padding: 8px 12px;
align-self: stretch;
align-items: center;
color: var(--slate12) !important;
border-radius: 6px;
/* Paragraph/Extrasmall/Regular */
font-family: "IBM Plex Sans";
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 166.667% */
&.react-select__option--is-selected {
color: var(--indigo9) !important;
}
.react-select__option{
display: flex;
justify-content: space-between;
padding: 8px 12px;
align-self: stretch;
align-items: center;
color: var(--slate12) !important;
border-radius: 6px;
/* Paragraph/Extrasmall/Regular */
font-family: 'IBM Plex Sans';
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 166.667% */
&.react-select__option--is-selected{
color: var(--indigo9) !important;
}
&:active{
background: var(--base) !important;
box-shadow: 0px 0px 0px 4px var(--slate6);
color : var(--slate12) !important;
}
&:active {
background: var(--surfaces-surface-01) !important;
box-shadow: 0px 0px 0px 4px var(--slate6);
color: var(--slate12) !important;
}
}
}

View file

@ -20,10 +20,10 @@
}
.select-search-container {
--select-search-background: var(--base);
--select-search-border: var(--slate7);
--select-search-background: var(--surfaces-surface-01);
--select-search-border: var(--border-weak);
--select-search-selected: #dadcde;
--select-search-text: var(--slate12);
--select-search-text: var(--text-default);
--select-search-subtle-text: #6c6f85;
--select-search-inverted-text: var(--select-search-background);
--select-search-highlight: var(--indigo3);

View file

@ -2,12 +2,13 @@
@import "./designtheme.scss";
.global-datasources-sidebar {
height: calc(100vh - 64px);
height: calc(100vh - 48px);
max-width: 288px;
background: var(--page-default);
background: var(--page-weak);
display: grid;
grid-template-rows: auto 1fr auto;
border-right: 1px solid var(--slate5);
border-right: 1px solid var(--border-weak);
gap: 30px;
.add-datasource-btn {
height: 40px;
@ -28,7 +29,7 @@
padding: 6px 15px;
width: 248px;
height: 32px;
margin-bottom: 10px;
margin-bottom: 8px;
&:focus-visible {
box-shadow: 0px 0px 0px 4px #dfe3e6;
@ -69,7 +70,8 @@
}
.datasources-list-item {
background-color: var(--indigo3);
background-color: var(--interactive-default);
color: var(--text-default);
}
}
@ -109,7 +111,7 @@
.datasource-modal-container {
position: relative;
background: var(--page-default);
background: var(--page-weak);
.modal-header {
background-color: var(--slate3) !important;
@ -118,12 +120,12 @@
.modal {
position: absolute;
z-index: 1050;
background: var(--slate2);
background: var(--page-weak);
}
.modal-content {
border: 1px solid var(--slate5);
background-color: var(--base) !important;
border: 1px solid var(--border-weak);
background-color: var(--page-weak) !important;
.input-icon {
&:hover {
@ -165,6 +167,12 @@
display: flex;
justify-content: center;
align-items: center;
svg {
top: 1px;
left: 1px;
position: relative;
}
}
}
@ -184,26 +192,24 @@
.datasource-list-container {
overflow-y: auto;
padding-left: 20px;
max-height: calc(100vh - 64px);
border-left: 1px solid var(--slate5);
max-height: calc(100vh - 48px);
.datasource-list {
width: 976px;
margin: 0 auto;
max-height: calc(100vh - 70px);
padding-bottom: 48px;
.datasource-search-holder {
width: 100%;
margin-top: 22px;
margin-top: 24px;
margin-bottom: 24px;
}
.liner {
margin-top: 5px;
width: 100% !important;
}
input {
background: none !important;
border: none !important;
}
.ghost-search-box-wrapper .form-control.ghost-search {
padding-top: 16px;
padding-bottom: 16px;
height: 64px;
}
}

View file

@ -1,16 +1,14 @@
.instance-logout-wrapper{
background: var(--base);
background: var(--page-weak);
.instance-logout-header{
padding: 24px 24px;
gap: 12px;
height: 72px;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
border-bottom: 1px solid rgb(230, 232, 235); /* Light gray border */
border-bottom: 1px solid var(--border-weak);
padding-bottom: 1rem;
&.dark-mode {
border-bottom: 1px solid rgb(43, 47, 49) !important;
}
.instance-logout-title{
font-size: 18px;
line-height: 28px;

View file

@ -1,7 +1,7 @@
@import "./colors.scss";
@import "./designtheme.scss";
.left-sidebar {
background: var(--page-default) !important;
background: var(--page-weak) !important;
display: flex;
gap: 16px;
@ -785,7 +785,7 @@
align-items: center;
padding-top: 0px;
width: 48px;
border-right: 1px solid var(--slate5);
border-right: 1px solid var(--border-weak);
}
.tj-leftsidebar-icon-wrap {

View file

@ -6,16 +6,17 @@
width: 880px;
margin: auto;
border-radius: 6px;
border: 1px solid var(--border-weak);
.body-wrapper {
border: 1px solid var(--slate5);
height: 100%;
min-height: 620px;
}
.license-page-sidebar {
max-width: 220px;
background-color: var(--base);
border-right: 1px solid var(--slate5) !important;
background-color: var(--surfaces-surface-01);
border-right: 1px solid var(--border-weak) !important;
display: grid !important;
grid-template-rows: auto 1fr auto !important;
@ -29,7 +30,7 @@
}
.license-content-wrapper {
background-color: var(--base);
background-color: var(--surfaces-surface-01);
.groups-sub-header-wrap {
width: 100%;
@ -253,11 +254,10 @@
.license-header-wrap {
display: flex;
justify-content: space-between;
padding-right: 40px;
padding-left: 20px;
padding: 24px 40px 16px;
align-items: center;
height: unset !important;
background-color: var(--base);
background-color: var(--surfaces-surface-01);
.status-container {
border-radius: 20px;
@ -599,9 +599,9 @@
align-items: center;
align-self: stretch;
border-radius: 8px;
background-color: #FFFFFF;
border: 1px solid var(--upgrade-weak, #FFAF4140);
box-shadow: 0px 0px 1px 0px var(--dropshadow-100700-layer-1, rgba(48, 50, 51, 0.05)), 0px 1px 1px 0px var(--dropshadow-100400-layer-2, rgba(48, 50, 51, 0.10));
background-color: var(--surfaces-surface-01);
border: 1px solid var(--border-weak, #FFAF4140);
box-shadow: var(--elevation-000-box-shadow);
.license-loader {
justify-content: center;
@ -796,7 +796,7 @@
}
.license-error-modal {
background-color: var(--base);
background-color: var(--surfaces-surface-01);
.modal-header {
background-color: var(--slate3) !important;
@ -859,7 +859,7 @@
width: 100%;
height: 88px;
border-top: 1px solid var(--slate5) !important;
background: var(--base);
background: var(--surfaces-surface-01);
margin-top: 0px !important;
}

View file

@ -1,6 +1,7 @@
.apps-modules-tabs {
.nav-link {
background-color: var(--page-default);
.apps-modules-tabs.nav-tabs {
.nav-link,
ul > li.nav-link.active {
background-color: var(--page-weak);
}
.nav-link.active {

View file

@ -0,0 +1,13 @@
// Card
.card {
border: 0 !important;
outline: 1px solid var(--border-weak);
box-shadow: var(--elevation-100-box-shadow);
border-radius: 8px;
background-color: var(--background-surface-layer-01) !important;
&.card--clickable:hover {
box-shadow: var(--elevation-200-box-shadow);
}
}

View file

@ -18972,7 +18972,7 @@ img {
@media not print {
.theme-dark {
color: #f4f6fa;
background-color: #1f2936
background-color: #1E2226;
}
.theme-dark .card,

File diff suppressed because it is too large Load diff

View file

@ -11,6 +11,7 @@ const Card = ({
width = 50,
usePluginIcon = false,
className,
cardClassName,
titleClassName,
actionButton,
darkMode,
@ -37,7 +38,7 @@ const Card = ({
return (
<div style={{ height: '112px', width: '164px' }} className={`col-md-2 mb-4 ${className}`}>
<div
className="card"
className={`card ${cardClassName}`}
role="button"
onClick={(e) => {
e.preventDefault();

View file

@ -5,7 +5,7 @@
line-height: 20px;
display: flex;
align-items: center;
color: var(--slate12);
color: var(--text-default);
min-height: 32px;
cursor: pointer;
padding: 6px 8px;
@ -71,5 +71,5 @@
}
.tj-list-item-selected {
background-color: var(--slate5);;
background-color: var(--interactive-default);
}

View file

@ -71,9 +71,9 @@ function Header({
<div className="row w-100 gx-0">
{!collapseSidebar && (
<div className="tj-dashboard-section-header" data-name={pathname}>
<div className="row">
<div className="row tw-w-full">
<div className="col-9 d-flex">
<p className="tj-text-md font-weight-500" data-cy="dashboard-section-header">
<p className="tj-text-md font-weight-500 text-black-000" data-cy="dashboard-section-header">
{pathname}
</p>
{routesWithTags(pathname) && (
@ -117,7 +117,7 @@ function Header({
</div>
)}
<div className="col tj-dashboard-header-wrap">
<div className="d-flex justify-content-sm-between">
<div className="d-flex justify-content-sm-between tw-w-full">
{enableCollapsibleSidebar && collapseSidebar && (
<ToolTip message="Open sidebar" placement="bottom" delay={{ show: 0, hide: 100 }}>
<div className="pe-3">

View file

@ -1,22 +1,22 @@
import React from 'react';
const AppLimitSvg = () => (
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 25 25" fill="none">
const AppLimitSvg = ({ fill }) => (
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 25 25" fill={fill}>
<path
d="M2.5 4.64844C2.5 3.26773 3.61929 2.14844 5 2.14844H7.5C8.88071 2.14844 10 3.26773 10 4.64844V7.14844C10 8.52915 8.88071 9.64844 7.5 9.64844H5C3.61929 9.64844 2.5 8.52915 2.5 7.14844V4.64844Z"
fill="#CCD1D5"
fill={fill}
/>
<path
d="M17.5 2.14844C16.1193 2.14844 15 3.26773 15 4.64844V7.14844C15 8.52915 16.1193 9.64844 17.5 9.64844H20C21.3807 9.64844 22.5 8.52915 22.5 7.14844V4.64844C22.5 3.26773 21.3807 2.14844 20 2.14844H17.5Z"
fill="#CCD1D5"
fill={fill}
/>
<path
d="M18.75 22.1484C20.8211 22.1484 22.5 20.4695 22.5 18.3984C22.5 16.3274 20.8211 14.6484 18.75 14.6484C16.6789 14.6484 15 16.3274 15 18.3984C15 20.4695 16.6789 22.1484 18.75 22.1484Z"
fill="#CCD1D5"
fill={fill}
/>
<path
d="M5 14.6484C3.61929 14.6484 2.5 15.7677 2.5 17.1484V19.6484C2.5 21.0291 3.61929 22.1484 5 22.1484H7.5C8.88071 22.1484 10 21.0291 10 19.6484V17.1484C10 15.7677 8.88071 14.6484 7.5 14.6484H5Z"
fill="#CCD1D5"
fill={fill}
/>
</svg>
);

View file

@ -5,7 +5,7 @@ const Plus = ({ fill = '#C1C8CD', width = '25', className = '', viewBox = '0 0 2
width={width}
height={width}
viewBox={viewBox}
fill="none"
fill={fill}
xmlns="http://www.w3.org/2000/svg"
className={className}
data-cy={dataCy}

View file

@ -5,7 +5,7 @@ const Search = ({ fill = '#C1C8CD', width = '24', className = '', viewBox = '0 0
width={width}
height={width}
viewBox={viewBox}
fill="none"
fill={fill}
xmlns="http://www.w3.org/2000/svg"
className={className}
style={style}

View file

@ -148,7 +148,7 @@ function Layout({
collapseSidebar={collapseSidebar}
toggleCollapsibleSidebar={toggleCollapsibleSidebar}
/>
<div style={{ paddingTop: 64 }}>{children}</div>
<div style={{ paddingTop: 48 }}>{children}</div>
</div>
<ConfirmDialog
title={'Unsaved Changes'}

View file

@ -16,7 +16,7 @@
}
.form-check>.form-check-input:not(:checked) {
background-color: #ffffff;
background-color: var(--slider-track);
}
.text-wrappers{
display: flex;

View file

@ -0,0 +1,35 @@
import * as React from 'react';
import { cn } from '@/lib/utils';
const Card = React.forwardRef(({ className, ...props }, ref) => (
<div ref={ref} className={cn('rounded-lg border bg-card text-card-foreground shadow-sm', className)} {...props} />
));
Card.displayName = 'Card';
const CardHeader = React.forwardRef(({ className, ...props }, ref) => (
<div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
));
CardHeader.displayName = 'CardHeader';
const CardTitle = React.forwardRef(({ className, ...props }, ref) => (
<div ref={ref} className={cn('text-2xl font-semibold leading-none tracking-tight', className)} {...props} />
));
CardTitle.displayName = 'CardTitle';
const CardDescription = React.forwardRef(({ className, ...props }, ref) => (
<div ref={ref} className={cn('text-sm text-muted-foreground', className)} {...props} />
));
CardDescription.displayName = 'CardDescription';
const CardContent = React.forwardRef(({ className, ...props }, ref) => (
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
));
CardContent.displayName = 'CardContent';
const CardFooter = React.forwardRef(({ className, ...props }, ref) => (
<div ref={ref} className={cn('flex items-center p-6 pt-0', className)} {...props} />
));
CardFooter.displayName = 'CardFooter';
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };

View file

@ -28,7 +28,7 @@
}
.load.dark-loader {
display: flex;
background-color: #1f2936;
background-color: #1E2226;
margin: 0;
}

View file

@ -6,6 +6,7 @@ import { Dropdown } from 'react-bootstrap';
import SolidIcon from '@/_ui/Icon/SolidIcons';
import { LicenseTooltip } from '@/LicenseTooltip';
import { DefaultSSOList, DefaultSSOModal } from '@/modules/common/components';
import { Button } from '@/components/ui/Button/Button';
class BaseSSOConfigurationList extends React.Component {
protectedSSO = ['openid', 'ldap', 'saml'];
constructor(props) {
@ -304,7 +305,8 @@ class BaseSSOConfigurationList extends React.Component {
noTooltipIfValid={true}
placement="left"
>
<div
<Button
variant="outline"
className="sso-option"
key={key}
onClick={isFeatureAvailable ? () => this.openModal(key) : (e) => e.preventDefault()}
@ -345,7 +347,7 @@ class BaseSSOConfigurationList extends React.Component {
/>
<span className="slider round"></span>
</label>
</div>
</Button>
</LicenseTooltip>
);
};
@ -381,12 +383,13 @@ class BaseSSOConfigurationList extends React.Component {
bsPrefix="no-caret-dropdown-toggle"
data-cy="dropdown-custom-toggle"
>
<div
<Button
variant="outline"
className="sso-option-label"
style={{
paddingLeft: '12px',
width: '270px',
paddingRight: '220px',
paddingRight: '160px',
paddingTop: '6px',
paddingBottom: '6px',
height: '34px',
@ -395,7 +398,7 @@ class BaseSSOConfigurationList extends React.Component {
>
Instance SSO {defaultSSO ? `(${this.state.inheritedInstanceSSO})` : ''}
<SolidIcon className="option-icon" name={showDropdown ? 'cheveronup' : 'cheverondown'} fill={'grey'} />
</div>
</Button>
</Dropdown.Toggle>
<Dropdown.Menu style={{ width: '100%' }}>

View file

@ -20,8 +20,7 @@
padding-top: 6px;
padding-bottom: 6px;
margin-bottom: 10px;
background-color: #f9f9f9;
border: 1px solid #e1e1e1;
width: 100%;
border-radius: 8px;
transition: background-color 0.1s;
cursor: pointer;
@ -236,12 +235,9 @@ input:checked+.slider:before {
.workspace-settings-page {
width: 880px;
margin: 0 auto;
background: var(--base);
background: var(--page-weak);
.card {
background: var(--base);
border: 1px solid var(--slate7) !important;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05) !important;
width: 880px;
.card-header {
@ -273,8 +269,8 @@ input:checked+.slider:before {
align-items: center;
padding: 24px 32px;
gap: 8px;
border-top: 1px solid var(--slate5) !important;
background: var(--base);
border-top: 1px solid var(--border-weak) !important;
background: var(--surfaces-surface-01);
margin-top: 0px !important;
align-Self: 'stretch';
height: 88px;
@ -303,6 +299,11 @@ input:checked+.slider:before {
.theme-dark {
.form-control {
background-color: unset !important;
input {
color: var(--text-default) !important;
border-color: var(--border-default) !important;
}
}
.react-tel-input .form-control {

View file

@ -42,14 +42,13 @@
}
.constant-wrapper {
background-color: #f8f9fa;
background-color: var(--page-weak);
padding: 0px;
}
.constant-page-wrapper {
background-color: #ffffff;
border: 1px solid #e9ecef;
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
background-color: var(--page-weak);
border: 1px solid var(--border-weak);
overflow: hidden;
width: 920px;
height: 620px;
@ -257,17 +256,11 @@
color: #adb5bd;
}
/* Dark Theme Styles */
.dark-theme .constant-wrapper,
.theme-dark .constant-wrapper {
background-color: var(--slate2);
}
.dark-theme .constant-page-wrapper,
.theme-dark .constant-page-wrapper {
background-color: var(--base);
border: 1px solid #6c757d;
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.3);
background-color: var(--page-weak);
border: 1px solid var(--border-weak);
}
.dark-theme .workspace-constant-header .tj-text-sm,

View file

@ -44,16 +44,18 @@ const ConstantTable = ({
return (
<div>
<div className="card constant-table-card" style={{ border: 'none' }}>
<div className="constant-table-card" style={{ border: 'none' }}>
<div
className="fixedHeader table-responsive px-2"
className="fixedHeader table-responsive"
ref={tableRef}
style={{ maxHeight: tableRef.current && calculateOffset() }}
>
<table className="table table-vcenter mt-2" disabled={true}>
<thead>
<tr>
<th data-cy="workspace-variable-table-name-header">Name</th>
<th className="!tw-pl-4" data-cy="workspace-variable-table-name-header">
Name
</th>
<th data-cy="workspace-variable-table-value-header">Value</th>
{canUpdateDeleteConstant && (
<th className="w-1" style={{ paddingRight: '16px' }}>
@ -99,7 +101,7 @@ const ConstantTable = ({
{constants.map((constant) => {
return (
<tr key={constant.id}>
<td className="p-3-constants">
<td className="p-3-constants !tw-pl-4">
<span
data-cy={`${constant.name.toLowerCase().replace(/\s+/g, '-')}-workspace-constant-name`}
data-tooltip-id="tooltip-for-org-constant-cell"

View file

@ -473,10 +473,8 @@ const BaseManageOrgConstants = ({
featureAceess={featureAccess}
licenseType={featureAccess?.licenseStatus?.licenseType}
/>
<div style={{ marginTop: '850px' }}>
<OrganizationList />
</div>
</div>
<OrganizationList />
</div>
<div className="page-wrapper mt-4">
<div className="container-xl" style={{ width: '880px' }}>

View file

@ -13,7 +13,7 @@ import { WorkspaceDropDown } from '@/modules/dashboard/components';
each workspace related component has organizations list component which can be moved to a single wrapper.
otherwise this component will intiate everytime we switch between pages
*/
const BaseOrganizationList = function ({ workspacesLimit = null, LicenseBadge = () => null, ...props }) {
const BaseOrganizationList = ({ workspacesLimit = null, LicenseBadge = () => null, ...props }) => {
const { current_organization_id, admin } = authenticationService.currentSessionValue;
const { fetchOrganizations, organizationList, isGettingOrganizations } = useCurrentSessionStore(
(state) => ({

View file

@ -68,7 +68,7 @@ const UsersTable = ({
/>
<div style={customStyles} className="tj-user-table-wrapper">
<div className="card-table fixedHeader table-responsive">
<table data-testid="usersTable" className="users-table table table-vcenter h-100">
<table data-testid="usersTable" className="users-table table table-vcenter h-100 mx-0">
<thead>
<tr>
<th data-cy="users-table-name-column-header" data-name="name-header">
@ -106,9 +106,7 @@ const UsersTable = ({
{translator('header.organization.menus.manageUsers.workspaces', 'Workspaces')}
</th>
)}
<th className="w-1"></th>
<th className="w-1"></th>
<th className="w-1"></th>
<th className="w-1 !tw-w-16 !tw-max-w-16 !tw-min-w-16"></th>
</tr>
</thead>
{isLoading ? (
@ -128,7 +126,7 @@ const UsersTable = ({
users.length > 0 &&
users.map((user) => (
<tr key={user.id} data-cy={`${user.name.toLowerCase().replace(/\s+/g, '-')}-user-row`}>
<td>
<td data-name="name-header">
<Avatar
avatarId={user.avatar_id}
text={`${user.first_name ? user.first_name[0] : ''}${
@ -161,7 +159,7 @@ const UsersTable = ({
</td>
)}
{isLoadingAllUsers && (
<td className="text-muted">
<td className="text-muted !tw-w-[230px] tw-max-w-[230px]">
<span
className="text-muted user-type"
data-cy={`${user.name.toLowerCase().replace(/\s+/g, '-')}-user-type`}
@ -176,7 +174,7 @@ const UsersTable = ({
{!isLoadingAllUsers && <GroupChipTD groups={user.groups.map((group) => group.name)} />}
{user.status && (
<td
className="text-muted"
className="text-muted !tw-w-[230px] tw-max-w-[230px]"
data-name={wsSettings ? 'status-header' : ''}
style={{ marginRight: wsSettings ? '6px' : '0px' }}
>
@ -223,7 +221,7 @@ const UsersTable = ({
</td>
)}
{isLoadingAllUsers && (
<td className="text-muted">
<td className="text-muted !tw-w-[230px] tw-max-w-[230px]">
<a
className="px-2 text-muted workspaces"
onClick={
@ -239,7 +237,7 @@ const UsersTable = ({
</a>
</td>
)}
<td className="user-actions-button">
<td className="user-actions-button tw-w-16 tw-max-w-16">
<UsersActionMenu
archivingUser={archivingUser}
user={user}
@ -336,7 +334,9 @@ const GroupChipTD = ({ groups = [], isRole = false }) => {
onClick={(e) => {
orderedArray.length > 2 && toggleAllGroupsList(e);
}}
className={cx('text-muted groups-name-cell', { 'groups-hover': orderedArray.length > 2 })}
className={cx('text-muted groups-name-cell !tw-w-[230px] tw-max-w-[230px]', {
'groups-hover': orderedArray.length > 2,
})}
>
<div className="groups-name-container tj-text-sm font-weight-500">
{orderedArray.length === 0 ? (

View file

@ -995,7 +995,7 @@ class DataSourceManagerComponent extends React.Component {
<input
type="text"
onChange={(e) => this.onNameChanged(e.target.value)}
className="form-control-plaintext form-control-plaintext-sm color-slate12"
className="form-control-plaintext form-control-plaintext-sm color-slate12 tw-border-x tw-border-y"
value={decodeEntities(selectedDataSource.name)}
style={{ width: '160px' }}
data-cy="data-source-name-input-field"

View file

@ -249,7 +249,7 @@ export const GlobalDataSources = ({ darkMode = false, updateSelectedDatasource }
<div className="datasource-search-holder">
<SearchBox
dataCy={`home-page`}
className="border-0 homepage-search"
className="border-0"
darkMode={darkMode}
placeholder={`Search data sources`}
initialValue={queryString}
@ -260,7 +260,6 @@ export const GlobalDataSources = ({ darkMode = false, updateSelectedDatasource }
setSuggestingDataSource(false);
}}
/>
<div className="liner mb-4"></div>
</div>
{suggestingDataSource ? (
<center className="empty-ds-container">
@ -307,7 +306,7 @@ export const GlobalDataSources = ({ darkMode = false, updateSelectedDatasource }
}, 100);
};
return (
<div>
<div className="tw-pt-4">
<SegregatedList
handleOnSelect={handleOnSelect}
activeDatasourceList={activeDatasourceList}
@ -375,6 +374,7 @@ export const GlobalDataSources = ({ darkMode = false, updateSelectedDatasource }
width={'35px'}
actionButton={addDataSourceBtn(item)}
className="datasource-card"
cardClassName="card--clickable"
titleClassName={'datasource-card-title'}
tags={tags}
/>

View file

@ -10,6 +10,7 @@ import { SearchBox } from '@/_components/SearchBox';
import { DATA_SOURCE_TYPE } from '@/_helpers/constants';
import FolderSkeleton from '@/_ui/FolderSkeleton/FolderSkeleton';
import Modal from '@/HomePage/Modal';
import { Button } from '@/components/ui/Button/Button';
export const List = ({ updateSelectedDatasource }) => {
const {
@ -141,15 +142,18 @@ export const List = ({ updateSelectedDatasource }) => {
Data sources added{' '}
{!isLoading && filteredData && filteredData.length > 0 && `(${filteredData.length})`}
</div>
<div
className="datasources-search-btn"
<Button
size="medium"
variant="ghost"
iconOnly
ariaLabel="Search for folders"
onClick={() => {
setShowInput(true);
}}
data-cy="added-ds-search-icon"
data-cy="create-new-folder-button"
>
<SolidIcon name="search" width="14" fill={darkMode ? '#ECEDEE' : '#11181C'} />
</div>
<SolidIcon name="search" width="14" fill={darkMode ? '#CFD3D8E6' : '#6A727C'} />
</Button>
</>
) : (
<SearchBox