Other · ConfigProvider

ConfigProvider

Provide a unified global configuration for components.

Scenes to be used

Coverage configuration is divided into two scenarios

  • When you need to override the public Props configuration of multiple components (such as timezone, rtl), use ConfigProvider
  • When the ConfigProvider props are not enough and you want to modify a certain type of Props of a certain component globally (for example, set the theme of all Buttons to solid, or the position of all Popovers), use semiGlobal

ConfigProvider

ConfigProvider is built on context, so it affects the child components in the JSX tree. ConfigProvider and ConfigConsumer render no element of their own (a div carrying dir is added only when the direction changes), and undeclared attributes (class, style, ref and native attributes) are discarded, so they never reach the DOM.

Demos

How to import

import { ConfigProvider, ConfigConsumer, useConfig } from '@fibrous/semi-ui-solid';

Basic Usage

By passing in the timeZone parameter, users can configure the time zone for the time components:

Select Time Zone:




Code
import { For, createSignal } from 'solid-js';
import { ConfigProvider, Select, DatePicker, TimePicker } from '@fibrous/semi-ui-solid';

const defaultTimestamp = 1581599305265;

// Fractional offsets are written as fixed GMT strings; an IANA name is kept because it follows daylight saving time
const gmtList = [
    ...Array.from({ length: 26 }, (_, index) => {
        const hourOffset = index - 11;
        const prefix = hourOffset >= 0 ? '+' : '-';
        return `GMT${prefix}${String(Math.abs(hourOffset)).padStart(2, '0')}:00`;
    }),
    'GMT-03:30',
    'GMT+05:45',
    'GMT+13:45',
    'America/New_York',
];

export default function ConfigProviderDemo() {
    const [timeZone, setTimeZone] = createSignal('GMT+08:00');

    return (
        <ConfigProvider timeZone={timeZone()}>
            <div style={{ width: '300px' }}>
                <h5 style={{ margin: '10px' }}>Select Time Zone:</h5>
                <Select aria-label="时区" placeholder="请选择时区" style={{ width: '300px' }} value={timeZone()} showClear onSelect={(value) => setTimeZone(String(value))}>
                    <For each={gmtList}>{(gmt) => <Select.Option value={gmt}>{gmt}</Select.Option>}</For>
                </Select>
                <br />
                <br />
                <DatePicker type="dateTime" defaultValue={defaultTimestamp} onChange={(date, dateString) => console.log('DatePicker changed: ', date, dateString)} />
                <br />
                <br />
                <TimePicker defaultValue={defaultTimestamp} onChange={(date, dateString) => console.log('DatePicker changed: ', date, dateString)} />
            </div>
        </ConfigProvider>
    );
}

Manually obtain values

Usually, the value of ConfigProvider is automatically obtained and consumed within the component, so you don't need to worry about it. However, in some special scenarios, you may need to manually obtain the value to perform other operations.

Use the children function of ConfigConsumer to obtain the value of ConfigProvider. The function runs only once, so read fields as config.xxx instead of destructuring them. In a child component you can also call useConfig(), which returns Accessor<ContextValue>; call the accessor (config()) to read the current value, and it is an empty object without a ConfigProvider.

{"direction":"ltr","timeZone":"GMT+08:00","responsiveObserve":false,"responsiveMap":{"xs":"(max-width: 575px)","sm":"(min-width: 576px)","md":"(min-width: 768px)","lg":"(min-width: 992px)","xl":"(min-width: 1200px)","xxl":"(min-width: 1600px)"},"screens":{"xs":false,"sm":false,"md":false,"lg":false,"xl":false,"xxl":false}}
Code
import { ConfigProvider, ConfigConsumer, Typography } from '@fibrous/semi-ui-solid';

export default function ConfigProviderDemo() {
    return (
        <ConfigProvider timeZone="GMT+08:00">
            {/*...*/}
            <ConfigConsumer>
                {(value) => (
                    <Typography.Text ellipsis={{ showTooltip: { opts: { style: { 'min-width': '1200px' } } } }} style={{ width: '600px' }}>
                        {JSON.stringify(value)}
                    </Typography.Text>
                )}
            </ConfigConsumer>
            {/*...*/}
        </ConfigProvider>
    );
}

Responsive breakpoints

