mirror of
https://gitlab.com/bramw/baserow.git
synced 2025-04-17 10:22:36 +00:00
Add style for collection fields
This commit is contained in:
parent
1f2b7eae5e
commit
a5148fa1fa
47 changed files with 564 additions and 211 deletions
backend
src/baserow/contrib/builder
tests/baserow/contrib/builder
changelog/entries/unreleased/feature
web-frontend/modules
builder
collectionFieldTypes.js
components
elements
baseComponents
components
theme
locales
mixins
plugins
themeConfigBlockTypes.jscore/assets/scss/components/builder
|
@ -258,7 +258,7 @@ class CollectionFieldSerializer(serializers.ModelSerializer):
|
|||
object.
|
||||
"""
|
||||
|
||||
default_allowed_fields = ["name", "type", "id", "uid"]
|
||||
default_allowed_fields = ["name", "type", "id", "uid", "styles"]
|
||||
|
||||
config = serializers.DictField(
|
||||
required=False,
|
||||
|
|
|
@ -698,6 +698,12 @@ class CollectionField(models.Model):
|
|||
help_text="The configuration of the field.",
|
||||
)
|
||||
|
||||
styles = models.JSONField(
|
||||
default=dict,
|
||||
help_text="The theme overrides for this field",
|
||||
null=True, # TODO zdm remove me after 1.27
|
||||
)
|
||||
|
||||
def get_type(self):
|
||||
"""Returns the type for this model instance"""
|
||||
|
||||
|
|
|
@ -368,6 +368,7 @@ class CollectionFieldType(
|
|||
"uid": str(instance.uid),
|
||||
"name": instance.name,
|
||||
"type": instance.type,
|
||||
"styles": instance.styles,
|
||||
"config": serialized_config,
|
||||
}
|
||||
|
||||
|
@ -440,6 +441,7 @@ class CollectionFieldType(
|
|||
"uid": serialized_values.get("uid", RandomUUID()),
|
||||
"config": deserialized_config,
|
||||
"type": serialized_values["type"],
|
||||
"styles": serialized_values.get("styles", {}),
|
||||
"name": serialized_values["name"],
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 4.2.13 on 2024-07-19 10:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("builder", "0032_tablethemeconfigblock"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="collectionfield",
|
||||
name="styles",
|
||||
field=models.JSONField(
|
||||
default=dict, help_text="The theme overrides for this field", null=True
|
||||
),
|
||||
),
|
||||
]
|
|
@ -87,7 +87,13 @@ def test_can_update_a_table_element_fields(api_client, data_fixture):
|
|||
{key: value for key, value in f.items() if key not in ["id"]}
|
||||
for f in response.json()["fields"]
|
||||
] == [
|
||||
{"name": "Name", "type": "text", "value": "get('test1')", "uid": uuids[0]},
|
||||
{
|
||||
"name": "Name",
|
||||
"type": "text",
|
||||
"value": "get('test1')",
|
||||
"uid": uuids[0],
|
||||
"styles": {},
|
||||
},
|
||||
{
|
||||
"name": "Color",
|
||||
"type": "link",
|
||||
|
@ -95,9 +101,16 @@ def test_can_update_a_table_element_fields(api_client, data_fixture):
|
|||
"navigate_to_url": "get('test2')",
|
||||
"link_name": "get('test3')",
|
||||
"target": "self",
|
||||
"styles": {},
|
||||
"uid": uuids[1],
|
||||
},
|
||||
{"name": "Question", "type": "text", "value": "get('test3')", "uid": uuids[2]},
|
||||
{
|
||||
"name": "Question",
|
||||
"type": "text",
|
||||
"value": "get('test3')",
|
||||
"uid": uuids[2],
|
||||
"styles": {},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -459,6 +459,7 @@ def test_builder_application_export(data_fixture):
|
|||
"type": f.type,
|
||||
"config": f.config,
|
||||
"uid": str(f.uid),
|
||||
"styles": {},
|
||||
}
|
||||
for f in element4.fields.all()
|
||||
],
|
||||
|
@ -855,18 +856,21 @@ def test_builder_application_export(data_fixture):
|
|||
"uid": "447cbec7-c422-42eb-bd50-204b53453330",
|
||||
"name": "Field 1",
|
||||
"type": "text",
|
||||
"styles": {},
|
||||
"config": {"value": "get('test1')"},
|
||||
},
|
||||
{
|
||||
"uid": "44446a1c-841f-47ba-b1df-e902cc50c6ed",
|
||||
"name": "Field 2",
|
||||
"type": "text",
|
||||
"styles": {},
|
||||
"config": {"value": "get('test2')"},
|
||||
},
|
||||
{
|
||||
"uid": "960aef1f-a894-4003-8cf2-36da3b9c798b",
|
||||
"name": "Field 3",
|
||||
"type": "text",
|
||||
"styles": {},
|
||||
"config": {"value": "get('test3')"},
|
||||
},
|
||||
],
|
||||
|
@ -1111,12 +1115,14 @@ IMPORT_REFERENCE = {
|
|||
{
|
||||
"name": "F 1",
|
||||
"type": "text",
|
||||
"styles": {},
|
||||
"config": {"value": "get('current_record.field_25')"},
|
||||
"uid": str(uuid.uuid4()),
|
||||
},
|
||||
{
|
||||
"name": "F 2",
|
||||
"type": "link",
|
||||
"styles": {},
|
||||
"uid": str(uuid.uuid4()),
|
||||
"config": {
|
||||
"page_parameters": [],
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "feature",
|
||||
"message": "[Builder] Allow to configure table field styles",
|
||||
"issue_number": 2803,
|
||||
"bullet_points": [],
|
||||
"created_at": "2024-07-23"
|
||||
}
|
|
@ -17,6 +17,7 @@ import {
|
|||
import resolveElementUrl from '@baserow/modules/builder/utils/urlResolution'
|
||||
import { pathParametersInError } from '@baserow/modules/builder/utils/params'
|
||||
import { ClickEvent } from '@baserow/modules/builder/eventTypes'
|
||||
import { ThemeConfigBlockType } from '@baserow/modules/builder/themeConfigBlockTypes'
|
||||
|
||||
export class CollectionFieldType extends Registerable {
|
||||
get name() {
|
||||
|
@ -51,6 +52,15 @@ export class CollectionFieldType extends Registerable {
|
|||
isInError({ field, builder }) {
|
||||
return false
|
||||
}
|
||||
|
||||
getStyleOverride({ colorVariables, field, theme }) {
|
||||
return ThemeConfigBlockType.getAllStyles(
|
||||
this.app.$registry.getOrderedList('themeConfigBlock'),
|
||||
field.styles?.cell || {},
|
||||
colorVariables,
|
||||
theme
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export class BooleanCollectionFieldType extends CollectionFieldType {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<p class="ab-paragraph">
|
||||
<p class="ab-text">
|
||||
<slot />
|
||||
</p>
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<template>
|
||||
<BaserowTable
|
||||
:fields="fields"
|
||||
:rows="rows"
|
||||
class="ab-table"
|
||||
:orientation="orientation"
|
||||
>
|
||||
<template #field-name="{ field }">
|
||||
<th :key="field.__id__" class="ab-table__header-cell">
|
||||
<slot name="field-name" :field="field">{{ field.name }}</slot>
|
||||
</th>
|
||||
</template>
|
||||
<template #cell-content="{ rowIndex, value, field }">
|
||||
<slot
|
||||
name="cell-content"
|
||||
:value="value"
|
||||
:field="field"
|
||||
:row-index="rowIndex"
|
||||
>
|
||||
<td :key="field.id" class="ab-table__cell">
|
||||
<div class="ab-table__cell-content">
|
||||
{{ value }}
|
||||
</div>
|
||||
</td>
|
||||
</slot>
|
||||
</template>
|
||||
<template #empty-state>
|
||||
<div class="ab-table__empty-message">
|
||||
{{ $t('abTable.empty') }}
|
||||
</div>
|
||||
</template>
|
||||
</BaserowTable>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TABLE_ORIENTATION } from '@baserow/modules/builder/enums'
|
||||
import BaserowTable from '@baserow/modules/builder/components/elements/components/BaserowTable'
|
||||
|
||||
export default {
|
||||
name: 'ABTable',
|
||||
components: { BaserowTable },
|
||||
props: {
|
||||
fields: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
rows: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
orientation: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: TABLE_ORIENTATION.HORIZONTAL,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,17 @@
|
|||
<template>
|
||||
<span class="ab-tag" :style="{ ['--tag-background-color']: color }">
|
||||
<slot />
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ABTag',
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -4,13 +4,13 @@
|
|||
<template v-if="orientation === TABLE_ORIENTATION.HORIZONTAL">
|
||||
<thead>
|
||||
<tr class="baserow-table__row">
|
||||
<th
|
||||
v-for="field in fields"
|
||||
:key="field.__id__"
|
||||
class="baserow-table__header-cell"
|
||||
>
|
||||
<slot name="field-name" :field="field">{{ field.name }}</slot>
|
||||
</th>
|
||||
<template v-for="field in fields">
|
||||
<slot name="field-name" :field="field">
|
||||
<th :key="field.__id__" class="baserow-table__header-cell">
|
||||
{{ field.name }}
|
||||
</th>
|
||||
</slot>
|
||||
</template>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody v-if="rows.length">
|
||||
|
@ -19,20 +19,18 @@
|
|||
:key="row.__id__"
|
||||
class="baserow-table__row"
|
||||
>
|
||||
<td
|
||||
v-for="field in fields"
|
||||
:key="field.id"
|
||||
class="baserow-table__cell"
|
||||
>
|
||||
<template v-for="field in fields">
|
||||
<slot
|
||||
name="cell-content"
|
||||
:value="row[field.name]"
|
||||
:field="field"
|
||||
:row-index="index"
|
||||
>
|
||||
{{ row[field.name] }}
|
||||
<td :key="field.id" class="baserow-table__cell">
|
||||
{{ row[field.name] }}
|
||||
</td>
|
||||
</slot>
|
||||
</td>
|
||||
</template>
|
||||
</tr>
|
||||
</tbody>
|
||||
</template>
|
||||
|
@ -47,29 +45,27 @@
|
|||
v-for="(field, fieldIndex) in fields"
|
||||
:key="`${row.__id__}_${field.id}`"
|
||||
>
|
||||
<th
|
||||
class="baserow-table__header-cell"
|
||||
:class="{
|
||||
'baserow-table__separator': fieldIndex === fields.length - 1,
|
||||
}"
|
||||
<slot name="field-name" :field="field">
|
||||
<th :key="field.__id__" class="baserow-table__header-cell">
|
||||
{{ field.name }}
|
||||
</th>
|
||||
</slot>
|
||||
<slot
|
||||
name="cell-content"
|
||||
:value="row[field.name]"
|
||||
:field="field"
|
||||
:row-index="rowIndex"
|
||||
>
|
||||
{{ field.name }}
|
||||
</th>
|
||||
<td
|
||||
class="baserow-table__cell"
|
||||
:class="{
|
||||
'baserow-table__separator': fieldIndex === fields.length - 1,
|
||||
}"
|
||||
>
|
||||
<slot
|
||||
name="cell-content"
|
||||
:value="row[field.name]"
|
||||
:field="field"
|
||||
:row-index="rowIndex"
|
||||
<td
|
||||
class="baserow-table__cell"
|
||||
:class="{
|
||||
'baserow-table__separator':
|
||||
fieldIndex === fields.length - 1,
|
||||
}"
|
||||
>
|
||||
{{ value }}
|
||||
</slot>
|
||||
</td>
|
||||
</td>
|
||||
</slot>
|
||||
</tr>
|
||||
</tbody>
|
||||
</template>
|
||||
|
@ -105,9 +101,6 @@ export default {
|
|||
default: TABLE_ORIENTATION.HORIZONTAL,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
TABLE_ORIENTATION() {
|
||||
return TABLE_ORIENTATION
|
||||
|
|
|
@ -1,31 +1,46 @@
|
|||
<template>
|
||||
<div class="table-element">
|
||||
<BaserowTable
|
||||
:fields="element.fields"
|
||||
<ABTable
|
||||
:fields="fields"
|
||||
:rows="rows"
|
||||
:orientation="orientation"
|
||||
class="ab-table"
|
||||
:style="getStyleOverride('table')"
|
||||
:orientation="orientation"
|
||||
>
|
||||
<template #cell-content="{ rowIndex, field, value }">
|
||||
<component
|
||||
:is="collectionFieldTypes[field.type].component"
|
||||
:element="element"
|
||||
:field="field"
|
||||
:application-context-additions="{
|
||||
recordIndex: rowIndex,
|
||||
recordIndexPath: [...applicationContext.recordIndexPath, rowIndex],
|
||||
field,
|
||||
<!--
|
||||
-- We force-self-aligment to `auto` here to prevent some self-positionning
|
||||
-- like in buttons or links. we want to position the content through the table
|
||||
-- style to be able to override it later. Otherwise we have a conflict between
|
||||
-- these two aligments and only the more specific one (the field one)
|
||||
-- is respected even if it comes from the main theme.
|
||||
-->
|
||||
<td
|
||||
:key="field.id"
|
||||
class="ab-table__cell"
|
||||
:style="{
|
||||
'--force-self-alignment': 'auto',
|
||||
...fieldOverrides[field.id],
|
||||
}"
|
||||
v-bind="value"
|
||||
/>
|
||||
>
|
||||
<div class="ab-table__cell-content">
|
||||
<component
|
||||
:is="collectionFieldTypes[field.type].component"
|
||||
:element="element"
|
||||
:field="field"
|
||||
:application-context-additions="{
|
||||
recordIndex: rowIndex,
|
||||
recordIndexPath: [
|
||||
...applicationContext.recordIndexPath,
|
||||
rowIndex,
|
||||
],
|
||||
field,
|
||||
}"
|
||||
v-bind="value"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</template>
|
||||
<template #empty-state>
|
||||
<div class="table-element__empty-message">
|
||||
{{ $t('tableElement.empty') }}
|
||||
</div>
|
||||
</template>
|
||||
</BaserowTable>
|
||||
</ABTable>
|
||||
<div class="table-element__footer">
|
||||
<ABButton
|
||||
v-if="hasMorePage"
|
||||
|
@ -97,6 +112,22 @@ export default {
|
|||
return newRow
|
||||
})
|
||||
},
|
||||
fieldOverrides() {
|
||||
return Object.fromEntries(
|
||||
this.element.fields.map((field) => {
|
||||
const fieldType = this.collectionFieldTypes[field.type]
|
||||
|
||||
return [
|
||||
field.id,
|
||||
fieldType.getStyleOverride({
|
||||
colorVariables: this.colorVariables,
|
||||
field,
|
||||
theme: this.builder.theme,
|
||||
}),
|
||||
]
|
||||
})
|
||||
)
|
||||
},
|
||||
collectionFieldTypes() {
|
||||
return this.$registry.getAll('collectionField')
|
||||
},
|
||||
|
|
|
@ -97,7 +97,7 @@ export default {
|
|||
return renderer.renderToken(tokens, idx, options)
|
||||
},
|
||||
paragraph_open: (tokens, idx, options, env, renderer) => {
|
||||
tokens[idx].attrJoin('class', 'ab-paragraph')
|
||||
tokens[idx].attrJoin('class', 'ab-text')
|
||||
return renderer.renderToken(tokens, idx, options)
|
||||
},
|
||||
table_open: (tokens, idx, options, env, renderer) => {
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
|
||||
<script>
|
||||
import ABCheckbox from '@baserow/modules/builder/components/elements/baseComponents/ABCheckbox'
|
||||
import collectionField from '@baserow/modules/builder/mixins/collectionField'
|
||||
|
||||
export default {
|
||||
name: 'BooleanField',
|
||||
components: { ABCheckbox },
|
||||
mixins: [collectionField],
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
|
|
|
@ -8,24 +8,16 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import element from '@baserow/modules/builder/mixins/element'
|
||||
import collectionField from '@baserow/modules/builder/mixins/collectionField'
|
||||
|
||||
export default {
|
||||
name: 'ButtonField',
|
||||
mixins: [element],
|
||||
mixins: [collectionField],
|
||||
props: {
|
||||
element: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
field: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
eventName() {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<template>
|
||||
<div class="link-field">
|
||||
<ABLink variant="button" :url="url" :target="target">
|
||||
{{ realLinkName }}
|
||||
</ABLink>
|
||||
</div>
|
||||
<ABLink variant="button" :url="url" :target="target">
|
||||
{{ realLinkName }}
|
||||
</ABLink>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import collectionField from '@baserow/modules/builder/mixins/collectionField'
|
||||
|
||||
export default {
|
||||
name: 'LinkField',
|
||||
inject: ['mode', 'builder'],
|
||||
mixins: [collectionField],
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
|
|
|
@ -1,23 +1,21 @@
|
|||
<template>
|
||||
<div class="ab-tag-group">
|
||||
<div
|
||||
<div class="tag-field">
|
||||
<ABTag
|
||||
v-for="(tag, index) in tags"
|
||||
:key="`${index}-${tag.value}`"
|
||||
class="ab-tag"
|
||||
:style="`background-color: ${resolveColor(tag.color, colorVariables)}`"
|
||||
:color="resolveColor(tag.color, colorVariables)"
|
||||
>
|
||||
{{ tag.value }}
|
||||
</div>
|
||||
</ABTag>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { resolveColor } from '@baserow/modules/core/utils/colors'
|
||||
import { themeToColorVariables } from '@baserow/modules/builder/utils/theme'
|
||||
import collectionField from '@baserow/modules/builder/mixins/collectionField'
|
||||
|
||||
export default {
|
||||
name: 'TagsField',
|
||||
inject: ['builder'],
|
||||
mixins: [collectionField],
|
||||
props: {
|
||||
tags: {
|
||||
type: Array,
|
||||
|
@ -25,11 +23,5 @@ export default {
|
|||
default: () => [],
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
colorVariables() {
|
||||
return themeToColorVariables(this.builder.theme)
|
||||
},
|
||||
},
|
||||
methods: { resolveColor },
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
<template>
|
||||
<span>{{ value }}</span>
|
||||
<span class="ab-text">{{ value }}</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import collectionField from '@baserow/modules/builder/mixins/collectionField'
|
||||
|
||||
export default {
|
||||
name: 'TextField',
|
||||
mixins: [collectionField],
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
|
|
|
@ -11,6 +11,16 @@
|
|||
v-model="values.value"
|
||||
:placeholder="$t('textFieldForm.fieldValuePlaceholder')"
|
||||
/>
|
||||
<template #after-input>
|
||||
<CustomStyle
|
||||
v-model="values.styles"
|
||||
style-key="cell"
|
||||
:config-block-types="['table']"
|
||||
:theme="baseTheme"
|
||||
:extra-args="{ onlyCell: true, noAlignment: true }"
|
||||
variant="normal"
|
||||
/>
|
||||
</template>
|
||||
</FormGroup>
|
||||
</form>
|
||||
</template>
|
||||
|
@ -18,16 +28,18 @@
|
|||
<script>
|
||||
import collectionFieldForm from '@baserow/modules/builder/mixins/collectionFieldForm'
|
||||
import InjectedFormulaInput from '@baserow/modules/core/components/formula/InjectedFormulaInput'
|
||||
import CustomStyle from '@baserow/modules/builder/components/elements/components/forms/style/CustomStyle'
|
||||
|
||||
export default {
|
||||
name: 'BooleanFieldForm',
|
||||
components: { InjectedFormulaInput },
|
||||
components: { InjectedFormulaInput, CustomStyle },
|
||||
mixins: [collectionFieldForm],
|
||||
data() {
|
||||
return {
|
||||
allowedValues: ['value'],
|
||||
allowedValues: ['value', 'styles'],
|
||||
values: {
|
||||
value: '',
|
||||
styles: {},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
@ -11,6 +11,16 @@
|
|||
v-model="values.label"
|
||||
:placeholder="$t('buttonFieldForm.labelPlaceholder')"
|
||||
/>
|
||||
<template #after-input>
|
||||
<CustomStyle
|
||||
v-model="values.styles"
|
||||
style-key="cell"
|
||||
:config-block-types="['table', 'button']"
|
||||
:theme="baseTheme"
|
||||
:extra-args="{ onlyCell: true, noAlignment: true }"
|
||||
variant="normal"
|
||||
/>
|
||||
</template>
|
||||
</FormGroup>
|
||||
<Alert>
|
||||
{{ $t('buttonFieldForm.infoMessage') }}
|
||||
|
@ -21,16 +31,18 @@
|
|||
<script>
|
||||
import collectionFieldForm from '@baserow/modules/builder/mixins/collectionFieldForm'
|
||||
import InjectedFormulaInput from '@baserow/modules/core/components/formula/InjectedFormulaInput'
|
||||
import CustomStyle from '@baserow/modules/builder/components/elements/components/forms/style/CustomStyle'
|
||||
|
||||
export default {
|
||||
name: 'ButtonFieldForm',
|
||||
components: { InjectedFormulaInput },
|
||||
components: { InjectedFormulaInput, CustomStyle },
|
||||
mixins: [collectionFieldForm],
|
||||
data() {
|
||||
return {
|
||||
allowedValues: ['label'],
|
||||
allowedValues: ['label', 'styles'],
|
||||
values: {
|
||||
label: '',
|
||||
styles: {},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
@ -11,6 +11,16 @@
|
|||
v-model="values.link_name"
|
||||
:placeholder="$t('linkFieldForm.fieldLinkNamePlaceholder')"
|
||||
/>
|
||||
<template #after-input>
|
||||
<CustomStyle
|
||||
v-model="values.styles"
|
||||
style-key="cell"
|
||||
:config-block-types="['table', 'button']"
|
||||
:theme="baseTheme"
|
||||
:extra-args="{ onlyCell: true, noAlignment: true }"
|
||||
variant="normal"
|
||||
/>
|
||||
</template>
|
||||
</FormGroup>
|
||||
<LinkNavigationSelectionForm
|
||||
:default-values="defaultValues"
|
||||
|
@ -22,20 +32,23 @@
|
|||
<script>
|
||||
import collectionFieldForm from '@baserow/modules/builder/mixins/collectionFieldForm'
|
||||
import InjectedFormulaInput from '@baserow/modules/core/components/formula/InjectedFormulaInput'
|
||||
import CustomStyle from '@baserow/modules/builder/components/elements/components/forms/style/CustomStyle'
|
||||
import LinkNavigationSelectionForm from '@baserow/modules/builder/components/elements/components/forms/general/LinkNavigationSelectionForm'
|
||||
|
||||
export default {
|
||||
name: 'TextField',
|
||||
components: {
|
||||
InjectedFormulaInput,
|
||||
CustomStyle,
|
||||
LinkNavigationSelectionForm,
|
||||
},
|
||||
mixins: [collectionFieldForm],
|
||||
data() {
|
||||
return {
|
||||
allowedValues: ['link_name'],
|
||||
allowedValues: ['link_name', 'styles'],
|
||||
values: {
|
||||
link_name: '',
|
||||
styles: {},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
@ -11,6 +11,16 @@
|
|||
v-model="values.values"
|
||||
:placeholder="$t('tagsFieldForm.fieldValuesPlaceholder')"
|
||||
/>
|
||||
<template #after-input>
|
||||
<CustomStyle
|
||||
v-model="values.styles"
|
||||
style-key="cell"
|
||||
:config-block-types="['table', 'typography']"
|
||||
:theme="baseTheme"
|
||||
:extra-args="{ onlyCell: true, onlyBody: true, noAlignment: true }"
|
||||
variant="normal"
|
||||
/>
|
||||
</template>
|
||||
</FormGroup>
|
||||
|
||||
<div>
|
||||
|
@ -61,18 +71,20 @@
|
|||
<script>
|
||||
import InjectedFormulaInput from '@baserow/modules/core/components/formula/InjectedFormulaInput'
|
||||
import collectionFieldForm from '@baserow/modules/builder/mixins/collectionFieldForm'
|
||||
import CustomStyle from '@baserow/modules/builder/components/elements/components/forms/style/CustomStyle'
|
||||
|
||||
export default {
|
||||
name: 'TagsField',
|
||||
components: { InjectedFormulaInput },
|
||||
components: { InjectedFormulaInput, CustomStyle },
|
||||
mixins: [collectionFieldForm],
|
||||
data() {
|
||||
return {
|
||||
allowedValues: ['values', 'colors', 'colors_is_formula'],
|
||||
allowedValues: ['values', 'colors', 'colors_is_formula', 'styles'],
|
||||
values: {
|
||||
values: '',
|
||||
colors: '#acc8f8',
|
||||
colors_is_formula: false,
|
||||
styles: {},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
@ -11,6 +11,16 @@
|
|||
v-model="values.value"
|
||||
:placeholder="$t('textFieldForm.fieldValuePlaceholder')"
|
||||
/>
|
||||
<template #after-input>
|
||||
<CustomStyle
|
||||
v-model="values.styles"
|
||||
style-key="cell"
|
||||
:config-block-types="['table', 'typography']"
|
||||
:theme="baseTheme"
|
||||
:extra-args="{ onlyCell: true, onlyBody: true, noAlignment: true }"
|
||||
variant="normal"
|
||||
/>
|
||||
</template>
|
||||
</FormGroup>
|
||||
</form>
|
||||
</template>
|
||||
|
@ -18,16 +28,18 @@
|
|||
<script>
|
||||
import collectionFieldForm from '@baserow/modules/builder/mixins/collectionFieldForm'
|
||||
import InjectedFormulaInput from '@baserow/modules/core/components/formula/InjectedFormulaInput'
|
||||
import CustomStyle from '@baserow/modules/builder/components/elements/components/forms/style/CustomStyle'
|
||||
|
||||
export default {
|
||||
name: 'TextField',
|
||||
components: { InjectedFormulaInput },
|
||||
components: { InjectedFormulaInput, CustomStyle },
|
||||
mixins: [collectionFieldForm],
|
||||
data() {
|
||||
return {
|
||||
allowedValues: ['value'],
|
||||
allowedValues: ['value', 'styles'],
|
||||
values: {
|
||||
value: '',
|
||||
styles: {},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
<CustomStyle
|
||||
v-model="values.styles"
|
||||
style-key="table"
|
||||
:config-block-types="['table']"
|
||||
:config-block-types="['table', 'typography']"
|
||||
:theme="builder.theme"
|
||||
:extra-args="{ onlyBody: true, noAlignment: true }"
|
||||
/>
|
||||
<FormGroup
|
||||
class="margin-bottom-2"
|
||||
|
@ -46,7 +47,6 @@
|
|||
:config-block-types="['button']"
|
||||
:theme="builder.theme"
|
||||
/>
|
||||
|
||||
<FormGroup
|
||||
small-label
|
||||
:label="$t('tableElementForm.buttonLoadMoreLabel')"
|
||||
|
@ -161,6 +161,7 @@
|
|||
:is="collectionTypes[field.type].formComponent"
|
||||
:element="element"
|
||||
:default-values="field"
|
||||
:base-theme="collectionFieldBaseTheme"
|
||||
:application-context-additions="{
|
||||
collectionField: field,
|
||||
}"
|
||||
|
@ -267,6 +268,9 @@ export default {
|
|||
collectionTypes() {
|
||||
return this.$registry.getAll('collectionField')
|
||||
},
|
||||
collectionFieldBaseTheme() {
|
||||
return { ...this.builder.theme, ...this.values.styles?.table }
|
||||
},
|
||||
errorMessageItemsPerPage() {
|
||||
return this.$v.values.items_per_page.$dirty &&
|
||||
!this.$v.values.items_per_page.required
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
<template>
|
||||
<div class="custom-style">
|
||||
<div class="custom-style" :class="`custom-style--${variant}`">
|
||||
<ButtonText
|
||||
v-if="variant === 'float'"
|
||||
v-tooltip="$t('customStyle.configureThemeOverrides')"
|
||||
class="custom-style__button"
|
||||
icon="baserow-icon-settings"
|
||||
tooltip-position="bottom-left"
|
||||
@click="openPanel()"
|
||||
/>
|
||||
<ButtonIcon
|
||||
v-else
|
||||
v-tooltip="$t('customStyle.configureThemeOverrides')"
|
||||
class="custom-style__button"
|
||||
icon="baserow-icon-settings"
|
||||
|
@ -14,30 +23,29 @@
|
|||
{{ $t('customStyle.themeOverrides') }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-auto-overflow-scroll class="custom-style__config-blocks">
|
||||
<div
|
||||
v-for="(themeConfigBlock, index) in themeConfigBlocks"
|
||||
<Tabs class="custom-style__config-blocks">
|
||||
<Tab
|
||||
v-for="themeConfigBlock in themeConfigBlocks"
|
||||
:key="themeConfigBlock.getType()"
|
||||
:title="themeConfigBlock.label"
|
||||
class="custom-style__config-block"
|
||||
>
|
||||
<h2
|
||||
v-if="themeConfigBlocks.length > 1"
|
||||
class="custom-style__config-block-title"
|
||||
<div
|
||||
v-auto-overflow-scroll
|
||||
class="custom-style__config-block-content"
|
||||
>
|
||||
{{ themeConfigBlock.label }}
|
||||
</h2>
|
||||
<ThemeConfigBlock
|
||||
ref="configBlocks"
|
||||
:theme="theme"
|
||||
:default-values="value?.[styleKey]"
|
||||
:preview="false"
|
||||
:theme-config-block-type="themeConfigBlock"
|
||||
:class="{ 'margin-top-3': index >= 1 }"
|
||||
:extra-args="extraArgs"
|
||||
@values-changed="onValuesChanged($event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<ThemeConfigBlock
|
||||
ref="configBlocks"
|
||||
:theme="theme"
|
||||
:default-values="value?.[styleKey]"
|
||||
:preview="false"
|
||||
:theme-config-block-type="themeConfigBlock"
|
||||
:extra-args="extraArgs"
|
||||
@values-changed="onValuesChanged($event)"
|
||||
/>
|
||||
</div>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</Context>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -55,6 +63,14 @@ export default {
|
|||
required: false,
|
||||
default: () => {},
|
||||
},
|
||||
variant: {
|
||||
required: false,
|
||||
type: String,
|
||||
default: 'float',
|
||||
validator: function (value) {
|
||||
return ['float', 'normal'].includes(value)
|
||||
},
|
||||
},
|
||||
theme: { type: Object, required: true },
|
||||
configBlockTypes: {
|
||||
type: Array,
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
</template>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
v-if="values.button_width === 'auto'"
|
||||
v-if="values.button_width === 'auto' && !extraArgs?.noAlignment"
|
||||
horizontal-narrow
|
||||
small-label
|
||||
required
|
||||
|
@ -34,7 +34,7 @@
|
|||
</template>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
v-else
|
||||
v-if="values.button_width === 'full'"
|
||||
horizontal-narrow
|
||||
small-label
|
||||
required
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
</template>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
v-if="!extraArgs?.noAlignment"
|
||||
horizontal-narrow
|
||||
small-label
|
||||
required
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<template>
|
||||
<div>
|
||||
<ThemeConfigBlockSection :title="$t('tableThemeConfigBlock.table')">
|
||||
<ThemeConfigBlockSection
|
||||
v-if="!onlyCell"
|
||||
:title="$t('tableThemeConfigBlock.table')"
|
||||
>
|
||||
<template #default>
|
||||
<FormGroup
|
||||
horizontal-narrow
|
||||
|
@ -54,12 +57,14 @@
|
|||
</FormGroup>
|
||||
</template>
|
||||
<template #preview>
|
||||
<BaserowTable :fields="fields" :rows="rows" class="ab-table">
|
||||
</BaserowTable>
|
||||
<ABTable :fields="fields" :rows="rows" />
|
||||
</template>
|
||||
</ThemeConfigBlockSection>
|
||||
|
||||
<ThemeConfigBlockSection :title="$t('tableThemeConfigBlock.header')">
|
||||
<ThemeConfigBlockSection
|
||||
v-if="!onlyCell"
|
||||
:title="$t('tableThemeConfigBlock.header')"
|
||||
>
|
||||
<template #default>
|
||||
<FormGroup
|
||||
horizontal-narrow
|
||||
|
@ -148,8 +153,7 @@
|
|||
</FormGroup>
|
||||
</template>
|
||||
<template #preview>
|
||||
<BaserowTable :fields="fields" :rows="rows" class="ab-table">
|
||||
</BaserowTable>
|
||||
<ABTable :fields="fields" :rows="rows" />
|
||||
</template>
|
||||
</ThemeConfigBlockSection>
|
||||
|
||||
|
@ -232,11 +236,13 @@
|
|||
</FormGroup>
|
||||
</template>
|
||||
<template #preview>
|
||||
<BaserowTable :fields="fields" :rows="rows" class="ab-table">
|
||||
</BaserowTable>
|
||||
<ABTable :fields="fields" :rows="rows" />
|
||||
</template>
|
||||
</ThemeConfigBlockSection>
|
||||
<ThemeConfigBlockSection :title="$t('tableThemeConfigBlock.separators')">
|
||||
<ThemeConfigBlockSection
|
||||
v-if="!onlyCell"
|
||||
:title="$t('tableThemeConfigBlock.separators')"
|
||||
>
|
||||
<template #default>
|
||||
<FormGroup
|
||||
horizontal-narrow
|
||||
|
@ -310,8 +316,7 @@
|
|||
</FormGroup>
|
||||
</template>
|
||||
<template #preview>
|
||||
<BaserowTable :fields="fields" :rows="rows" class="ab-table">
|
||||
</BaserowTable>
|
||||
<ABTable :fields="fields" :rows="rows" />
|
||||
</template>
|
||||
</ThemeConfigBlockSection>
|
||||
</div>
|
||||
|
@ -397,6 +402,9 @@ export default {
|
|||
this.values.table_cell_horizontal_padding = newValue.horizontal
|
||||
},
|
||||
},
|
||||
onlyCell() {
|
||||
return this.extraArgs?.onlyCell
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isAllowedKey(key) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
</template>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
v-if="!extraArgs?.noAlignment"
|
||||
horizontal-narrow
|
||||
small-label
|
||||
class="margin-bottom-2"
|
||||
|
|
|
@ -383,6 +383,7 @@
|
|||
"table": "Table"
|
||||
},
|
||||
"colorThemeConfigBlock": {
|
||||
"transparent": "Transparent",
|
||||
"primaryColor": "Primary",
|
||||
"secondaryColor": "Secondary",
|
||||
"borderColor": "Border",
|
||||
|
@ -464,7 +465,7 @@
|
|||
},
|
||||
"tableThemeConfigBlock": {
|
||||
"borderColor": "Border color",
|
||||
"backgroundAlternateColor": "Alternate color",
|
||||
"backgroundAlternateColor": "Even rows color",
|
||||
"backgroundColor": "Background color",
|
||||
"textColor": "Text color",
|
||||
"borderSize": "Border size",
|
||||
|
@ -531,9 +532,11 @@
|
|||
"buttonLoadMoreLabel": "Show more label"
|
||||
},
|
||||
"tableElement": {
|
||||
"empty": "No items have been found.",
|
||||
"showMore": "Show more"
|
||||
},
|
||||
"abTable": {
|
||||
"empty": "No items have been found."
|
||||
},
|
||||
"repeatElement": {
|
||||
"empty": "No items have been found.",
|
||||
"showMore": "Show more",
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { mapGetters } from 'vuex'
|
||||
import applicationContextMixin from '@baserow/modules/builder/mixins/applicationContext'
|
||||
|
||||
export default {
|
||||
mixins: [applicationContextMixin],
|
||||
computed: {
|
||||
dataSources() {
|
||||
return this.$store.getters['dataSource/getPageDataSources'](this.page)
|
||||
|
|
35
web-frontend/modules/builder/mixins/collectionField.js
Normal file
35
web-frontend/modules/builder/mixins/collectionField.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { resolveColor } from '@baserow/modules/core/utils/colors'
|
||||
import { ThemeConfigBlockType } from '@baserow/modules/builder/themeConfigBlockTypes'
|
||||
import applicationContextMixin from '@baserow/modules/builder/mixins/applicationContext'
|
||||
|
||||
export default {
|
||||
inject: ['workspace', 'builder', 'page', 'mode'],
|
||||
mixins: [applicationContextMixin],
|
||||
props: {
|
||||
element: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
field: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
elementType() {
|
||||
return this.$registry.get('element', this.element.type)
|
||||
},
|
||||
themeConfigBlocks() {
|
||||
return this.$registry.getOrderedList('themeConfigBlock')
|
||||
},
|
||||
colorVariables() {
|
||||
return ThemeConfigBlockType.getAllColorVariables(
|
||||
this.themeConfigBlocks,
|
||||
this.builder.theme
|
||||
)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
resolveColor,
|
||||
},
|
||||
}
|
|
@ -8,5 +8,9 @@ export default {
|
|||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
baseTheme: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import ABCheckbox from '@baserow/modules/builder/components/elements/baseCompone
|
|||
import ABRadio from '@baserow/modules/builder/components/elements/baseComponents/ABRadio.vue'
|
||||
import ABImage from '@baserow/modules/builder/components/elements/baseComponents/ABImage.vue'
|
||||
import ABParagraph from '@baserow/modules/builder/components/elements/baseComponents/ABParagraph.vue'
|
||||
import ABTag from '@baserow/modules/builder/components/elements/baseComponents/ABTag.vue'
|
||||
import ABTable from '@baserow/modules/builder/components/elements/baseComponents/ABTable.vue'
|
||||
|
||||
function setupVueForAB(Vue) {
|
||||
Vue.component('ABButton', ABButton)
|
||||
|
@ -24,6 +26,8 @@ function setupVueForAB(Vue) {
|
|||
Vue.component('ABRadio', ABRadio)
|
||||
Vue.component('ABImage', ABImage)
|
||||
Vue.component('ABParagraph', ABParagraph)
|
||||
Vue.component('ABTag', ABTag)
|
||||
Vue.component('ABTable', ABTable)
|
||||
}
|
||||
|
||||
setupVueForAB(Vue)
|
||||
|
|
|
@ -283,6 +283,7 @@ export class TypographyThemeConfigBlockType extends ThemeConfigBlockType {
|
|||
style.addColorIfExists(theme, `body_text_color`)
|
||||
style.addIfExists(theme, `body_text_alignment`)
|
||||
style.addFontFamilyIfExists(theme, `body_font_family`)
|
||||
|
||||
return style.toObject()
|
||||
}
|
||||
|
||||
|
@ -606,11 +607,31 @@ export class TableThemeConfigBlockType extends ThemeConfigBlockType {
|
|||
style.addIfExists(theme, `table_header_text_alignment`)
|
||||
|
||||
style.addColorIfExists(theme, 'table_cell_background_color')
|
||||
style.addColorIfExists(theme, 'table_cell_alternate_background_color')
|
||||
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(
|
||||
theme,
|
||||
'table_cell_alternate_background_color'
|
||||
) &&
|
||||
theme.table_cell_alternate_background_color !== 'transparent'
|
||||
) {
|
||||
// We want to set the alternate color only if defined
|
||||
style.addColorIfExists(theme, 'table_cell_alternate_background_color')
|
||||
}
|
||||
style.addColorIfExists(theme, 'table_cell_text_color')
|
||||
style.addFontFamilyIfExists(theme, `table_cell_font_family`)
|
||||
style.addPixelValueIfExists(theme, `table_cell_font_size`)
|
||||
style.addIfExists(theme, `table_cell_alignment`)
|
||||
style.addIfExists(
|
||||
theme,
|
||||
'table_cell_alignment',
|
||||
null,
|
||||
(v) =>
|
||||
({
|
||||
[HORIZONTAL_ALIGNMENTS.LEFT]: 'flex-start',
|
||||
[HORIZONTAL_ALIGNMENTS.CENTER]: 'center',
|
||||
[HORIZONTAL_ALIGNMENTS.RIGHT]: 'flex-end',
|
||||
}[v])
|
||||
)
|
||||
style.addPixelValueIfExists(theme, `table_cell_vertical_padding`)
|
||||
style.addPixelValueIfExists(theme, `table_cell_horizontal_padding`)
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
border-radius: var(--button-border-radius, 4px);
|
||||
width: var(--button-width, auto);
|
||||
text-align: var(--button-text-alignment, center);
|
||||
align-self: var(--button-alignment, flex-start);
|
||||
align-self: var(--force-self-alignment, var(--button-alignment, initial));
|
||||
font-family: var(--button-font-family, Inter);
|
||||
padding: var(--button-vertical-padding, 4px)
|
||||
var(--button-horizontal-padding, 12px);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
font-size: var(--link-font-size, 14px);
|
||||
text-decoration: var(--link-text-decoration, underline);
|
||||
color: var(--link-text-color, $black);
|
||||
align-self: var(--link-text-alignment, flex-start);
|
||||
align-self: var(--force-self-alignment, var(--link-text-alignment, initial));
|
||||
font-family: var(--link-font-family, Inter);
|
||||
|
||||
&:hover,
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
.ab-table {
|
||||
border: var(--table-border-size, 1px) solid var(--table-border-color, $black);
|
||||
text-align: var(--table-cell-alignment, left);
|
||||
font-size: var(--body-font-size, 13px);
|
||||
font-size: var(--body-font-size, 12px);
|
||||
border-radius: var(--table-border-radius, 0);
|
||||
background-color: var(--table-cell-background-color, $palette-neutral-200);
|
||||
background-color: var(--table-cell-background-color, transparent);
|
||||
|
||||
.baserow-table__header-cell,
|
||||
.baserow-table__cell {
|
||||
padding: var(--table-cell-vertical-padding, 10px)
|
||||
var(--table-cell-horizontal-padding, 20px);
|
||||
}
|
||||
|
||||
.baserow-table__cell {
|
||||
.ab-table__cell {
|
||||
font-size: var(--body-font-size, 13px);
|
||||
color: var(--body-text-color, $color-neutral-900);
|
||||
font-family: var(--body-font-family, Inter);
|
||||
text-align: var(--table-cell-alignment, left);
|
||||
background-color: var(--table-cell-background-color, transparent);
|
||||
}
|
||||
|
||||
.baserow-table__header-cell {
|
||||
.ab-table__header-cell {
|
||||
font-weight: 600;
|
||||
background-color: var(
|
||||
--table-header-background-color,
|
||||
|
@ -28,54 +21,89 @@
|
|||
color: var(--table-header-text-color, $color-neutral-900);
|
||||
font-family: var(--table-header-font-family, Inter);
|
||||
text-align: var(--table-header-text-alignment, left);
|
||||
padding: var(--table-cell-vertical-padding, 10px)
|
||||
var(--table-cell-horizontal-padding, 20px);
|
||||
border-right: var(--table-vertical-separator-size, 1px) solid
|
||||
var(--table-vertical-separator-color, $black);
|
||||
}
|
||||
|
||||
& .baserow-table__row:not(:last-child) .baserow-table__separator {
|
||||
border-bottom: var(--table-horizontal-separator-size, 1px) solid
|
||||
var(--table-horizontal-separator-color, $black);
|
||||
.baserow-table__row:nth-child(even) .ab-table__cell {
|
||||
background-color: var(
|
||||
--table-cell-alternate-background-color,
|
||||
var(--table-cell-background-color, transparent)
|
||||
);
|
||||
}
|
||||
|
||||
.baserow-table--vertical {
|
||||
.baserow-table__header-cell {
|
||||
border-right: var(--table-vertical-separator-size, 1px) solid
|
||||
var(--table-vertical-separator-color, $black);
|
||||
}
|
||||
|
||||
tbody.baserow-table__row:nth-child(even) {
|
||||
background-color: var(
|
||||
--table-cell-alternate-background-color,
|
||||
transparent
|
||||
);
|
||||
}
|
||||
.baserow-table__empty-message {
|
||||
background-color: var(--table-cell-background-color, transparent);
|
||||
font-size: var(--body-font-size, 13px);
|
||||
color: var(--body-text-color, $color-neutral-900);
|
||||
font-family: var(--body-font-family, Inter);
|
||||
}
|
||||
|
||||
.baserow-table--horizontal {
|
||||
.baserow-table__header-cell,
|
||||
.baserow-table__cell {
|
||||
border-bottom: var(--table-horizontal-separator-size, 1px) solid
|
||||
var(--table-horizontal-separator-color, $black);
|
||||
border-right: var(--table-vertical-separator-size, 1px) solid
|
||||
var(--table-vertical-separator-color, $black);
|
||||
}
|
||||
|
||||
.baserow-table__row {
|
||||
.baserow-table__cell:last-child,
|
||||
.baserow-table__header-cell:last-child {
|
||||
.ab-table__header-cell,
|
||||
.ab-table__cell {
|
||||
border-bottom: var(--table-horizontal-separator-size, 1px) solid
|
||||
var(--table-horizontal-separator-color, $black);
|
||||
}
|
||||
|
||||
.ab-table__cell {
|
||||
border-right: var(--table-vertical-separator-size, 1px) solid
|
||||
var(--table-vertical-separator-color, $black);
|
||||
}
|
||||
|
||||
.ab-table__cell:last-child,
|
||||
.ab-table__header-cell:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
.baserow-table__row:last-child {
|
||||
.baserow-table__cell {
|
||||
.ab-table__cell {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
tbody .baserow-table__row:nth-child(even) {
|
||||
.baserow-table__row:nth-child(even) .ab-table__cell {
|
||||
background-color: var(
|
||||
--table-cell-alternate-background-color,
|
||||
transparent
|
||||
var(--table-cell-background-color, transparent)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.baserow-table--vertical {
|
||||
.baserow-table__row tr:last-child {
|
||||
.ab-table__header-cell,
|
||||
.ab-table__cell {
|
||||
border-bottom: var(--table-horizontal-separator-size, 1px) solid
|
||||
var(--table-horizontal-separator-color, $black);
|
||||
}
|
||||
}
|
||||
|
||||
.baserow-table__row:last-child tr {
|
||||
.ab-table__header-cell,
|
||||
.ab-table__cell {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ab-table__cell-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: var(--table-cell-alignment, flex-start);
|
||||
padding: var(--table-cell-vertical-padding, 10px)
|
||||
var(--table-cell-horizontal-padding, 20px);
|
||||
}
|
||||
|
||||
.ab-table__empty-message {
|
||||
text-align: center;
|
||||
padding: 50px 0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
.ab-tag-group {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.ab-tag {
|
||||
@include select-option-style(inline-flex, true);
|
||||
@extend %ellipsis;
|
||||
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
max-width: 140px;
|
||||
font-size: var(--body-font-size, 14px);
|
||||
color: var(--body-text-color, $black);
|
||||
font-family: var(--body-font-family, Inter);
|
||||
background-color: var(--tag-background-color, transparent);
|
||||
border-radius: 1em;
|
||||
padding: 0.4em 0.5em;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.ab-paragraph {
|
||||
.ab-text {
|
||||
font-size: var(--body-font-size, 14px);
|
||||
margin: 0;
|
||||
color: var(--body-text-color, $black);
|
|
@ -6,7 +6,7 @@
|
|||
@import 'ab_heading';
|
||||
@import 'ab_input';
|
||||
@import 'ab_link';
|
||||
@import 'ab_paragraph';
|
||||
@import 'ab_text';
|
||||
@import 'ab_tag';
|
||||
@import 'ab_radio';
|
||||
@import 'ab_image';
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
@import 'forms/all';
|
||||
@import 'ab_components/all';
|
||||
@import 'collectionFields/all';
|
||||
@import 'link_element';
|
||||
@import 'heading_element';
|
||||
@import 'image_element';
|
||||
|
@ -11,3 +10,4 @@
|
|||
@import 'choice_element';
|
||||
@import 'iframe_element';
|
||||
@import 'repeat_element';
|
||||
@import 'tag_field';
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
@import 'link_field';
|
|
@ -1,5 +0,0 @@
|
|||
.link-field {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
.tag-field {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
flex-wrap: nowrap;
|
||||
gap: 4px;
|
||||
}
|
|
@ -2,10 +2,12 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.custom-style__button {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: -6px;
|
||||
.custom-style--float {
|
||||
.custom-style__button {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: -6px;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-style__context {
|
||||
|
@ -20,7 +22,7 @@
|
|||
height: 40px;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
border-bottom: 1px solid $color-neutral-200;
|
||||
border-bottom: 1px solid $color-neutral-100;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
@ -37,12 +39,24 @@
|
|||
}
|
||||
|
||||
.custom-style__config-blocks {
|
||||
width: 358px;
|
||||
padding: 20px 20px 5px;
|
||||
overflow-y: auto;
|
||||
// 100% - top bar height
|
||||
height: calc(100% - 40px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.custom-style__config-block-title {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.custom-style__config-block {
|
||||
// Width of sidebar - 2 x padding - left border
|
||||
width: calc(400px - 40px - 1px);
|
||||
overflow-y: auto;
|
||||
|
||||
// 100% - tab header height
|
||||
height: calc(100% - 40px);
|
||||
}
|
||||
|
||||
.custom-style__context .tabs__header {
|
||||
background-color: $color-neutral-50;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue