Add base tab

pull/6768/head
Cagatay Civici 2024-11-12 16:44:52 +03:00
parent 0f4ddcc417
commit 94b225ba1f
4 changed files with 97 additions and 49 deletions

View File

@ -13,17 +13,23 @@
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<div class="flex flex-col gap-4 border border-surface-200 dark:border-surface-700 rounded-md p-4"> <div class="flex flex-col gap-4 border border-surface-200 dark:border-surface-700 rounded-md p-4">
<span class="font-semibold">Built-in Themes</span> <span class="font-semibold">Built-in Themes</span>
<span class="text-muted-color">Four alternatives to choose from.</span>
<SelectButton v-model="$appState.preset" @update:modelValue="onPresetChange" :options="presetOptions" optionLabel="label" optionValue="value" :allowEmpty="false" /> <SelectButton v-model="$appState.preset" @update:modelValue="onPresetChange" :options="presetOptions" optionLabel="label" optionValue="value" :allowEmpty="false" />
</div> </div>
<Divider>OR</Divider> <Divider>OR</Divider>
<div class="flex flex-col gap-4 border border-surface-200 dark:border-surface-700 rounded-md p-4"> <div class="flex flex-col gap-4 border border-surface-200 dark:border-surface-700 rounded-md p-4 items-start">
<span class="font-semibold">Import Figma Tokens</span> <span class="font-semibold">Load Theme</span>
<input type="file" /> <span class="text-muted-color">Continue editing the theme files stored locally.</span>
<Button label="Restore from local storage" class="!px-3 !py-2" severity="secondary" @click="loadFromLocalStorage" />
</div> </div>
<Divider>OR</Divider> <Divider>OR</Divider>
<div class="flex flex-col gap-4 border border-surface-200 dark:border-surface-700 rounded-md p-4 items-start"> <div class="flex flex-col gap-4 border border-surface-200 dark:border-surface-700 rounded-md p-4">
<span class="font-semibold">Saved Theme</span> <div class="flex items-center gap-4">
<Button icon="pi pi-upload" label="Load" class="!px-3 !py-2" severity="secondary" /> <span class="font-semibold">Import Figma Tokens </span>
<Tag value="PRO" severity="contrast"></Tag>
</div>
<span class="text-muted-color leading-6">Export the token studio json file and import to the Visual Editor. This feature is currently under development.</span>
<FileUpload mode="basic" disabled pt:root:class="!justify-start" />
</div> </div>
</div> </div>
</TabPanel> </TabPanel>
@ -120,18 +126,9 @@ export default {
}; };
}, },
mounted() { mounted() {
const savedTheme = localStorage.getItem(this.$appState.designerKey); this.preset.semantic.primary = this.preset.primitive.emerald;
this.preset.semantic.colorScheme.light.surface = { ...{ 0: '#ffffff' }, ...this.preset.primitive.slate };
if (savedTheme) { this.preset.semantic.colorScheme.dark.surface = { ...{ 0: '#ffffff' }, ...this.preset.primitive.zinc };
this.preset = JSON.parse(savedTheme).defaultTheme;
setTimeout(() => {
usePreset(this.preset);
}, 2000);
} else {
this.preset.semantic.primary = this.preset.primitive.emerald;
this.preset.semantic.colorScheme.light.surface = { ...{ 0: '#ffffff' }, ...this.preset.primitive.slate };
this.preset.semantic.colorScheme.dark.surface = { ...{ 0: '#ffffff' }, ...this.preset.primitive.zinc };
}
}, },
methods: { methods: {
apply() { apply() {
@ -194,6 +191,14 @@ app.mount("#app");
}; };
localStorage.setItem(this.$appState.designerKey, JSON.stringify(themeRecord)); localStorage.setItem(this.$appState.designerKey, JSON.stringify(themeRecord));
},
loadFromLocalStorage() {
const savedTheme = localStorage.getItem(this.$appState.designerKey);
if (savedTheme) {
this.preset = JSON.parse(savedTheme).defaultTheme;
this.$toast.add({ severity: 'success', summary: 'Success', detail: 'Theme loaded to Designer', life: 3000 });
}
} }
} }
}; };

View File

