Skip to content

Commit 210f3f9

Browse files
committed
feat(react): wire up theme primaryColor in v0.9 basic catalog
Closes #977
1 parent 92b4c2d commit 210f3f9

File tree

8 files changed

+33
-14
lines changed

8 files changed

+33
-14
lines changed

renderers/react/src/v0_9/A2uiSurface.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,18 @@ DeferredChild.displayName = 'DeferredChild';
127127
export const A2uiSurface: React.FC<{surface: SurfaceModel<ReactComponentImplementation>}> = ({
128128
surface,
129129
}) => {
130+
const themeStyle = useMemo(() => {
131+
const style: Record<string, string> = {};
132+
if (surface.theme?.primaryColor) {
133+
style['--a2ui-primary-color'] = surface.theme.primaryColor;
134+
}
135+
return style;
136+
}, [surface.theme]);
137+
130138
// The root component always has ID 'root' and base path '/'
131-
return <DeferredChild surface={surface} id="root" basePath="/" />;
139+
return (
140+
<div style={themeStyle as React.CSSProperties}>
141+
<DeferredChild surface={surface} id="root" basePath="/" />
142+
</div>
143+
);
132144
};

renderers/react/src/v0_9/catalog/basic/components/Button.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import React from 'react';
1818
import {createReactComponent} from '../../../adapter';
1919
import {ButtonApi} from '@a2ui/web_core/v0_9/basic_catalog';
20-
import {LEAF_MARGIN} from '../utils';
20+
import {LEAF_MARGIN, PRIMARY_COLOR} from '../utils';
2121