ConfigProvider supports responsive breakpoint configuration and subscriptions to breakpoint changes.

Enable observing & custom breakpoints

  • Use responsiveObserve to enable breakpoint observing (recommended only when you really need subscriptions)
  • Use responsiveMap to customize breakpoints (falls back to default map when not provided)
import { createSignal, onCleanup, onMount } from 'solid-js';
import { ConfigProvider, ConfigConsumer, Typography } from '@fibrous/semi-ui-solid';

function BreakpointSubscriber(props) {
    const [screens, setScreens] = createSignal(props.screens);

    onMount(() => {
        const unsubscribe = props.onBreakpoint?.((next) => setScreens(next));
        onCleanup(() => unsubscribe?.());
    });

    return <Typography.Text>{JSON.stringify(screens())}</Typography.Text>;
}

function Demo() {
    return (
        <ConfigProvider
            responsiveObserve
            responsiveMap={{
                xs: '(max-width: 575px)',
                sm: '(min-width: 576px)',
                md: '(min-width: 768px)',
                lg: '(min-width: 992px)',
                xl: '(min-width: 1200px)',
                xxl: '(min-width: 1600px)',
            }}
        >
            <ConfigConsumer>{(config) => <BreakpointSubscriber onBreakpoint={config.onBreakpoint} screens={config.screens} />}</ConfigConsumer>
        </ConfigProvider>
    );
}

Subscription API

onBreakpoint supports two overloads (both return an unsubscribe function):

  • onBreakpoint((screens) => void): callback receives the full screens map
  • onBreakpoint(['md', 'lg'], (screen, match) => void): listen to specific breakpoints only

RTL/LTR

Global configuration direction can change the text direction of components. rtl means right to left (similar to Hebrew or Arabic), ltr means left to right (similar to most languages such as English). When an explicitly passed direction differs from the outer one, including at the outermost level, ConfigProvider wraps its content in a div carrying the dir attribute. The RTL styles of components match :dir(rtl) and follow the nearest ancestor dir attribute; popup roots carry a dir from the ConfigProvider direction. When the page sets dir="rtl" itself, for example on <html>, components in the page look RTL, but their logic such as arrow-key direction and popup placement only reads the ConfigProvider direction, and popups and Table inside a ConfigProvider follow its direction (ltr by default), so set direction="rtl" as well.

Special components:

  • Command call of Modal, Notification and Toast needs to be passed to 'direction' through prop.
  • If you want to internationalize the directional icon, you need to handle it on your own. We think RTL for icon will make it difficult to understand and maintain. Semi has adapted the icons in other components.
  • The tree data of Table does not support RTL (Chrome, Safari have different behave with Firefox), and fixed column supports RTL.

Imperative calls (Modal.success(), Toast.info() and the like) render outside the ConfigProvider and cannot read its direction. To follow the direction, pass direction in the options, or use Modal.useModal(), Toast.useToast() and Notification.useNotification(), which inherit the ConfigProvider wherever their returned Holder component is rendered.

Buttons



Input





Prefix


Suffix


0/100


多选框
禁用的多选框
禁用的多选框










Navigation




Finished
This is a description.
2
In Progress
This is a description.
3
Waiting
This is a description.

Finished
This is a description
In Process
This is a description
3
Waiting
This is a description

Display

XZ5
YB5
LX5
YZ
HW
XM

grey tag
blue tag
ghost tag
solid tag
red tag
green tag
orange tag
teal tag
violet tag
white tag

I am Popover
I am Tooltip

  • 审核中
    2019-07-14 10:35
  • 发布成功
    2019-06-13 16:17
  • 审核失败
    2019-05-14 18:34

Feedback





I am loading...

Here are some texts.

And more texts on the way.

Code
import { createSignal, type JSX } from 'solid-js';
import { Dynamic } from 'solid-js/web';
import { IconCamera, IconChevronDown, IconEdit, IconList, IconSidebar, IconVigoLogo } from '@fibrous/semi-icons-solid';
import { ConfigProvider, ButtonGroup, Button, Row, Col, Notification, DatePicker, TimePicker, Timeline, Popover, Tag, Tooltip, Badge, Avatar, Steps, Pagination, Modal, Breadcrumb, Rating, Nav, Spin, Cascader, Radio, Select, Input, Typography, TextArea, Checkbox, Switch, Toast } from '@fibrous/semi-ui-solid';

