Skip to content

fix: issue with default brand color #1678

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/studio/electron/main/assets/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Node, ObjectExpression } from '@babel/types';
import type { ColorUpdate } from '@onlook/models/assets';
import { DEFAULT_COLOR_NAME } from '@onlook/models/constants';
import fg from 'fast-glob';
import fs from 'fs';
import path from 'path';
Expand Down Expand Up @@ -122,7 +123,7 @@ export function addTailwindRootColor(
type: 'ObjectProperty',
key: {
type: 'Identifier',
name: 'DEFAULT',
name: DEFAULT_COLOR_NAME,
},
value: {
type: 'StringLiteral',
Expand Down
15 changes: 9 additions & 6 deletions apps/studio/electron/main/assets/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
} from '@onlook/models/assets';
import { Theme } from '@onlook/models/assets';
import type { CodeDiffRequest } from '@onlook/models/code';
import { DEFAULT_COLOR_NAME } from '@onlook/models/constants';
import { parseHslValue } from '@onlook/utility';
import fs from 'fs';
import { camelCase } from 'lodash';
Expand Down Expand Up @@ -54,7 +55,7 @@ export async function updateTailwindColorConfig(
return { success: true };
}

const camelCaseName = camelCase(newName);
const camelCaseName = newName === DEFAULT_COLOR_NAME ? newName : camelCase(newName);
return originalKey
? updateTailwindColorVariable(colorUpdate, originalKey, newColor, camelCaseName, theme)
: createTailwindColorVariable(colorUpdate, newColor, camelCaseName, parentName);
Expand Down Expand Up @@ -91,7 +92,7 @@ function addTailwindNestedColor(
type: 'ObjectProperty',
key: {
type: 'Identifier',
name: 'DEFAULT',
name: DEFAULT_COLOR_NAME,
},
value: {
type: 'StringLiteral',
Expand Down Expand Up @@ -226,11 +227,11 @@ function updateTailwindConfigFile(
) {
// Special handling for DEFAULT
const oldVarName =
nestedProp.key.name === 'DEFAULT'
nestedProp.key.name === DEFAULT_COLOR_NAME
? parentKey
: `${parentKey}-${nestedProp.key.name}`;
const newVarName =
nestedProp.key.name === 'DEFAULT'
nestedProp.key.name === DEFAULT_COLOR_NAME
? newName
: `${newName}-${nestedProp.key.name}`;

Expand Down Expand Up @@ -261,7 +262,9 @@ function updateTailwindConfigFile(
if (nestedProp.value.type === 'StringLiteral') {
// Special handling for DEFAULT values
const varName =
keyName === 'DEFAULT' ? parentKey : newCssVarName;
keyName === DEFAULT_COLOR_NAME
? parentKey
: newCssVarName;
nestedProp.value.value = `var(--${varName})`;
valueUpdated = true;
}
Expand Down Expand Up @@ -296,7 +299,7 @@ async function updateTailwindColorVariable(
newCssVarName = newName !== parentKey ? `${newName}` : originalName;
} else {
// Special handling for DEFAULT
if (keyName === 'DEFAULT') {
if (keyName === DEFAULT_COLOR_NAME) {
newCssVarName = parentKey;
originalName = parentKey;
} else {
Expand Down
12 changes: 6 additions & 6 deletions apps/studio/src/lib/editor/engine/theme/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ProjectsManager } from '@/lib/projects';
import { invokeMainChannel } from '@/lib/utils';
import type { ColorItem } from '@/routes/editor/LayersPanel/BrandTab/ColorPanel/ColorPalletGroup';
import { MainChannels } from '@onlook/models';
import { DEFAULT_COLOR_NAME, MainChannels } from '@onlook/models';
import type { ConfigResult, ParsedColors, ThemeColors } from '@onlook/models/assets';
import { Theme } from '@onlook/models/assets';
import { Color } from '@onlook/utility';
Expand Down Expand Up @@ -74,7 +74,7 @@ export class ThemeManager {
) {
processConfigObject(value, prefix ? `${prefix}-${key}` : key, key);

if ('DEFAULT' in value) {
if (DEFAULT_COLOR_NAME in value) {
const varName = extractVarName(value.DEFAULT as string);
if (varName) {
parsed[key] = {
Expand Down Expand Up @@ -182,7 +182,7 @@ export class ThemeManager {
ungroupedKeys.forEach((key) => {
colorGroupsObj[key] = [
{
name: 'DEFAULT',
name: DEFAULT_COLOR_NAME,
originalKey: `${key}-DEFAULT`,
lightColor: parsed[key].lightMode,
darkColor: parsed[key].darkMode,
Expand Down Expand Up @@ -230,7 +230,7 @@ export class ThemeManager {

// Create color items for each shade in the scale
const colorItems: ColorItem[] = Object.entries(defaultColorScale)
.filter(([shade]) => shade !== 'DEFAULT')
.filter(([shade]) => shade !== DEFAULT_COLOR_NAME)
.map(([shade, defaultValue]) => {
const lightModeValue = lightModeColors[`${colorName}-${shade}`]?.value;
const darkModeValue = darkModeColors[`${colorName}-${shade}`]?.value;
Expand Down Expand Up @@ -498,8 +498,8 @@ export class ThemeManager {

const brandGroup = this.brandColors[groupName];
if (brandGroup) {
if (!shadeName || shadeName === 'DEFAULT') {
const defaultColor = brandGroup.find((color) => color.name === 'DEFAULT');
if (!shadeName || shadeName === DEFAULT_COLOR_NAME) {
const defaultColor = brandGroup.find((color) => color.name === DEFAULT_COLOR_NAME);
if (defaultColor?.lightColor) {
return defaultColor.lightColor;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { useEditorEngine } from '@/components/Context';
import type { CompoundStyle, SingleStyle } from '@/lib/editor/styles/models';
import { invokeMainChannel } from '@/lib/utils';
import type { ColorItem } from '@/routes/editor/LayersPanel/BrandTab/ColorPanel/ColorPalletGroup';
import { MainChannels } from '@onlook/models/constants';
import { DEFAULT_COLOR_NAME, MainChannels } from '@onlook/models/constants';
import { Icons } from '@onlook/ui/icons';
import { Color, isColorEmpty } from '@onlook/utility';
import { observer } from 'mobx-react-lite';
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { PopoverPicker } from './Popover';
import { BrandPopoverPicker } from './ColorBrandPicker';

const stripUrlWrapper = (url: string) => {
return url.replace(/^url\((['"]?)(.*)\1\)/, '$2');
Expand Down Expand Up @@ -125,8 +125,8 @@ const ColorInput = observer(
onValueChange?.(elementStyle.key, valueString);
} else {
let colorValue = newValue.originalKey;
if (colorValue.endsWith('DEFAULT')) {
colorValue = colorValue.split('-DEFAULT')[0];
if (colorValue.endsWith(DEFAULT_COLOR_NAME)) {
colorValue = colorValue.split(`-${DEFAULT_COLOR_NAME}`)[0];
}
editorEngine.style.updateCustom(elementStyle.key, colorValue);
onValueChange?.(elementStyle.key, colorValue);
Expand Down Expand Up @@ -199,21 +199,22 @@ const ColorInput = observer(
};
return (
<div className="w-32 p-[6px] gap-2 flex flex-row rounded cursor-pointer bg-background-onlook/75">
{/* <BrandPopoverPicker
color={color}
onChange={sendStyleUpdate}
onChangeEnd={sendStyleUpdate}
backgroundImage={backgroundImage}
compoundStyle={compoundStyle}
/> */}

<PopoverPicker
<BrandPopoverPicker
color={color}
onChange={sendStyleUpdate}
onChangeEnd={sendStyleUpdate}
backgroundImage={backgroundImage}
compoundStyle={compoundStyle}
/>

{/* <PopoverPicker
color={color}
onChange={sendStyleUpdate}
onChangeEnd={sendStyleUpdate}
backgroundImage={backgroundImage}
compoundStyle={compoundStyle}
/> */}

<ColorTextInput
value={value}
isFocused={isFocused}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { useEditorEngine } from '@/components/Context';
import { invokeMainChannel } from '@/lib/utils';
import { Theme } from '@onlook/models/assets';
import { MainChannels } from '@onlook/models/constants';
import { Button } from '@onlook/ui/button';
import {
DropdownMenu,
Expand All @@ -6,14 +10,10 @@ import {
DropdownMenuTrigger,
} from '@onlook/ui/dropdown-menu';
import { Icons } from '@onlook/ui/icons';
import { Tooltip, TooltipContent, TooltipPortal, TooltipTrigger } from '@onlook/ui/tooltip';
import { Color, toNormalCase } from '@onlook/utility';
import { useState } from 'react';
import { ColorPopover } from './ColorPopover';
import { MainChannels } from '@onlook/models/constants';
import { invokeMainChannel } from '@/lib/utils';
import { useEditorEngine } from '@/components/Context';
import { Tooltip, TooltipContent, TooltipTrigger, TooltipPortal } from '@onlook/ui/tooltip';
import { Theme } from '@onlook/models/assets';

export interface ColorItem {
name: string;
Expand Down Expand Up @@ -284,7 +284,7 @@ export const BrandPalletGroup = ({
color.name,
)}
</span>
<span className="text-xs text-muted-foreground">
<span className="text-xs text-background-tertiary">
{getColorValue(color)}
</span>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { DEFAULT_COLOR_NAME } from '@onlook/models/constants';
import { Popover, PopoverContent, PopoverTrigger } from '@onlook/ui/popover';
import { Tooltip, TooltipContent, TooltipTrigger } from '@onlook/ui/tooltip';
import { cn } from '@onlook/ui/utils';
import { toNormalCase, type Color } from '@onlook/utility';
import { camelCase } from 'lodash';
import { useEffect, useState } from 'react';
Expand Down Expand Up @@ -33,7 +35,8 @@ export const ColorPopover = ({
}
};
const handleSave = () => {
const camelCaseName = camelCase(editedName);
const camelCaseName =
editedName === DEFAULT_COLOR_NAME ? editedName : camelCase(editedName);

if (existedName?.includes(camelCaseName) && camelCaseName !== brandColor) {
setError('Color name already exists');
Expand Down Expand Up @@ -74,15 +77,17 @@ export const ColorPopover = ({
setEditedName(e.target.value);
setError(null);
}}
className={`w-full rounded-md border ${
error ? 'border-red-500' : 'border-white/10'
} bg-background-secondary px-2 py-1 text-sm`}
disabled={isDefaultPalette || editedName === 'DEFAULT'}
className={cn(
'w-full rounded-md border bg-background-secondary px-2 py-1 text-sm',
error ? 'border-red-500' : 'border-white/10',
)}
disabled={isDefaultPalette || editedName === DEFAULT_COLOR_NAME}
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleSave();
}
}}
autoFocus
/>
</TooltipTrigger>
{error && (
Expand Down
2 changes: 1 addition & 1 deletion apps/studio/src/routes/editor/LayersPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export const LayersPanel = observer(() => {

<button
className={cn(
'w-16 h-16 rounded-xl flex flex-col items-center justify-center gap-1.5 p-2 hidden',
'w-16 h-16 rounded-xl flex flex-col items-center justify-center gap-1.5 p-2',
selectedTab === TabValue.BRAND && isLocked
? 'bg-accent text-foreground border-[0.5px] border-foreground/20'
: 'text-muted-foreground hover:text-foreground hover:bg-accent/50',
Expand Down
2 changes: 2 additions & 0 deletions packages/models/src/constants/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,5 @@ export const DefaultSettings = {
buildFlags: '--no-lint',
},
};

export const DEFAULT_COLOR_NAME = 'DEFAULT';
6 changes: 6 additions & 0 deletions packages/utility/src/string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ export function toNormalCase(str: string): string {
return str;
}

// Skip if the string is fully uppercase
if (str === str.toUpperCase()) {
return str;
}

// For other cases, convert camelCase/PascalCase to normal case

return str
.replace(/([A-Z])/g, ' $1')
.trim()
Expand Down