Compare commits

...

14 Commits

Author SHA1 Message Date
徐涛
3f2e655b1c build: 添加上传脚本
- 新增 upload 脚本文件
- 使用 rsync 命令将 dist 目录内容同步到 archgrid.net 服务器的 /var/www/color-lab/ 目录
2025-07-31 08:14:12 +08:00
徐涛
ae37903673 feat(color): 调整 QStyle2 基准配色方案
- 修改 outline_color、outline_variant_color 和 overlay_color 的生成逻辑
- 优化暗黑和明亮主题下的颜色选择
- 简化颜色计算公式,提高代码可读性
2025-07-31 08:12:57 +08:00
徐涛
d88eebe356 feat(color): 调整中性色 swatch 的倍率以适应新的颜色方案
- 调整了 neutral_swatch.get 方法中的倍率参数
- 针对暗黑模式和普通模式分别设置了不同的倍率值
- 修改了 outline_color 和 outline_variant_color 的生成逻辑
2025-07-31 06:06:48 +08:00
徐涛
f6ff4b10e6 fix(color-module): 修正surface变量的命名格式
统一surface变量的命名格式,在CSS、SCSS和JavaScript中使用一致的命名规则
2025-07-28 06:08:42 +08:00
徐涛
1e4a9fd858 feat(颜色方案): 增加中性色板生成功能
- 在`baseline.rs`中添加新的CSS变量生成逻辑
- 在`swatch.rs`中添加`generate_neutral_swatch_list`函数
- 优化danger、success、warn和info的CSS变量生成
- 修复CSS变量生成中的拼写错误
- 更新JavaScript字段生成逻辑
2025-07-23 06:35:36 +08:00
徐涛
034f12c99b fix: 将自定义颜色名称转换为小写以保持一致性 2025-07-21 22:37:47 +08:00
徐涛
61ff3eff5c fix(swatch): 修正颜色样本键名前缀格式 2025-07-21 22:33:59 +08:00
徐涛
3bed5a97c5 fix(scheme): 修复预览组件中可选颜色单元的条件渲染 2025-07-21 22:24:51 +08:00
徐涛
ab4af06fd1 refactor(Preview): 对自定义颜色键进行排序以提高一致性 2025-07-20 11:17:27 +08:00
徐涛
ec93cd5678 fix(Preview): 修正阴影和覆盖层的文本颜色为中性变体 2025-07-20 11:02:35 +08:00
徐涛
38b11dcd85 refactor(Builder.tsx): 移除调试用的console.log语句 2025-07-20 09:57:12 +08:00
徐涛
0d9c11b4fb fix(组件): 修正ContextMenu中Q2SchemeSource的类型引用 2025-07-20 09:02:40 +08:00
徐涛
d6fba55f3d fix(组件): 将上下文菜单中的警告颜色参数从'warning'改为'warn' 2025-07-20 09:02:08 +08:00
徐涛
58be84c499 refactor(q-2-scheme): 将neutral和surface类型改为Q2ColorSet并更新相关引用
更新Q2Baseline类型中的neutral、neutralVariant、surface和surfaceVariant字段类型为Q2ColorSet
调整Preview组件中相关属性的引用方式
修复SchemeDetail组件中Q2Scheme的props类型
2025-07-20 09:00:30 +08:00
8 changed files with 113 additions and 40 deletions

View File