const flexStyle: JSX.CSSProperties = { display: 'flex', 'margin-bottom': '32px', 'flex-wrap': 'wrap' };
const titleStyle: JSX.CSSProperties = { margin: '50px 0 16px 0' };
const rowStyle: JSX.CSSProperties = { margin: '16px 10px' };
const badgeStyle: JSX.CSSProperties = {
    width: '42px',
    height: '42px',
    'border-radius': '4px',
    display: 'inline-block',
};
const tagStyle: JSX.CSSProperties = { 'margin-right': '8px', 'margin-bottom': '8px' };
const buttonStyle: JSX.CSSProperties = { ...tagStyle };

const treeData = [
    {
        label: '浙江省',
        value: 'zhejiang',
        children: [
            {
                label: '杭州市',
                value: 'hangzhou',
                children: [
                    { label: '西湖区', value: 'xihu' },
                    { label: '萧山区', value: 'xiaoshan' },
                    { label: '临安区', value: 'linan' },
                ],
            },
            {
                label: '宁波市',
                value: 'ningbo',
                children: [
                    { label: '海曙区', value: 'haishu' },
                    { label: '江北区', value: 'jiangbei' },
                ],
            },
        ],
    },
];

export default function ConfigProviderDemo() {
    const [direction, setDirection] = createSignal<'ltr' | 'rtl'>();
    // Read at each call so a notification shows the direction selected at the time it is opened
    const opts = () => ({
        title: 'Hi,Bytedance',
        content: 'ies dance dance dance',
        duration: 3,
        direction: direction(),
    });
    const navItems = [
        { itemKey: 'user', text: 'Option1' },
        { itemKey: 'union', text: 'Option2' },
        {
            itemKey: 'approve-management',
            text: 'Group3',
            items: ['3-1', '3-2'],
        },
    ];
    const navIcons: Record<string, typeof IconEdit> = { user: IconEdit, union: IconCamera, 'approve-management': IconList };

    return (
        <div>
            <div style={{ 'margin-bottom': '20px' }}>
                <ButtonGroup>
                    <Button onClick={() => setDirection('ltr')}>LTR</Button>
                    <Button onClick={() => setDirection('rtl')}>RTL</Button>
                </ButtonGroup>
            </div>
            <ConfigProvider direction={direction()}>
                <Row>
                    <h3 style={titleStyle}>Buttons</h3>
                </Row>
                <Row style={rowStyle}>
                    <Button loading theme="solid" style={{ 'margin-right': '8px' }}>
                        加载
                    </Button>
                    <Button icon={<IconSidebar />} theme="solid" style={{ 'margin-right': '8px' }}>
                        收起
                    </Button>
                    <Button icon={<IconChevronDown />} theme="solid" iconPosition="right" style={{ 'margin-right': '8px' }}>
                        展开选项
                    </Button>
                    <br />
                    <br />
                    <ButtonGroup>
                        <Button>拷贝</Button>
                        <Button>查询</Button>
                        <Button>剪切</Button>
                    </ButtonGroup>
                </Row>
                <Row>
                    <h3 style={titleStyle}>Input</h3>
                </Row>
                <Row style={rowStyle} gutter={16}>
                    <Col span={12}>
                        <Input aria-label="输入框" placeholder="输入框" />
                        <br />
                        <br />
                        <Input aria-label="禁用的输入框" disabled placeholder="输入框" />
                        <br />
                        <br />
                        <Input aria-label="带前缀的输入框" prefix="Prefix" showClear />
                        <br />
                        <br />
                        <Input
                            aria-label="带后缀的输入框"
                            suffix={
                                <Typography.Text strong type="secondary" style={{ margin: '0 8px' }}>
                                    Suffix
                                </Typography.Text>
                            }
                            showClear
                        />
                        <br />
                        <br />
                        <TextArea aria-label="文本框" placeholder="文本框" maxCount={100} />
                        <br />
                        <br />
                        <div style={flexStyle}>
                            <Switch aria-label="已开启的开关" style={{ 'margin-right': '8px' }} defaultChecked />
                            <Switch aria-label="已关闭的开关" style={{ 'margin-right': '8px' }} />
                            <Switch aria-label="禁用的开关" disabled defaultChecked style={{ 'margin-right': '8px' }} />
                        </div>
                        <div style={flexStyle}>
                            <Checkbox style={{ 'margin-right': '8px' }} defaultChecked>
                                多选框
                            </Checkbox>
                            <Checkbox style={{ 'margin-right': '8px' }} disabled defaultChecked>
                                禁用的多选框
                            </Checkbox>
                            <Checkbox style={{ 'margin-right': '8px' }} disabled>
                                禁用的多选框
                            </Checkbox>
                        </div>
                        <div style={{ ...flexStyle, 'margin-bottom': '0' }}>
                            <Radio style={{ 'margin-right': '8px' }} defaultChecked>
                                单选框
                            </Radio>
                            <Radio style={{ 'margin-right': '8px' }} disabled defaultChecked>
                                禁用的单选框
                            </Radio>
                            <Radio style={{ 'margin-right': '8px' }} disabled>
                                禁用的单选框
                            </Radio>
                        </div>
                    </Col>
                    <Col span={12}>
                        <DatePicker onChange={(_date, dateString) => console.log(dateString)} style={{ width: '100%' }} />
                        <br />
                        <br />
                        <TimePicker style={{ width: '100%' }} />
                        <br />
                        <br />
                        <Select aria-label="选择器-单选" style={{ width: '100%' }} placeholder="选择器-单选">
                            <Select.Option value="abc">抖音</Select.Option>
                            <Select.Option value="hotsoon">火山</Select.Option>
                            <Select.Option value="pipixia" disabled>
                                皮皮虾
                            </Select.Option>
                            <Select.Option value="xigua">西瓜视频</Select.Option>
                        </Select>
                        <br />
                        <br />
                        <Select aria-label="选择器-禁用" disabled style={{ width: '100%' }} placeholder="选择器-禁用">
                            <Select.Option value="abc">抖音</Select.Option>
                            <Select.Option value="hotsoon">火山</Select.Option>
                            <Select.Option value="pipixia" disabled>
                                皮皮虾
                            </Select.Option>
                            <Select.Option value="xigua">西瓜视频</Select.Option>
                        </Select>
                        <br />
                        <br />
                        <Select aria-label="选择器-多选" multiple style={{ width: '100%' }} placeholder="选择器-多选">
                            <Select.Option value="abc">抖音</Select.Option>
                            <Select.Option value="hotsoon">火山</Select.Option>
                            <Select.Option value="pipixia" disabled>
                                皮皮虾
                            </Select.Option>
                            <Select.Option value="xigua">西瓜视频</Select.Option>
                        </Select>
                        <br />
                        <br />
                        <Cascader style={{ width: '100%' }} treeData={treeData} placeholder="级联选择器" />
                    </Col>
                </Row>
                <Row>
                    <h3 style={titleStyle}>Navigation</h3>
                </Row>
                <Row style={rowStyle}>
                    <Breadcrumb>
                        <Breadcrumb.Item>Semi-ui</Breadcrumb.Item>
                        <Breadcrumb.Item>Breadcrumb</Breadcrumb.Item>
                        <Breadcrumb.Item>Default</Breadcrumb.Item>
                    </Breadcrumb>
                    <Nav mode="horizontal" items={navItems} renderItemIcon={({ item }) => <Dynamic component={navIcons[String(item.itemKey)]} />} />
                    <br />
                    <br />
                    <Pagination total={80} showSizeChanger />
                    <br />
                    <Steps current={1}>
                        <Steps.Step title="Finished" description="This is a description." />
                        <Steps.Step title="In Progress" description="This is a description." />
                        <Steps.Step title="Waiting" description="This is a description." />
                    </Steps>
                    <br />
                    <Steps current={1} status="error">
                        <Steps.Step title="Finished" description="This is a description" />
                        <Steps.Step title="In Process" description="This is a description" />
                        <Steps.Step title="Waiting" description="This is a description" />
                    </Steps>
                </Row>
                <Row>
                    <h3 style={titleStyle}>Display</h3>
                </Row>
                <Row style={rowStyle}>
                    <div style={{ display: 'flex' }}>
                        <div style={{ padding: '8px' }}>
                            <Badge count={5} theme="solid">
                                <Avatar color="blue" shape="square" style={badgeStyle}>
                                    XZ
                                </Avatar>
                            </Badge>
                        </div>
                        <div style={{ padding: '8px' }}>
                            <Badge count={5} theme="light">
                                <Avatar color="cyan" shape="square" style={badgeStyle}>
                                    YB
                                </Avatar>
                            </Badge>
                        </div>
                        <div style={{ padding: '8px' }}>
                            <Badge count={5} theme="inverted">
                                <Avatar color="indigo" shape="square" style={badgeStyle}>
                                    LX
                                </Avatar>
                            </Badge>
                        </div>
                        <div style={{ padding: '8px' }}>
                            <Badge dot theme="solid">
                                <Avatar color="light-blue" shape="square" style={badgeStyle}>
                                    YZ
                                </Avatar>
                            </Badge>
                        </div>
                        <div style={{ padding: '8px' }}>
                            <Badge dot theme="light">
                                <Avatar color="teal" shape="square" style={badgeStyle}>
                                    HW
                                </Avatar>
                            </Badge>
                        </div>
                        <div style={{ padding: '8px', 'border-radius': '4px', 'background-color': 'var(--semi-color-fill-0)' }}>
                            <Badge dot theme="inverted">
                                <Avatar color="green" shape="square" style={badgeStyle}>
                                    XM
                                </Avatar>
                            </Badge>
                        </div>
                    </div>
                    <br />
                    <div>
                        <Tag color="grey" style={tagStyle}>
                            grey tag
                        </Tag>
                        <Tag color="blue" style={tagStyle}>
                            blue tag
                        </Tag>
                        <Tag color="blue" type="ghost" style={tagStyle}>
                            ghost tag
                        </Tag>
                        <Tag color="blue" type="solid" style={tagStyle}>
                            solid tag
                        </Tag>
                        <Tag color="red" style={tagStyle}>
                            red tag
                        </Tag>
                        <Tag color="green" style={tagStyle}>
                            green tag
                        </Tag>
                        <Tag color="orange" style={tagStyle}>
                            orange tag
                        </Tag>
                        <Tag color="teal" style={tagStyle}>
                            teal tag
                        </Tag>
                        <Tag color="violet" style={tagStyle}>
                            violet tag
                        </Tag>
                        <Tag color="white" style={tagStyle}>
                            white tag
                        </Tag>
                    </div>
                    <br />
                    <div style={{ display: 'flex', 'align-items': 'center' }}>
                        <Popover content="hi semi-design" style={{ padding: '8px' }}>
                            {(trigger) => (
                                <Tag {...trigger()} style={{ 'margin-right': '8px' }}>
                                    I am Popover
                                </Tag>
                            )}
                        </Popover>
                        <Tooltip content="hi semi-design">
                            {(trigger) => (
                                <Tag {...trigger()} style={{ 'margin-right': '8px' }}>
                                    I am Tooltip
                                </Tag>
                            )}
                        </Tooltip>
                        <Rating defaultValue={3} size="small" style={{ 'margin-right': '8px' }} />
                    </div>
                    <br />
                    <Timeline>
                        <Timeline.Item time="2019-07-14 10:35" type="ongoing">
                            审核中
                        </Timeline.Item>
                        <Timeline.Item time="2019-06-13 16:17" type="success">
                            发布成功
                        </Timeline.Item>
                        <Timeline.Item time="2019-05-14 18:34" type="error">
                            审核失败
                        </Timeline.Item>
                    </Timeline>
                </Row>
                <Row>
                    <h3 style={titleStyle}>Feedback</h3>
                </Row>
                <Row style={rowStyle}>
                    <Button type="primary" onClick={() => Notification.success(opts())} style={buttonStyle}>
                        成功信息的通知
                    </Button>
                    <Button onClick={() => Notification.info(opts())} style={buttonStyle}>
                        提示信息的通知
                    </Button>
                    <Button type="warning" onClick={() => Notification.warning(opts())} style={buttonStyle}>
                        警告信息的通知
                    </Button>
                    <Button type="danger" onClick={() => Notification.error(opts())} style={buttonStyle}>
                        失败信息的通知
                    </Button>
                    <Button style={buttonStyle} aria-label="Vigo 图标通知" icon={<IconVigoLogo />} onClick={() => Notification.info({ ...opts(), icon: <IconVigoLogo /> })} />
                    <Button style={buttonStyle} aria-label="粉色 Vigo 图标通知" icon={<IconVigoLogo />} onClick={() => Notification.info({ ...opts(), icon: <IconVigoLogo style={{ color: 'pink' }} /> })} />
                    <br />
                    <Button type="primary" onClick={() => Modal.success(opts())} style={buttonStyle}>
                        成功信息的弹窗
                    </Button>
                    <Button onClick={() => Modal.info(opts())} style={buttonStyle}>
                        提示信息的弹窗
                    </Button>
                    <Button type="warning" onClick={() => Modal.warning(opts())} style={buttonStyle}>
                        警告信息的弹窗
                    </Button>
                    <Button type="danger" onClick={() => Modal.error(opts())} style={buttonStyle}>
                        失败信息的弹窗
                    </Button>
                    <br />
                    <Button type="primary" onClick={() => Toast.success(opts())} style={buttonStyle}>
                        成功信息的提示
                    </Button>
                    <Button onClick={() => Toast.info(opts())} style={buttonStyle}>
                        提示信息的提示
                    </Button>
                    <Button type="warning" onClick={() => Toast.warning(opts())} style={buttonStyle}>
                        警告信息的提示
                    </Button>
                    <Button type="danger" onClick={() => Toast.error(opts())} style={buttonStyle}>
                        失败信息的提示
                    </Button>
                    <br />
                    <br />
                    <Spin tip="I am loading...">
                        <div
                            style={{
                                'background-color': 'var(--semi-color-primary-light-default)',
                                border: '1px solid var(--semi-color-primary)',
                                'border-radius': '4px',
                                padding: '16px 10px',
                            }}
                        >
                            <p>Here are some texts.</p>
                            <p>And more texts on the way.</p>
                        </div>
                    </Spin>
                </Row>
            </ConfigProvider>
        </div>
    );
}

