Skip to content
Open
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
214 changes: 191 additions & 23 deletions packages/base/brand-guide.gts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
import ColorField from './color';
import {
BasicFitted,
CopyButton,
Swatch,
Button,
FieldContainer,
Expand Down Expand Up @@ -103,7 +104,11 @@ class BrandGuideIsolated extends Component<typeof BrandGuide> {
/>
<GridContainer class='brand-guide-grid'>
{{#each this.sectionsWithContent as |section|}}
<NavSection @id={{section.id}} @title={{section.title}}>
<NavSection
@id={{section.id}}
@title={{section.title}}
data-test-brand-guide-section={{section.id}}
>
{{#if (eq section.id 'brand-palette')}}
<GridContainer>
{{#if @model.brandColorPalette.length}}
Expand Down Expand Up @@ -363,28 +368,50 @@ class BrandGuideIsolated extends Component<typeof BrandGuide> {
<code>--brand-secondary-mark-min-height</code>)</dd>
</dl>
</div>
{{#if @model.brandColorPalette.length}}
<h3 class='brand-guide-vars-heading'>Brand-Specific
Variables</h3>
<p class='brand-guide-vars-description'>These variables are
custom css properties for usage by the specific brand.</p>
<div class='brand-guide-vars-box'>
<h4 class='brand-guide-vars-title'>Custom Brand Variables</h4>
<p class='brand-guide-vars-description'>Additional brand
colors as defined in the Brand Color Palette.</p>
<dl class='brand-guide-vars'>
{{#each @model.brandColorPalette as |color|}}
{{#if color.name}}
<dt><code>{{buildCssVariableName
color.name
}}</code></dt>
<dd>Custom brand color</dd>
{{/if}}
{{/each}}
</dl>
</div>
{{/if}}
{{/if}}
{{else if (eq section.id 'custom-css')}}
<p class='brand-guide-vars-description'>These variables are
custom css properties for usage by this theme only.</p>
<div class='brand-guide-vars-box brand-guide-custom-css-block'>
<CopyButton
class='brand-guide-custom-css-block-copy-button'
@textToCopy={{this.customCssVarsBlock}}
/>
<dl class='brand-guide-vars'>
{{#each this.paletteVarEntries as |entry|}}
<dt class='var-row' data-test-brand-guide-palette-var>
<code
data-test-brand-guide-palette-var-name
>{{entry.varName}}</code>
</dt>
<dd
class='color-entry var-row'
data-test-brand-guide-palette-swatch
>
<Swatch
class='color-swatch-mini'
@color={{entry.color.value}}
@style='round'
/>
</dd>
{{/each}}
{{#each @model.customCssVariables as |cssVar|}}
{{#if cssVar.name}}
<dt class='var-row' data-test-brand-guide-css-var>
<code
data-test-brand-guide-css-var-name
>{{buildCssVariableName cssVar.name}}</code>
</dt>
Comment thread
burieberry marked this conversation as resolved.
<dd class='var-row'>
<code
class='css-var-value'
data-test-brand-guide-css-var-value
>{{cssVar.value}}</code>
</dd>
{{/if}}
Comment on lines +398 to +411
{{/each}}
</dl>
</div>
{{else if (eq section.id 'import-css')}}
<CssFieldEditor @setCss={{@model.setCss}} />
{{else if (eq section.id 'inspirations')}}
Expand Down Expand Up @@ -412,6 +439,10 @@ class BrandGuideIsolated extends Component<typeof BrandGuide> {
--brand-guide-border: 1px solid var(--dsr-border);
--brand-guide-spacing: var(--boxel-sp-xl);
--boxel-container-padding: var(--brand-guide-spacing);
/* Pin tooltip colors so brand theme vars don't bleed into the overlay */
--boxel-tooltip-background-color: rgb(0 0 0 / 85%);
--boxel-tooltip-text-color: var(--boxel-light, #fff);
--boxel-tooltip-border-color: transparent;
}
.brand-guide-dashboard-header {
position: relative;
Expand Down Expand Up @@ -680,7 +711,34 @@ class BrandGuideIsolated extends Component<typeof BrandGuide> {
font-size: 0.9em;
}

/* Import Custom CSS */
/* Custom CSS / color variables section */
.brand-guide-custom-css-block {
position: relative;
}
.brand-guide-custom-css-block-copy-button {
position: absolute;
top: var(--boxel-sp-xs);
right: var(--boxel-sp-xs);
}
.var-row {
display: flex;
align-items: center;
gap: var(--boxel-sp-xs);
}
.color-entry {
display: flex;
align-items: center;
}
.css-var-value {
font-family: var(
--font-mono,
var(--boxel-monospace-font-family, monospace)
);
font-size: 0.9em;
color: var(--dsr-muted-fg);
}

/* Import CSS */
.css-textarea {
--boxel-input-height: 19rem;
}
Expand Down Expand Up @@ -769,6 +827,11 @@ class BrandGuideIsolated extends Component<typeof BrandGuide> {
navTitle: 'Brand Palette',
title: 'Brand Palette',
},
{
id: 'custom-css',
navTitle: 'Custom CSS',
title: 'Custom CSS Variables',
},
{
id: 'typography',
navTitle: 'Typography',
Expand Down Expand Up @@ -801,6 +864,10 @@ class BrandGuideIsolated extends Component<typeof BrandGuide> {
return Boolean(this.args.model.cssVariables);
}

if (section.id === 'custom-css') {
return this.hasCustomVariables;
}

if (section.id === 'brand-palette') {
return this.hasBrandPaletteContent;
}
Expand Down Expand Up @@ -834,6 +901,51 @@ class BrandGuideIsolated extends Component<typeof BrandGuide> {
);
}

private get paletteVarEntries() {
if (!entriesToCssRuleMap || !this.args.model?.brandColorPalette?.length) {
return [];
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let paletteRules = entriesToCssRuleMap(
this.args.model.brandColorPalette as any,
);
return this.args.model.brandColorPalette
.filter((color) => color.name)
.map((color) => ({
color,
varName: buildCssVariableName(color.name!),
colorValue: paletteRules.get(color.name!) ?? '',
Comment on lines +913 to +917
}));
}

private get customCssVarsBlock() {
let lines: string[] = [];
if (entriesToCssRuleMap && this.args.model?.brandColorPalette?.length) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let paletteRules = entriesToCssRuleMap(
this.args.model.brandColorPalette as any,
);
for (let [name, colorValue] of paletteRules.entries()) {
lines.push(`${buildCssVariableName(name)}: ${colorValue};`);
}
}
for (let cssVar of this.args.model?.customCssVariables ?? []) {
let name = cssVar.name?.trim();
let value = cssVar.value?.trim();
if (name && value) {
lines.push(`${buildCssVariableName(name)}: ${value};`);
}
Comment on lines +932 to +937
}
return lines.join('\n');
}

private get hasCustomVariables() {
return Boolean(
this.args.model?.brandColorPalette?.length ||
this.args.model?.customCssVariables?.length,
);
}

private get hasVisualDNAContent() {
let model = this.args.model;
if (!model) {
Expand Down Expand Up @@ -878,6 +990,52 @@ export class CompoundColorField extends FieldDef {
</style>
</template>
};

static edit = class Edit extends Component<typeof this> {
<template>
<div class='compound-color-edit'>
<FieldContainer @label='Name' @vertical={{true}}>
<@fields.name />
</FieldContainer>
<FieldContainer @label='Color' @vertical={{true}}>
<@fields.value />
</FieldContainer>
</div>
<style scoped>
.compound-color-edit {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--boxel-sp-sm);
}
</style>
</template>
};
}

export class CustomCssVariable extends FieldDef {
static displayName = 'Custom CSS Variable';
@field name = contains(StringField);
@field value = contains(StringField);

static edit = class Edit extends Component<typeof this> {
<template>
<div class='custom-css-variable-edit'>
<FieldContainer @label='Variable Name' @vertical={{true}}>
<@fields.name />
</FieldContainer>
<FieldContainer @label='Value' @vertical={{true}}>
<@fields.value />
</FieldContainer>
</div>
<style scoped>
.custom-css-variable-edit {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--boxel-sp-sm);
}
</style>
</template>
};
}

export default class BrandGuide extends DetailedStyleRef {
Expand Down Expand Up @@ -929,6 +1087,15 @@ export default class BrandGuide extends DetailedStyleRef {
}
}

// add custom CSS variables
for (let cssVar of this.customCssVariables ?? []) {
let name = cssVar.name?.trim();
let value = cssVar.value?.trim();
if (!name || !value) continue;
let varName = buildCssVariableName(name);
if (!brandRules.has(varName)) brandRules.set(varName, value);
}

if (!brandRules.size) {
return;
}
Expand Down Expand Up @@ -995,6 +1162,7 @@ export default class BrandGuide extends DetailedStyleRef {
}

@field brandColorPalette = containsMany(CompoundColorField);
@field customCssVariables = containsMany(CustomCssVariable);
@field functionalPalette = contains(BrandFunctionalPalette);
@field typography = contains(ThemeTypographyField);
@field markUsage = contains(BrandLogo);
Expand Down
2 changes: 1 addition & 1 deletion packages/base/structured-theme.gts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const GUIDE_SECTIONS = [
{
id: 'import-css',
navTitle: 'Import CSS',
title: 'Import Custom CSS',
title: 'Import CSS',
fieldName: null,
Comment on lines 51 to 55
},
{
Expand Down
Loading
Loading