Wrapping components
The tag property
Intergalactic components are built with polymorphic typings, that means that you can provide tag property that will redefine allowed properties list.
import Button from '@semcore/ui/button';
<Button
href="">
// Error: Property 'href' does not exist on type... //
Hello world
</Button><Button
tag="a"
href="">
Hello world
</Button>tag property also accepts React components and other Intergalactic components what allows you to easley combine logic of visual appearance of both components.
import { LinkTrigger } from '@semcore/ui/base-trigger';
import { Box } from '@semcore/ui/flex-box';
import Select from '@semcore/ui/select';
import { Text } from '@semcore/ui/typography';
import React from 'react';
const options = Array(6)
.fill('')
.map((_, index) => ({ value: index, children: `Option ${index}` }));
const Demo = () => (
<>
<Box mb={2}>
<Text size={200} tag='label' htmlFor='select-linktrigger'>
Select merged with LinkTrigger
</Text>
</Box>
<Select tag={LinkTrigger} options={options} id='select-linktrigger' />
</>
);
export default Demo;
The tag property is not included in the component's props, so you can't make wrappers by simple using that.
import Select, { SelectProps } from '@semcore/ui/select'
const WrappedSelect = ({
tag, // Property tag does not exist on type SelectProps.
...other
}: SelectProps) => (
<Select {...other} />
)Making wrappers
Use the special utility wrapIntergalacticComponent to wrap components. It does nothing in runtime but ensures correct typings in TypeScript.
import Button from '@semcore/ui/button';
import { wrapIntergalacticComponent } from '@semcore/ui/core';
import React from 'react';
const AlertButton = wrapIntergalacticComponent<
typeof Button,
{
handle: ('click' | 'hover')[];
message: string;
}
>(({ handle, message, ...restProps }) => {
const handleClick = () => {
if (handle.includes('click')) {
alert(message);
}
};
const handleMouseOver = () => {
if (handle.includes('hover')) {
alert(message);
}
};
return <Button {...restProps} onClick={handleClick} onMouseOver={handleMouseOver} />;
});
const Demo = () => (
<AlertButton handle={['click']} message='Hello world'>
Show alert
</AlertButton>
);
export default Demo;
Complex wrappers
Some components props are generic, for example Select component has generic value and DataTable has generic data. For such components, special wrapping utilities are provided.
It available for the following components:
wrapDataTable,wrapDataTableRow,wrapDataTableCellfor DataTable.wrapAccordionfor Accordion.wrapPillsfor Pills.wrapRadioGroupfor Radio.wrapSelectfor Select.wrapSliderfor Slider.wrapTabLinefor TabLine.wrapTabPanelfor TabPanel.wrapWizardStepperfor Wizard.
import Card from '@semcore/ui/card';
import { DataTable, wrapDataTable } from '@semcore/ui/data-table';
import React from 'react';
const CardDataTable = wrapDataTable<{ title: string }>(({ title, ...restProps }) => {
return (
<Card>
<Card.Header>
<Card.Title>{title}</Card.Title>
</Card.Header>
<Card.Body px={0}>
<DataTable {...restProps} aria-label='Table title' />
</Card.Body>
</Card>
);
});
const Demo = () => {
return (
<CardDataTable
data={data}
title='A table combined with card'
columns={[
{ name: 'keyword', children: 'Keyword' },
{ name: 'kd', children: 'KD,%' },
{ name: 'cpc', children: 'CPC' },
{ name: 'vol', children: 'Vol.' },
]}
/>
);
};
const data = [
{
keyword: 'ebay buy',
kd: '77.8',
cpc: '$1.25',
vol: '32,500,000',
},
{
keyword: 'www.ebay.com',
kd: '11.2',
cpc: '$3.4',
vol: '65,457,920',
},
{
keyword: 'www.ebay.com',
kd: '10',
cpc: '$0.65',
vol: '47,354,640',
},
];
export default Demo;