2222
export const Button = createReactComponent(ButtonApi, ({props, buildChild}) => {
2323
const style: React.CSSProperties = {
@@ -27,7 +27,7 @@ export const Button = createReactComponent(ButtonApi, ({props, buildChild}) => {
2727
border: props.variant === 'borderless' ? 'none' : '1px solid #ccc',
2828
backgroundColor:
2929
props.variant === 'primary'
30-
? 'var(--a2ui-primary-color, #007bff)'
30+
? PRIMARY_COLOR
3131
: props.variant === 'borderless'
3232
? 'transparent'
3333
: '#fff',

renderers/react/src/v0_9/catalog/basic/components/CheckBox.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import React from 'react';
1818
import {createReactComponent} from '../../../adapter';
1919
import {CheckBoxApi} from '@a2ui/web_core/v0_9/basic_catalog';
20-
import {LEAF_MARGIN} from '../utils';
20+
import {LEAF_MARGIN, PRIMARY_COLOR} from '../utils';
2121

2222
export const CheckBox = createReactComponent(CheckBoxApi, ({props}) => {
2323
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -36,7 +36,7 @@ export const CheckBox = createReactComponent(CheckBoxApi, ({props}) => {
3636
type="checkbox"
3737
checked={!!props.value}
3838
onChange={onChange}
39-
style={{cursor: 'pointer', outline: hasError ? '1px solid red' : 'none'}}
39+
style={{cursor: 'pointer', outline: hasError ? '1px solid red' : 'none', accentColor: PRIMARY_COLOR}}
4040
/>
4141
{props.label && (
4242
<label

renderers/react/src/v0_9/catalog/basic/components/ChoicePicker.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import React, {useState} from 'react';
1818
import {createReactComponent} from '../../../adapter';
1919
import {ChoicePickerApi} from '@a2ui/web_core/v0_9/basic_catalog';
20-
import {LEAF_MARGIN, STANDARD_BORDER, STANDARD_RADIUS} from '../utils';
20+
import {LEAF_MARGIN, PRIMARY_COLOR, STANDARD_BORDER, STANDARD_RADIUS} from '../utils';
2121

2222
// The type of an option is deeply nested into the ChoicePickerApi schema, and
2323
// it seems z.infer is not inferring it correctly (?). We use `any` for now.
@@ -87,9 +87,9 @@ export const ChoicePicker = createReactComponent(ChoicePickerApi, ({props, conte
8787
padding: '4px 12px',
8888
borderRadius: '16px',
8989
border: isSelected
90-
? '1px solid var(--a2ui-primary-color, #007bff)'
90+
? `1px solid ${PRIMARY_COLOR}`
9191
: STANDARD_BORDER,
92-
backgroundColor: isSelected ? 'var(--a2ui-primary-color, #007bff)' : '#fff',
92+
backgroundColor: isSelected ? PRIMARY_COLOR : '#fff',
9393
color: isSelected ? '#fff' : 'inherit',
9494
cursor: 'pointer',
9595
fontSize: '12px',

renderers/react/src/v0_9/catalog/basic/components/Slider.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import React from 'react';
1818
import {createReactComponent} from '../../../adapter';
1919
import {SliderApi} from '@a2ui/web_core/v0_9/basic_catalog';
20-
import {LEAF_MARGIN} from '../utils';
20+
import {LEAF_MARGIN, PRIMARY_COLOR} from '../utils';
2121

2222
export const Slider = createReactComponent(SliderApi, ({props}) => {
2323
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -51,7 +51,7 @@ export const Slider = createReactComponent(SliderApi, ({props}) => {
5151
max={props.max}
5252
value={props.value ?? 0}
5353
onChange={onChange}
54-
style={{width: '100%', cursor: 'pointer'}}
54+
style={{width: '100%', cursor: 'pointer', accentColor: PRIMARY_COLOR}}
5555
/>
5656
</div>
5757
);

renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import {useState} from 'react';
1818
import {createReactComponent} from '../../../adapter';
1919
import {TabsApi} from '@a2ui/web_core/v0_9/basic_catalog';
20-
import {LEAF_MARGIN} from '../utils';
20+
import {LEAF_MARGIN, PRIMARY_COLOR} from '../utils';
2121

2222
// The type of a tab is deeply nested into the TabsApi schema, and
2323
// it seems z.infer is not inferring it correctly (?). We use `any` for now.
@@ -42,10 +42,10 @@ export const Tabs = createReactComponent(TabsApi, ({props, buildChild}) => {
4242
border: 'none',
4343
background: 'none',
4444
borderBottom:
45-
selectedIndex === i ? '2px solid var(--a2ui-primary-color, #007bff)' : 'none',
45+
selectedIndex === i ? `2px solid ${PRIMARY_COLOR}` : 'none',
4646
fontWeight: selectedIndex === i ? 'bold' : 'normal',
4747
cursor: 'pointer',
48-
color: selectedIndex === i ? 'var(--a2ui-primary-color, #007bff)' : 'inherit',
48+
color: selectedIndex === i ? PRIMARY_COLOR : 'inherit',
4949
}}
5050
>
5151
{tab.title}

renderers/react/src/v0_9/catalog/basic/components/TextField.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import React from 'react';
1818
import {createReactComponent} from '../../../adapter';
1919
import {TextFieldApi} from '@a2ui/web_core/v0_9/basic_catalog';
20-
import {LEAF_MARGIN, STANDARD_BORDER, STANDARD_RADIUS} from '../utils';
20+
import {LEAF_MARGIN, PRIMARY_COLOR, STANDARD_BORDER, STANDARD_RADIUS} from '../utils';
2121

2222
export const TextField = createReactComponent(TextFieldApi, ({props}) => {
2323
const onChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
@@ -34,6 +34,7 @@ export const TextField = createReactComponent(TextFieldApi, ({props}) => {
3434
border: STANDARD_BORDER,
3535
borderRadius: STANDARD_RADIUS,
3636
boxSizing: 'border-box',
37+
outlineColor: PRIMARY_COLOR,
3738
};
3839

3940
// Note: To have a unique id without passing context we can use a random or provided id,

renderers/react/src/v0_9/catalog/basic/utils.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ export const STANDARD_BORDER = '1px solid #ccc';
2828
/** Standard border radius. */
2929
export const STANDARD_RADIUS = '8px';
3030

31+
/** Default primary color, used as fallback when no theme is provided. */
32+
export const DEFAULT_PRIMARY_COLOR = '#007bff';
33+
34+
/** CSS value referencing the theme primary color with fallback. */
35+
export const PRIMARY_COLOR = `var(--a2ui-primary-color, ${DEFAULT_PRIMARY_COLOR})`;
36+
3137
export const mapJustify = (j?: string) => {
3238
switch (j) {
3339
case 'center':

0 commit comments

Comments
 (0)