Nesting

ConfigProvider can be nested. The inner one overrides only the props it is given; props it does not pass (direction, locale, timeZone, getPopupContainer, responsiveObserve, responsiveMap) are inherited from the outer one. A prop set to undefined counts as not passed; locale={null} is explicit, so it clears the outer locale and leaves it to the LocaleProvider inside, or the default language.

An inner direction="ltr" switches a subtree inside an rtl ConfigProvider back to left to right, for both the logic and the styles of its components.

外层:locale = en-US,timeZone = Asia/Tokyo,direction = ltr
内层只传 timeZone,其余继承外层:locale = en-US,timeZone = 8,direction = ltr
Code
import en_US from '@fibrous/semi-foundation/locale/source/en_US';
import { ConfigProvider, ConfigConsumer } from '@fibrous/semi-ui-solid';

function ConfigSummary(props: { title: string }) {
    return (
        <ConfigConsumer>
            {(config) => (
                <div style={{ margin: '8px' }}>
                    {props.title}:locale = {config.locale?.code ?? '未设置'},timeZone = {String(config.timeZone)},direction = {config.direction}
                </div>
            )}
        </ConfigConsumer>
    );
}

export default function ConfigProviderDemo() {
    return (
        <ConfigProvider locale={en_US} timeZone="Asia/Tokyo" direction="ltr">
            <ConfigSummary title="外层" />
            <ConfigProvider timeZone={8}>
                <ConfigSummary title="内层只传 timeZone,其余继承外层" />
            </ConfigProvider>
        </ConfigProvider>
    );
}