@ -1,7 +1,22 @@
<template> <template>
<span class="text-sm">{{ label }}</span> <span class="text-sm">{{ label }}</span>
<div class="relative"> <div class="relative">
<input :value="modelValue" @input="onInput" type="text" :class="['border border-surface-300 dark:border-surface-600 rounded-lg py-2 px-2 w-full', { 'pr-8': type === 'color' }]" /> <AutoComplete
:modelValue="modelValue"
@input="onInput"
:suggestions="items"
@complete="search"
unstyled
:pt="{
pcInputText: {
root: ['border border-surface-300 dark:border-surface-600 rounded-lg py-2 px-2 w-full', { 'pr-8': type === 'color' }]
},
overlay: 'bg-surface-0 dark:bg-surface-950 shadow-2 rounded-md',
listContainer: 'max-h-40 overflow-auto',
list: 'm-0 py-2 px-0 list-none',
option: 'p-2'
}"
/>
<div v-if="type === 'color'" class="absolute right-[4px] top-1/2 -mt-3 w-6 h-6 rounded-md border border-surface-300 dark:border-surface-600" :style="{ backgroundColor: previewColor }"></div> <div v-if="type === 'color'" class="absolute right-[4px] top-1/2 -mt-3 w-6 h-6 rounded-md border border-surface-300 dark:border-surface-600" :style="{ backgroundColor: previewColor }"></div>
</div> </div>
</template> </template>
@ -9,6 +24,32 @@
<script> <script>
import { $dt } from '@primevue/themes'; import { $dt } from '@primevue/themes';
const tokens = [
'{primary.50}',
'{primary.100}',
'{primary.200}',
'{primary.300}',
'{primary.400}',
'{primary.500}',
'{primary.600}',
'{primary.700}',
'{primary.800}',
'{primary.900}',
'{primary.950}',
'{surface.0}',
'{surface.50}',
'{surface.100}',
'{surface.200}',
'{surface.300}',
'{surface.400}',
'{surface.500}',
'{surface.600}',
'{surface.700}',
'{surface.800}',
'{surface.900}',
'{surface.950}'
];
export default { export default {
emits: ['update:modelValue'], emits: ['update:modelValue'],
props: { props: {
@ -25,9 +66,26 @@ export default {
default: undefined default: undefined
} }
}, },
data() {
return {
items: []
};
},
methods: { methods: {
onInput(event) { onInput(event) {
console.log(event.target.value);
this.$emit('update:modelValue', event.target.value); this.$emit('update:modelValue', event.target.value);
},
search(event) {
const query = event.query;
if (query.startsWith('{')) {
const tokenQuery = query.substring(1);
this.items = tokens.filter((t) => t.startsWith(tokenQuery));
} else {
this.items = [];
}
} }
}, },
computed: { computed: {

View File

@ -2,28 +2,22 @@
<Fieldset legend="Rounded" :toggleable="true"> <Fieldset legend="Rounded" :toggleable="true">
<section class="grid grid-cols-4 mb-3 gap-2"> <section class="grid grid-cols-4 mb-3 gap-2">
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">none</span> <DesignTokenField v-model="$preset.primitive.borderRadius.none" label="None" />
<input v-model="$preset.primitive.borderRadius.none" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">xs</span> <DesignTokenField v-model="$preset.primitive.borderRadius.xs" label="Extra Small" />
<input v-model="$preset.primitive.borderRadius.xs" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">sm</span> <DesignTokenField v-model="$preset.primitive.borderRadius.sm" label="Small" />
<input v-model="$preset.primitive.borderRadius.sm" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">md</span> <DesignTokenField v-model="$preset.primitive.borderRadius.md" label="Medium" />
<input v-model="$preset.primitive.borderRadius.md" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">lg</span> <DesignTokenField v-model="$preset.primitive.borderRadius.lg" label="Large" />
<input v-model="$preset.primitive.borderRadius.lg" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">xl</span> <DesignTokenField v-model="$preset.primitive.borderRadius.xl" label="Extra Large" />
<input v-model="$preset.primitive.borderRadius.xl" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
</section> </section>
</Fieldset> </Fieldset>

View File

@ -9,28 +9,22 @@
</section> </section>
<section class="grid grid-cols-4 mb-3 gap-2"> <section class="grid grid-cols-4 mb-3 gap-2">
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">Transition Duration</span> <DesignTokenField v-model="$preset.semantic.transitionDuration" label="Transition Duration" />
<input v-model="$preset.semantic.transitionDuration" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">Disabled Opacity</span> <DesignTokenField v-model="$preset.semantic.disabledOpacity" label="Disabled Opacity" />
<input v-model="$preset.semantic.disabledOpacity" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">Icon Size</span> <DesignTokenField v-model="$preset.semantic.iconSize" label="Icon Size" />
<input v-model="$preset.semantic.iconSize" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">Anchor Gutter</span> <DesignTokenField v-model="$preset.semantic.anchorGutter" label="Anchor Gutter" />
<input v-model="$preset.semantic.anchorGutter" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">Border Radius</span> <DesignTokenField v-model="$preset.semantic.content.borderRadius" label="Border Radius" />
<input v-model="$preset.semantic.content.borderRadius" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">Mask Transition Dur.</span> <DesignTokenField v-model="$preset.semantic.mask.transitionDuration" label="Mask Transition Dur." />
<input v-model="$preset.semantic.mask.transitionDuration" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"></div> <div class="flex flex-col gap-1"></div>
<div class="flex flex-col gap-1"></div> <div class="flex flex-col gap-1"></div>
@ -39,19 +33,16 @@
<div class="text-sm mb-1 font-semibold text-surface-950 dark:text-surface-0">Focus Ring</div> <div class="text-sm mb-1 font-semibold text-surface-950 dark:text-surface-0">Focus Ring</div>
<section class="grid grid-cols-4 gap-2"> <section class="grid grid-cols-4 gap-2">
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">Width</span> <DesignTokenField v-model="$preset.semantic.focusRing.width" label="Width" />
<input v-model="$preset.semantic.focusRing.width" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">Style</span> <DesignTokenField v-model="$preset.semantic.focusRing.style" label="Style" />
<input v-model="$preset.semantic.focusRing.style" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<DesignTokenField v-model="$preset.semantic.focusRing.color" label="Color" type="color" /> <DesignTokenField v-model="$preset.semantic.focusRing.color" label="Color" type="color" />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<span class="text-sm">Offset</span> <DesignTokenField v-model="$preset.semantic.focusRing.offset" label="Offset" />
<input v-model="$preset.semantic.focusRing.offset" type="text" class="border border-surface-300 dark:border-surface-600 rounded-lg p-2 w-full" />
</div> </div>
</section> </section>
</Fieldset> </Fieldset>