mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 08:02:26 +00:00
fix: improve app css consistency
This commit is contained in:
@@ -229,7 +229,8 @@
|
||||
css?.button?.class ?? '',
|
||||
isMenuItem ? 'flex items-center justify-start' : '',
|
||||
isMenuItem ? '!border-0' : '',
|
||||
'wm-button'
|
||||
'wm-button',
|
||||
`wm-button-${resolvedConfig.color}`
|
||||
)}
|
||||
variant={isMenuItem ? 'border' : 'contained'}
|
||||
style={css?.button?.style}
|
||||
@@ -237,7 +238,8 @@
|
||||
css?.container?.class ?? '',
|
||||
resolvedConfig.fillContainer ? 'w-full h-full' : '',
|
||||
isMenuItem ? 'w-full' : '',
|
||||
'wm-button-container'
|
||||
'wm-button-container',
|
||||
`wm-button-container-${resolvedConfig.color}`
|
||||
)}
|
||||
wrapperStyle={css?.container?.style}
|
||||
disabled={resolvedConfig.disabled}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import InitializeComponent from '../helpers/InitializeComponent.svelte'
|
||||
import { Alert } from '$lib/components/common'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
import { appendClass } from '../../editor/componentsPanel/cssUtils'
|
||||
|
||||
export let id: string
|
||||
export let configuration: RichConfigurations
|
||||
@@ -63,13 +64,13 @@
|
||||
tooltip={resolvedConfig.tooltip}
|
||||
size={resolvedConfig.size}
|
||||
collapsible={resolvedConfig.collapsible}
|
||||
bgClass={css?.background?.class}
|
||||
bgClass={appendClass(css?.background?.class, 'wm-alert-card-background')}
|
||||
bgStyle={css?.background?.style}
|
||||
iconClass={css?.icon?.class}
|
||||
iconClass={appendClass(css?.icon?.class, 'wm-alert-card-icon')}
|
||||
iconStyle={css?.icon?.style}
|
||||
titleClass={css?.title?.class}
|
||||
titleClass={appendClass(css?.title?.class, 'wm-alert-card-title')}
|
||||
titleStyle={css?.title?.style}
|
||||
descriptionClass={css?.description?.class}
|
||||
descriptionClass={appendClass(css?.description?.class, 'wm-alert-card-description')}
|
||||
descriptionStyle={css?.description?.style}
|
||||
isCollapsed={resolvedConfig.initiallyCollapsed}
|
||||
>
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
>
|
||||
<div
|
||||
style={css?.popup?.style}
|
||||
class={twMerge('mx-24 mt-8 bg-surface rounded-lg relative', css?.popup?.class)}
|
||||
class={twMerge('mx-24 mt-8 bg-surface wm-modal rounded-lg relative', css?.popup?.class)}
|
||||
use:clickOutside={{
|
||||
capture: false,
|
||||
stopPropagation: false,
|
||||
@@ -209,7 +209,7 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
class={twMerge('wm-modal h-full', 'overflow-y-auto')}
|
||||
class={twMerge('wm-modal-container h-full', 'overflow-y-auto', css?.container?.class)}
|
||||
on:pointerdown={(e) => {
|
||||
e?.stopPropagation()
|
||||
if (!$connectingInput.opened) {
|
||||
|
||||
@@ -3410,7 +3410,8 @@ See date-fns format for more information. By default, it is 'dd.MM.yyyy HH:mm'
|
||||
customCss: {
|
||||
button: { class: '', style: '' },
|
||||
buttonContainer: { class: '', style: '' },
|
||||
popup: { class: '', style: '' }
|
||||
popup: { class: '', style: '' },
|
||||
container: { class: '', style: '' }
|
||||
},
|
||||
initialData: {
|
||||
horizontalAlignment: 'center',
|
||||
|
||||
@@ -20,20 +20,38 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
interface CustomCSSEntry {
|
||||
type: CustomCSSType
|
||||
type?: CustomCSSType
|
||||
name: string
|
||||
icon: any
|
||||
ids: { id: string; forceStyle: boolean; forceClass: boolean }[]
|
||||
ids?: { id: string; forceStyle: boolean; forceClass: boolean }[]
|
||||
description?: string
|
||||
order?: number
|
||||
}
|
||||
|
||||
const { app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const descriptions = {
|
||||
buttoncomponent:
|
||||
'The button component also has additional color specific classes to allow customizing classes by color. wm-button-wrapper-blue, wm-button-container-blue, ...'
|
||||
}
|
||||
const entries: CustomCSSEntry[] = [
|
||||
{
|
||||
name: 'Dark Mode',
|
||||
icon: LayoutDashboardIcon,
|
||||
description:
|
||||
'When in dark mode, the entire document has the .dark class applied to it. You can apply selective styling by using the .dark class: e.g. .dark .my-element { color: white; }',
|
||||
order: 3
|
||||
},
|
||||
{
|
||||
type: 'app',
|
||||
name: 'App',
|
||||
icon: LayoutDashboardIcon,
|
||||
ids: ['viewer', 'grid', 'component'].map((id) => ({ id, forceStyle: true, forceClass: true }))
|
||||
ids: ['viewer', 'grid', 'component'].map((id) => ({
|
||||
id,
|
||||
forceStyle: true,
|
||||
forceClass: true
|
||||
})),
|
||||
order: 2
|
||||
},
|
||||
{
|
||||
type: 'quillcomponent',
|
||||
@@ -51,11 +69,12 @@
|
||||
id,
|
||||
forceStyle: v?.style != undefined,
|
||||
forceClass: v?.['class'] != undefined
|
||||
}))
|
||||
})),
|
||||
description: descriptions[type as keyof typeof descriptions]
|
||||
}))
|
||||
]
|
||||
|
||||
entries.sort((a, b) => a.name.localeCompare(b.name))
|
||||
entries.sort((a, b) => (b.order ?? 0) - (a.order ?? 0) + a.name.localeCompare(b.name))
|
||||
|
||||
let search = ''
|
||||
</script>
|
||||
@@ -66,15 +85,15 @@
|
||||
<div class="h-[calc(100%-50px)] overflow-auto relative">
|
||||
{#each search != '' ? entries.filter((x) => x.name
|
||||
.toLowerCase()
|
||||
.includes(search.toLowerCase())) : entries as { type, name, icon, ids } (name + type)}
|
||||
{#if ids.length > 0}
|
||||
.includes(search.toLowerCase())) : entries as { type, name, icon, ids, description } (name + type)}
|
||||
{#if description || (ids && ids.length > 0)}
|
||||
<ListItem
|
||||
title={name}
|
||||
prefix={TITLE_PREFIX}
|
||||
on:open={(e) => {
|
||||
if ($app.css != undefined) {
|
||||
if (e.detail && $app.css[type] == undefined) {
|
||||
$app.css[type] = Object.fromEntries(ids.map(({ id }) => [id, {}]))
|
||||
if (type && e.detail && $app.css[type] == undefined) {
|
||||
$app.css[type] = Object.fromEntries((ids ?? []).map(({ id }) => [id, {}]))
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -85,115 +104,120 @@
|
||||
{name}
|
||||
</span>
|
||||
</div>
|
||||
<div class="py-2">
|
||||
{#each customisationByComponent.filter( (c) => c.components.includes(type) ) as customisation (customisation.components.join('-'))}
|
||||
{#if customisation.link}
|
||||
<a
|
||||
href={customisation.link}
|
||||
target="_blank"
|
||||
class="text-frost-500 dark:text-frost-300 font-semibold text-xs"
|
||||
>
|
||||
<div class="flex flex-row gap-2">
|
||||
See documentation
|
||||
<ExternalLink size="16" />
|
||||
</div>
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
<Tabs selected="selectors">
|
||||
{#if customisation.selectors.length > 0}
|
||||
<Tab value="selectors" size="xs">
|
||||
Selectors ({customisation.selectors.length})
|
||||
</Tab>
|
||||
{/if}
|
||||
{#if customisation.variables.length > 0}
|
||||
<Tab value="variables" size="xs">
|
||||
<div class="flex flex-row gap-2 justify-center-center items-center">
|
||||
Variables ({customisation.variables.length})
|
||||
{#if description}
|
||||
<div class="py-2 text-xs text-gray-500">{description}</div>
|
||||
{/if}
|
||||
{#if type}
|
||||
<div class="py-2">
|
||||
{#each customisationByComponent.filter( (c) => c.components.includes(type) ) as customisation (customisation.components.join('-'))}
|
||||
{#if customisation.link}
|
||||
<a
|
||||
href={customisation.link}
|
||||
target="_blank"
|
||||
class="text-frost-500 dark:text-frost-300 font-semibold text-xs"
|
||||
>
|
||||
<div class="flex flex-row gap-2">
|
||||
See documentation
|
||||
<ExternalLink size="16" />
|
||||
</div>
|
||||
</Tab>
|
||||
</a>
|
||||
{/if}
|
||||
<div slot="content" class="h-full">
|
||||
<TabContent value="selectors" class="h-full mt-2 ">
|
||||
<DataTable size="sm">
|
||||
<Head>
|
||||
<tr>
|
||||
<Cell head first>Selector</Cell>
|
||||
<Cell head>Comment</Cell>
|
||||
<Cell head last />
|
||||
</tr>
|
||||
</Head>
|
||||
{#each customisation.selectors as { selector, comment }}
|
||||
<Row>
|
||||
<Cell first>
|
||||
<Badge color="gray">{selector}</Badge>
|
||||
</Cell>
|
||||
<Cell>
|
||||
{#if comment}
|
||||
<div class="max-w-24 whitespace-pre-wrap">{comment}</div>
|
||||
{/if}
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Button
|
||||
size="xs2"
|
||||
color="light"
|
||||
on:click={() => {
|
||||
dispatch('insertSelector', `${selector} {}`)
|
||||
}}
|
||||
>
|
||||
<ArrowUpSquare size={16} />
|
||||
</Button>
|
||||
</Cell>
|
||||
</Row>
|
||||
{/each}
|
||||
</DataTable>
|
||||
</TabContent>
|
||||
<TabContent value="variables" class="h-full mt-2">
|
||||
<DataTable>
|
||||
<Head>
|
||||
<tr>
|
||||
<Cell head first>Variable</Cell>
|
||||
<Cell head>Default value</Cell>
|
||||
<Cell head>Comment</Cell>
|
||||
<Cell head last />
|
||||
</tr>
|
||||
</Head>
|
||||
{#each customisation.variables as { variable, value, comment }}
|
||||
<Row>
|
||||
<Cell first>
|
||||
<Badge color="gray">{variable}</Badge>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Badge color="gray">{value}</Badge>
|
||||
</Cell>
|
||||
<Cell>
|
||||
{#if comment}
|
||||
<div class="w-80 whitespace-pre-wrap">{comment}</div>
|
||||
{/if}
|
||||
</Cell>
|
||||
<Cell sticky>
|
||||
<Button
|
||||
size="xs2"
|
||||
color="light"
|
||||
on:click={() => {
|
||||
dispatch(
|
||||
'insertSelector',
|
||||
`${customisation.root} { ${variable}: ${value};}`
|
||||
)
|
||||
}}
|
||||
wrapperClasses="px-2 py-3.5 bg-surface"
|
||||
>
|
||||
<ArrowUpSquare size={16} />
|
||||
</Button>
|
||||
</Cell>
|
||||
</Row>
|
||||
{/each}
|
||||
</DataTable>
|
||||
</TabContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<Tabs selected="selectors">
|
||||
{#if customisation.selectors.length > 0}
|
||||
<Tab value="selectors" size="xs">
|
||||
Selectors ({customisation.selectors.length})
|
||||
</Tab>
|
||||
{/if}
|
||||
{#if customisation.variables.length > 0}
|
||||
<Tab value="variables" size="xs">
|
||||
<div class="flex flex-row gap-2 justify-center-center items-center">
|
||||
Variables ({customisation.variables.length})
|
||||
</div>
|
||||
</Tab>
|
||||
{/if}
|
||||
<div slot="content" class="h-full">
|
||||
<TabContent value="selectors" class="h-full mt-2 ">
|
||||
<DataTable size="sm">
|
||||
<Head>
|
||||
<tr>
|
||||
<Cell head first>Selector</Cell>
|
||||
<Cell head>Comment</Cell>
|
||||
<Cell head last />
|
||||
</tr>
|
||||
</Head>
|
||||
{#each customisation.selectors as { selector, comment }}
|
||||
<Row>
|
||||
<Cell first>
|
||||
<Badge color="gray">{selector}</Badge>
|
||||
</Cell>
|
||||
<Cell>
|
||||
{#if comment}
|
||||
<div class="max-w-24 whitespace-pre-wrap">{comment}</div>
|
||||
{/if}
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Button
|
||||
size="xs2"
|
||||
color="light"
|
||||
on:click={() => {
|
||||
dispatch('insertSelector', `${selector} {}`)
|
||||
}}
|
||||
>
|
||||
<ArrowUpSquare size={16} />
|
||||
</Button>
|
||||
</Cell>
|
||||
</Row>
|
||||
{/each}
|
||||
</DataTable>
|
||||
</TabContent>
|
||||
<TabContent value="variables" class="h-full mt-2">
|
||||
<DataTable>
|
||||
<Head>
|
||||
<tr>
|
||||
<Cell head first>Variable</Cell>
|
||||
<Cell head>Default value</Cell>
|
||||
<Cell head>Comment</Cell>
|
||||
<Cell head last />
|
||||
</tr>
|
||||
</Head>
|
||||
{#each customisation.variables as { variable, value, comment }}
|
||||
<Row>
|
||||
<Cell first>
|
||||
<Badge color="gray">{variable}</Badge>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Badge color="gray">{value}</Badge>
|
||||
</Cell>
|
||||
<Cell>
|
||||
{#if comment}
|
||||
<div class="w-80 whitespace-pre-wrap">{comment}</div>
|
||||
{/if}
|
||||
</Cell>
|
||||
<Cell sticky>
|
||||
<Button
|
||||
size="xs2"
|
||||
color="light"
|
||||
on:click={() => {
|
||||
dispatch(
|
||||
'insertSelector',
|
||||
`${customisation.root} { ${variable}: ${value};}`
|
||||
)
|
||||
}}
|
||||
wrapperClasses="px-2 py-3.5 bg-surface"
|
||||
>
|
||||
<ArrowUpSquare size={16} />
|
||||
</Button>
|
||||
</Cell>
|
||||
</Row>
|
||||
{/each}
|
||||
</DataTable>
|
||||
</TabContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</ListItem>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
@@ -185,7 +185,11 @@ export const customisationByComponent: Customisation[] = [
|
||||
components: ['modalcomponent'],
|
||||
selectors: [
|
||||
{ selector: '.wm-modal', comment: 'main modal element', customCssKey: 'popup' },
|
||||
{ selector: '.wm-modal-button', comment: 'button to open modal', customCssKey: 'button' },
|
||||
{
|
||||
selector: '.wm-modal-container',
|
||||
comment: 'container for modal',
|
||||
customCssKey: 'container'
|
||||
},
|
||||
{
|
||||
selector: '.wm-modal-button-container',
|
||||
comment: 'container for button to open modal',
|
||||
@@ -826,6 +830,26 @@ export const customisationByComponent: Customisation[] = [
|
||||
selector: 'wm-alert-card-container',
|
||||
comment: 'Alert container',
|
||||
customCssKey: 'container'
|
||||
},
|
||||
{
|
||||
selector: 'wm-alert-card-background',
|
||||
comment: 'Alert background',
|
||||
customCssKey: 'background'
|
||||
},
|
||||
{
|
||||
selector: 'wm-alert-card-icon',
|
||||
comment: 'Alert icon',
|
||||
customCssKey: 'icon'
|
||||
},
|
||||
{
|
||||
selector: 'wm-alert-card-title',
|
||||
comment: 'Alert title',
|
||||
customCssKey: 'title'
|
||||
},
|
||||
{
|
||||
selector: 'wm-alert-card-description',
|
||||
comment: 'Alert description',
|
||||
customCssKey: 'description'
|
||||
}
|
||||
],
|
||||
variables: []
|
||||
@@ -860,3 +884,9 @@ export function hasStyleValue(obj: ComponentCssProperty | undefined) {
|
||||
|
||||
return obj.style !== ''
|
||||
}
|
||||
|
||||
export function appendClass(className: string | undefined, customCssKey: string) {
|
||||
if (!className) return customCssKey
|
||||
|
||||
return `${className} ${customCssKey}`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user