♾️ Harmony System
At the next lines I'll explain how the default system works and How you can create or extend your one of your own:
HARMONY_SYSTEM:
First of all, I would like you to think as:
- Flex:
<Piece kind='piece' />
Small parts of your screen, everything you want to organize into a container whatever the kind of them.
- Grid:
<Piece kind='container' />
Containers or your big parts of your screen where you want to organize your small parts (flex)
So everything that you need is a piece at other hand everything that you need
to organize our pieces is a container
Basic Grid:
const ContainerPattern = { order: 0, applyOn: (props: PieceProperties<any, any>) => props.kind === 'container', styles: { display: 'grid', flex: '1 1 auto', userSelect: 'none', }, }; const PiecePattern = { applyOn: (props) => props.kind === 'piece', order: 0, style: { display: 'flex', flex: '1 1 auto', userSelect: 'none', }, }; const Main = () => { return ( <PieceProvider patterns={[ContainerPattern, PiecePattern]}> <Piece kind='container' contentColumns='1fr 1fr' contentRows='1fr 1fr' > <Piece kind='piece' atRow={1} atColum={1} > Hello world. </Piece> <Piece kind='piece' atRow={2} atColum={2} > Hello world 2. </Piece> </Piece> </PieceProvider> ); }; render(<Main />);
Align Components
function Main() {
return (
<PieceProvider patterns={HARMONY_SYSTEM}>
<Piece
kind='container'
alignItems='end'
justifyContent='end'
>
<Piece
kind='piece'
alignSelf='start'
>
Hello world
</Piece>
<Piece kind='piece'>Hello world</Piece>
</Piece>
</PieceProvider>
);
}
Reset CSS
In the system offered we count with:
const RESET = {
applyOn: 'all',
order: 0,
style: {
margin: 0,
padding: 0,
border: 0,
fontSize: '100%',
fontWeight: '400',
fontStyle: 'normal',
boxSizing: 'border-box',
fontOpticalSizing: 'auto',
listStyle: 'none',
quotes: 'none',
userSelect: 'none',
overflow: 'hidden',
},
};
You'll probably ask why put overflow: hidden for all sort of component...
<Scrollable />
Something that always broke our navigation is definitely scrolls, when we want
to put it or not. For that reason I think the best solution at all is hide from
everything and show when you want to with: <Scrollable />.
Then everytime you want to render something that will grow more than your avaiable space, like lists:
- You can select the direction.
- Customize colors to match with your style.
- Animate: instant, smooth.
<PieceProvider theme={{ color: 'blue', highlight: 'orangeblue', }} patterns={mergeSystems(HARMONY_SYSTEM, { order: 0, applyOn: (props) => props.kind === 'scrollable', style: (theme) => ({ '--color': theme.color, '--highlight': theme.highlight, }), })} > <Piece kind='container' width='500px' > <Scrollable horizontal behavior='instant' //Optional > <Piece as='div' flex='0 0 350px' height='50px' background='green' ></Piece> <Piece as='div' flex='0 0 350px' height='50px' background='blue' ></Piece> </Scrollable> </Piece> </PieceProvider>
<Text />
Basic with this component you can use a text and align in all directions with
flex props:
<Text
as='p'
justifyContent='center'
alignItems='center'
>
Centered
</Text>
<Media />
Sometimes you want to hide some component at some screen size:
<Media query='(min-height: 702px)'>
<Piece>Hello world</Piece>
</Media>
Now you only will see it at screens bigger than 702px.
However the element will remain at your HTML if you don't want to:
<Media
query='(min-height: 702px)'
removeFromHtml
>
<Piece>Hello world</Piece>
</Media>
And if you want to be notified when the element will be activate
<Media
query='(min-height: 702px)'
removeFromHtml
onActivate={myFunction}
>
<Piece>Hello world</Piece>
</Media>
Creating your system
You can create your own:
const PIECE = { applyOn: (props) => props.kind === 'piece', order: 0, style: { display: 'block', userSelect: 'none', }, }; const LIST = { applyOn: 'ul', order: 0, style: { listStyle: 'square inside', paddingLeft: '20px', }, }; const LIST_ITEM = { applyOn: 'li', order: 0, style: { color: 'orange', lineHeight: 1.8, }, }; const MyCustomCssSystem = [PIECE, LIST, LIST_ITEM]; const Main = () => { return ( <PieceProvider patterns={MyCustomCssSystem}> <Piece as='ul'> <Piece as='li'>Item 1</Piece> </Piece> </PieceProvider> ); }; render(<Main />);
But if you want to use <Scrollable /> and other components designed for
you should extend from the main system:
Compounding Systems
You can merge more than one system adding your styles to the main
HARMONY_SYSTEM by importing mergeSystems look:
interface CustomTheme {
color: string;
highlight: string;
}
export const MyCustomCssSystem = mergeSystems<CustomTheme>(
HARMONY_SYSTEM,
{
applyOn: (props) => props.kind === 'scrollable',
style: ({ theme }) => ({
'--color': theme.color,
'--highlight': theme.highlight,
}),
order: 0,
},
{
applyOn: 'all',
style: {
transition: 'all 0.3s linear',
},
order: 0,
},
);
Default Properties
You're a totally able to set default properties in that schema
import { Piece, PieceProvider } from '@lizzelabs/react-harmony';
import { ReactNode } from 'react';
export interface ContainerProps {
children: ReactNode;
}
const Container = (props: ContainerProps) => {
return <Piece as='div'>{props.children}</Piece>;
};
const Main = () => {
return (
<PieceProvider
patterns={{
applyOn: 'div',
defaults: {
aria: {
'aria-hidden': true,
},
},
}}
>
<Container>
<Piece as='label'>Hello World</Piece>
</Container>
</PieceProvider>
);
};
// Now the container will be hidded from screen readers
Reference
Property | ||
|---|---|---|
applyOn | Applies the rule on. | (props: PieceProperties) => boolean HTML Tags ex: span, ul, div all |
Order | Priority of that style | number |
Style | Css | object |
Defaults | Default properties of a piece | object |