API Reference

ConfigProvider

Props

PropertyDescriptionTypeDefault
childrenContent affected by the configuration. When an explicitly passed direction differs from the outer one, including at the outermost level, the content is wrapped in a div carrying the dir attribute.JSX.Element-
directionText direction: ltr or rtl. Inherited from the outer ConfigProvider when omitted, and ltr at the outermost level.'ltr' | 'rtl'-
getPopupContainerFunction returning the popup container. It only affects Modal, SideSheet and ImagePreview, which still render through a Portal; the container needs position: relative. Inherited from the outer ConfigProvider when omitted, and document.body at the outermost level.Type() => HTMLElement-
localeLocale configuration, which takes precedence over LocaleProvider. Inherited from the outer ConfigProvider when omitted; when no ConfigProvider sets it, LocaleProvider decides, and zh_CN is used without either. Pass null to clear the outer locale.Locale | null-
responsiveMapCustom responsive breakpoints: keys are xs, sm, md, lg, xl and xxl, values are media query strings. Compared by content, so an inline object does not re-register listeners. Inherited from the outer ConfigProvider when omitted, and defaultResponsiveMap at the outermost level.ResponsiveMap-
responsiveObserveWhether to observe responsive breakpoints. When off, no matchMedia listener is registered; when on, listeners are registered on the first subscription and removed when none remain. Inherited from the outer ConfigProvider when omitted, and false at the outermost level.boolean-
timeZoneTime zone for time components: a number (hour offset from UTC), a GMT±HH:MM string or an IANA identifier. Numbers and GMT strings are fixed offsets all year. Inherited from the outer ConfigProvider when omitted.string | number-