@@ -12,7 +12,10 @@ use crate::{
errors,
schemes::{
q_style::{ColorExpand, NeutralSwatch, SchemeSetting},
q_style_2::{color_set::ColorSet, swatch::Swatch},
q_style_2::{
color_set::ColorSet,
swatch::{Swatch, generate_neutral_swatch_list},
},
},
};
@@ -46,7 +49,10 @@ impl ColorUnit {
let mut css_variables = Vec::new();
css_variables.extend(self.root.to_css_variables(prefix, name));
css_variables.extend(self.surface.to_css_variables(prefix, name));
css_variables.extend(
self.surface
.to_css_variables(prefix, &format!("{name}-surface")),
);
css_variables.extend(self.swatch.to_css_variables(prefix, name));
css_variables
@@ -56,7 +62,10 @@ impl ColorUnit {
let mut css_auto_scheme_collection = LinkedHashMap::new();
css_auto_scheme_collection.extend(self.root.to_css_auto_scheme_collection(name));
css_auto_scheme_collection.extend(self.surface.to_css_auto_scheme_collection(name));
css_auto_scheme_collection.extend(
self.surface
.to_css_auto_scheme_collection(&format!("{name}-surface")),
);
css_auto_scheme_collection.extend(self.swatch.to_css_auto_scheme_collection(name));
css_auto_scheme_collection
@@ -66,7 +75,10 @@ impl ColorUnit {
let mut scss_variables = Vec::new();
scss_variables.extend(self.root.to_scss_variables(prefix, name));
scss_variables.extend(self.surface.to_scss_variables(prefix, name));
scss_variables.extend(
self.surface
.to_scss_variables(prefix, &format!("{name}-surface")),
);
scss_variables.extend(self.swatch.to_scss_variables(prefix, name));
scss_variables
@@ -76,7 +88,7 @@ impl ColorUnit {
let mut js_object_fields = Vec::new();
js_object_fields.extend(self.root.to_javascript_fields(name));
js_object_fields.extend(self.surface.to_javascript_fields(name));
js_object_fields.extend(self.surface.to_javascript_fields(&format!("{name}Surface")));
js_object_fields.extend(self.swatch.to_javascript_fields(name));
js_object_fields
@@ -195,13 +207,10 @@ impl Baseline {
neutral_lightest.l
};
let neutral_swatch = Arc::new(NeutralSwatch::new(*neutral_lightest, *neutral_darkest));
let outline_color =
neutral_swatch.get(neutral_lightest.l * if is_dark { 0.5 } else { 0.7 });
let outline_variant_color =
neutral_swatch.get(neutral_lightest.l * if is_dark { 0.3 } else { 0.8 });
let outline_color = neutral_swatch.get(if is_dark { 0.25 } else { 0.7 });
let outline_variant_color = neutral_swatch.get(if is_dark { 0.2 } else { 0.8 });
let shadow_color = neutral_swatch.get(0.1);
let overlay_color =
neutral_swatch.get(neutral_lightest.l * if is_dark { 0.4 } else { 0.5 });
let overlay_color = neutral_swatch.get(0.3);
let neutral_color = neutral_swatch.get(if is_dark { 0.35 } else { 0.65 });
let neutral_variant_color = neutral_swatch.get(if is_dark { 0.45 } else { 0.55 });
@@ -301,6 +310,11 @@ impl Baseline {
if let Some(accent) = &self.accent {
css_variables.extend(accent.to_css_variables(scheme_mode, "accent"));
}
css_variables.extend(self.danger.to_css_variables(scheme_mode, "danger"));
css_variables.extend(self.success.to_css_variables(scheme_mode, "success"));
css_variables.extend(self.warn.to_css_variables(scheme_mode, "warn"));
css_variables.extend(self.info.to_css_variables(scheme_mode, "info"));
css_variables.extend(self.neutral.to_css_variables(scheme_mode, "neutral"));
css_variables.extend(
self.neutral_variant
@@ -311,10 +325,11 @@ impl Baseline {
self.surface_variant
.to_css_variables(scheme_mode, "surface-variant"),
);
css_variables.extend(self.danger.to_css_variables(scheme_mode, "danger"));
css_variables.extend(self.success.to_css_variables(scheme_mode, "success"));
css_variables.extend(self.warn.to_css_variables(scheme_mode, "warn"));
css_variables.extend(self.info.to_css_variables(scheme_mode, "info"));
let neutral_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
for (n, c) in neutral_swatch {
css_variables.push(format!("--color-{scheme_mode}-swatch-neutral-{n}: #{c};"));
}
css_variables.push(format!(
"--color-{scheme_mode}-shadow: #{};",
@@ -334,7 +349,8 @@ impl Baseline {
));
for (name, color_unit) in &self.custom_colors {
css_variables.extend(color_unit.to_css_variables(scheme_mode, name));
let lowercased_name = name.to_lowercase();
css_variables.extend(color_unit.to_css_variables(scheme_mode, &lowercased_name));
}
css_variables
@@ -353,6 +369,10 @@ impl Baseline {
if let Some(accent) = &self.accent {
css_variables.extend(accent.to_css_auto_scheme_collection("accent"));
}
css_variables.extend(self.danger.to_css_auto_scheme_collection("danger"));
css_variables.extend(self.success.to_css_auto_scheme_collection("success"));
css_variables.extend(self.warn.to_css_auto_scheme_collection("warn"));
css_variables.extend(self.info.to_css_auto_scheme_collection("info"));
css_variables.extend(self.neutral.to_css_auto_scheme_collection("neutral"));
css_variables.extend(
self.neutral_variant
@@ -364,6 +384,11 @@ impl Baseline {
.to_css_auto_scheme_collection("surface-variant"),
);
let neutral_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
for (n, c) in neutral_swatch {
css_variables.insert(format!("swatch-neutral-{n}"), c);
}
css_variables.insert("shadow".to_string(), map_oklch_to_srgb_hex(&self.shadow));
css_variables.insert("overlay".to_string(), map_oklch_to_srgb_hex(&self.overlay));
css_variables.insert("outline".to_string(), map_oklch_to_srgb_hex(&self.outline));
@@ -373,7 +398,8 @@ impl Baseline {
);
for (name, color) in &self.custom_colors {
css_variables.extend(color.to_css_auto_scheme_collection(name));
let lowercased_name = name.to_lowercase();
css_variables.extend(color.to_css_auto_scheme_collection(&lowercased_name));
}
css_variables
@@ -393,6 +419,10 @@ impl Baseline {
if let Some(accent) = &self.accent {
scss_variables.extend(accent.to_scss_variables(scheme_mode, "accent"));
}
scss_variables.extend(self.danger.to_scss_variables(scheme_mode, "danger"));
scss_variables.extend(self.success.to_scss_variables(scheme_mode, "success"));
scss_variables.extend(self.warn.to_scss_variables(scheme_mode, "warn"));
scss_variables.extend(self.info.to_scss_variables(scheme_mode, "info"));
scss_variables.extend(self.neutral.to_scss_variables(scheme_mode, "neutral"));
scss_variables.extend(
@@ -405,23 +435,33 @@ impl Baseline {
.to_scss_variables(scheme_mode, "surface-variant"),
);
let neutral_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
for (n, c) in neutral_swatch {
scss_variables.push(format!("$color-{scheme_mode}-swatch-neutral-{n}: #{c};"));
}
scss_variables.push(format!(
"--color-{scheme_mode}-shadow: #{};",
"$color-{scheme_mode}-shadow: #{};",
map_oklch_to_srgb_hex(&self.shadow)
));
scss_variables.push(format!(
"--color-{scheme_mode}-overlay: #{};",
"$color-{scheme_mode}-overlay: #{};",
map_oklch_to_srgb_hex(&self.overlay)
));
scss_variables.push(format!(
"--color-{scheme_mode}-outlint: #{};",
"$color-{scheme_mode}-outlint: #{};",
map_oklch_to_srgb_hex(&self.outline)
));
scss_variables.push(format!(
"--color-{scheme_mode}-outline-variant: #{};",
"$color-{scheme_mode}-outline-variant: #{};",
map_oklch_to_srgb_hex(&self.outline_variant)
));
for (name, color) in &self.custom_colors {
let lowercased_name = name.to_lowercase();
scss_variables.extend(color.to_scss_variables(scheme_mode, &lowercased_name));
}
scss_variables
}
@@ -463,6 +503,18 @@ impl Baseline {
javascript_fields.push(format!("{indent}{line:4}"));
}
for line in self.danger.to_javascript_fields("danger").iter() {
javascript_fields.push(format!("{indent}{line:4}"));
}
for line in self.success.to_javascript_fields("success").iter() {
javascript_fields.push(format!("{indent}{line:4}"));
}
for line in self.warn.to_javascript_fields("warn").iter() {
javascript_fields.push(format!("{indent}{line:4}"));
}
for line in self.info.to_javascript_fields("info").iter() {
javascript_fields.push(format!("{indent}{line:4}"));
}
for line in self.neutral.to_javascript_fields("neutral").iter() {
javascript_fields.push(format!("{indent}{line:4}"));
}
@@ -484,6 +536,11 @@ impl Baseline {
javascript_fields.push(format!("{indent}{line:4}"));
}
let neurtal_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
for (n, c) in neurtal_swatch {
javascript_fields.push(format!("{indent}neutralSwatch{n}: '#{c}',"));
}
javascript_fields.push(format!(
"{indent}shadow: '#{}',",
map_oklch_to_srgb_hex(&self.shadow)
@@ -502,7 +559,8 @@ impl Baseline {
));
for (name, color) in &self.custom_colors {
let color_lines = color.to_javascript_fields(name);
let lowercased_name = name.to_lowercase();
let color_lines = color.to_javascript_fields(&lowercased_name);
javascript_fields.extend(color_lines.iter().map(|s| format!("{indent}{s}")));
}

View File

@@ -51,7 +51,7 @@ impl Swatch {
let mut collection = LinkedHashMap::new();
for l in SWATCH_LIGHTINGS {
collection.insert(format!("{name}-{l:02}"), self.get_hex(l));
collection.insert(format!("swatch-{name}-{l:02}"), self.get_hex(l));
}
collection
@@ -98,6 +98,19 @@ impl Serialize for Swatch {
}
}
pub fn generate_neutral_swatch_list(swatch: &Arc<NeutralSwatch>) -> LinkedHashMap<String, String> {
let swatch = swatch.clone();
let mut collection = LinkedHashMap::new();
for l in SWATCH_LIGHTINGS {
let color = swatch.get((l as f32) / 100.0);
let color = map_oklch_to_srgb_hex(&color);
collection.insert(format!("{l:02}"), color);
}
collection
}
pub fn serialize_neutral_swatch<S>(
swatch: &Arc<NeutralSwatch>,
serailizer: S,

View File

@@ -107,7 +107,7 @@ const Q2SchemeMenu: FC<ContextMenuBodyProps> = ({ color, afterClick }) => {
const activeSchemeId = useAtomValue(activeSchemeAtom);
const updateScheme = useUpdateScheme(activeSchemeId);
const updateSchemeContent = useCallback(
(content: keyof QSchemeSource) => {
(content: keyof Q2SchemeSource) => {
updateScheme((prev) => {
prev.schemeStorage.source[content] = color;
return prev;
@@ -156,7 +156,7 @@ const Q2SchemeMenu: FC<ContextMenuBodyProps> = ({ color, afterClick }) => {
<div className={styles.menu_item} onClick={() => updateSchemeContent('success')}>
Set as Success color
</div>
<div className={styles.menu_item} onClick={() => updateSchemeContent('warning')}>
<div className={styles.menu_item} onClick={() => updateSchemeContent('warn')}>
Set as Warn color
</div>
<div className={styles.menu_item} onClick={() => updateSchemeContent('info')}>

View File

@@ -8,6 +8,7 @@ import { ScrollArea } from '../../../components/ScrollArea';
import { VSegmentedControl } from '../../../components/VSegmentedControl';
import { SchemeContent } from '../../../models';
import { Q2SchemeSource, Q2SchemeStorage } from '../../../q-2-scheme';
import { QSchemeSetting } from '../../../q-scheme';
import { useUpdateScheme } from '../../../stores/schemes';
import { isNilOrEmpty, mapToObject } from '../../../utls';
import { ColorEntry, IdenticalColorEntry } from '../ColorEntry';
@@ -202,7 +203,6 @@ export function Q2SchemeBuilder({ scheme, onBuildCompleted }: Q2SchemeBuilderPro
try {
const [source, settings] = collectSchemeSource(formData);
console.log('[Collected form data]', source, settings);
const generatedScheme = colorFn?.generate_q_scheme_2_manually(
source.primary ?? '',
isEmpty(source.secondary) ? undefined : source.secondary,

View File

@@ -107,7 +107,7 @@ interface PreviewBlockProps {
const PreviewBlock: FC<PreviewBlockProps> = ({ baseline, title }) => {
const customSets = useMemo(() => {
const colors = keys(baseline.customColors);
const colors = keys(baseline.customColors).sort();
const elements: ReactNode[] = [];
for (const key of colors) {
@@ -122,9 +122,9 @@ const PreviewBlock: FC<PreviewBlockProps> = ({ baseline, title }) => {
<div className={styles.preview_block} style={{ backgroundColor: `#${baseline.surface.root}` }}>
<h2 style={{ color: `#${baseline.surface.onRoot}` }}>{title}</h2>
<PreviewSet name="Primary" colorUnit={baseline.primary} />
<PreviewSet name="Secondary" colorUnit={baseline.secondary} />
<PreviewSet name="Tertiary" colorUnit={baseline.tertiary} />
<PreviewSet name="Accent" colorUnit={baseline.accent} />
{baseline.secondary && <PreviewSet name="Secondary" colorUnit={baseline.secondary} />}
{baseline.tertiary && <PreviewSet name="Tertiary" colorUnit={baseline.tertiary} />}
{baseline.accent && <PreviewSet name="Accent" colorUnit={baseline.accent} />}
<PreviewSet name="Danger" colorUnit={baseline.danger} />
<PreviewSet name="Success" colorUnit={baseline.success} />
<PreviewSet name="Warn" colorUnit={baseline.warn} />
@@ -134,16 +134,16 @@ const PreviewBlock: FC<PreviewBlockProps> = ({ baseline, title }) => {
<PreviewLine name="Surface" unit={baseline.surface} />
<PreviewLine name="Surface Variant" unit={baseline.surfaceVariant} />
<div className={styles.preview_indi_block}>
<PreviewCell bg={baseline.shadow} fg={baseline.surface.root.onRoot}>
<PreviewCell bg={baseline.shadow} fg={baseline.neutralVariant.onRoot}>
Shadow
</PreviewCell>
<PreviewCell bg={baseline.overlay} fg={baseline.surface.root.onRoot}>
<PreviewCell bg={baseline.overlay} fg={baseline.neutralVariant.onRoot}>
Overlay
</PreviewCell>
<PreviewCell bg={baseline.outline} fg={baseline.surface.root.onRoot}>
<PreviewCell bg={baseline.outline} fg={baseline.surface.onRoot}>
Outline
</PreviewCell>
<PreviewCell bg={baseline.outlineVariant} fg={baseline.surface.root.onRoot}>
<PreviewCell bg={baseline.outlineVariant} fg={baseline.surface.onRoot}>
Outline Variant
</PreviewCell>
</div>

View File

@@ -18,7 +18,7 @@ import { M3Scheme } from '../page-components/scheme/M3Scheme';
import { Q2Scheme } from '../page-components/scheme/Q2Scheme';
import { QScheme } from '../page-components/scheme/QScheme';
import { SwatchScheme } from '../page-components/scheme/SwatchScheme';
import { Q2SchemeSource } from '../q-2-scheme';
import { Q2SchemeStorage } from '../q-2-scheme';
import { QSchemeStorage } from '../q-scheme';
import { useScheme, useUpdateScheme } from '../stores/schemes';
import { SwatchSchemeStorage } from '../swatch_scheme';
@@ -53,7 +53,7 @@ export function SchemeDetail() {
case 'q_scheme':
return <QScheme scheme={scheme as SchemeContent<QSchemeStorage>} />;
case 'q_2_scheme':
return <Q2Scheme scheme={scheme as SchemeContent<Q2SchemeSource>} />;
return <Q2Scheme scheme={scheme as SchemeContent<Q2SchemeStorage>} />;
case 'swatch_scheme':
return <SwatchScheme scheme={scheme as SchemeContent<SwatchSchemeStorage>} />;
case 'material_2':

View File

@@ -21,10 +21,10 @@ export type Q2Baseline = {
secondary: Q2ColorUnit | null;
tertiary: Q2ColorUnit | null;
accent: Q2ColorUnit | null;
neutral: Q2ColorUnit;
neutralVariant: Q2ColorUnit;
surface: Q2ColorUnit;
surfaceVariant: Q2ColorUnit;
neutral: Q2ColorSet;
neutralVariant: Q2ColorSet;
surface: Q2ColorSet;
surfaceVariant: Q2ColorSet;
neutralSwatch: Record<string, string>;
danger: Q2ColorUnit;
success: Q2ColorUnit;

2
upload Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
rsync -rzvPh ./dist/ archgrid.net:/var/www/color-lab/