ConfigProvider.defaultResponsiveMap and the named export defaultResponsiveMap are the default breakpoint map. locale works like the locale parameter of LocaleProvider, see its usage. ConfigProvider does not accept class, style, ref or native attributes, and they do not land on the DOM.

ConfigConsumer

Props

PropertyDescriptionTypeDefault
childrenFunction child receiving the effective configuration (ContextValue). Inside a ConfigProvider it also holds screens and onBreakpoint; without a ConfigProvider it is an empty object. The function runs once, so read fields in JSX as config.xxx instead of destructuring them.Type(config: ContextValue) => JSX.Element-

ConfigConsumer renders no element either, so undeclared attributes are discarded.

useConfig

useConfig(): Accessor<ContextValue> returns an accessor of the effective configuration; call it to read the value, and it is an empty object without a ConfigProvider. ContextValue holds direction, timeZone, locale, getPopupContainer, responsiveObserve and responsiveMap from the table above, plus the read-only screens (which breakpoints match) and onBreakpoint (the subscribe function, see "Subscription API" above).

Time Zone Identifier

  • Numbers, such as 1,-9.5, represent the time offset from UTC, the unit is hour, and it can be negative or decimal;
  • A string, such as "GMT-09:30","GMT+08:00", which is a characterization offset string starting with "GMT", or IANA, such as "Asia/Shanghai","America/Los_Angeles", etc.

A number or a string like GMT-09:30 is a fixed offset all year round and never shifts for daylight saving time. For example, -3.5 and GMT-03:30 are UTC-03:30 in every season, and the time zone name (z) in a format shows GMT-03:30.

To follow the daylight saving time of a region, use an IANA identifier. Here you can check the IANA list, and whether the time zone has daylight saving time.

FAQ

  • The ConfigProvider does not provide the function of global custom prefix classname. How to achieve similar requirements (for example, Semi is used in the SDK, and it is expected that the packaged dom style does not have the .semi-xx prefix, so as not to be affected by the host's global CSS)?
    • Since prefixCls needs to be consumed by the js/css of the component layer at the same time, Semi put this switch in the configuration item of webpack plugin, rather than as a configuration item of ConfigProvider.
    • If you use webpack, please configure it in the parameters of SemiWebpackPlugin
# webpack config example: webpack.config.js
const SemiWebpackPlugin = require('@fibrous/semi-webpack-plugin').default;
module.exports = {
+    plugins: [new SemiWebpackPlugin({ prefixCls: 'imes' })],
}

semiGlobal

You can override the default Props of global components.

In semiGlobal.config.overrideDefaultProps you can configure the component default Props. A component reads the global configuration once when it is created, so changes made afterwards do not update components that already exist. Set it before the application mounts, at the entrance of the entire site. A DOM node in the defaults is discarded with a warning, because one node can only be attached in one place and every instance would move it into itself; strings and icon components take effect as usual.

Properties that are unique to each instance, such as id, insetLabelId, wrapperId, addonId and extraId, cannot be set through the global defaults: the types have no such keys, and they are ignored at runtime.

For example, the configuration below sets all Buttons to warning by default, and filter of Select to enabled by default, etc.

import { semiGlobal } from '@fibrous/semi-ui-solid';

semiGlobal.config.overrideDefaultProps = {
    Button: {
        type: 'warning',
    },
    Select: {
        filter: true,
    },
    Tooltip: {
        trigger: 'click',
    },
};