Skip to content

Commit

Permalink
feat: states feature
Browse files Browse the repository at this point in the history
  • Loading branch information
andreaSimonePorceddu authored and Mauro Erta committed Nov 30, 2022
1 parent 2e47628 commit 835510b
Show file tree
Hide file tree
Showing 32 changed files with 429 additions and 45 deletions.
188 changes: 164 additions & 24 deletions docs/docs/ThemeSpecification/components.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,23 @@ description: Components theme slice
### Structure

```typescript
type ComponentConfig = ComponentStyle<Props> & {
type ComponentConfig = ComponentStyle<Props, State> & {
tag?: string;
style: Style;
props?: Props;
meta?: ComponentMeta;
states: {
[key in State]: Style
}
variants: {
[key: string]: {
tag?: string;
style: Style;
props?: Props;
meta?: ComponentMeta;
states: {
[key in State]: Style
}
};
};
};
Expand Down Expand Up @@ -64,15 +70,28 @@ export default {
Button: {
tag: 'button',
style: {
bg: 'background',
bg: 'primary',
corner: 'm',
color: 'invertedTextColor'
},
states: {
danger: {
bg: 'danger'
}
}
variants: {
primary: {
outlined: {
style: {
bg: 'primary',
color: 'invertedTextColor',
bg: 'none',
borderColor: 'primary',
borderWidth: '1px'
color: 'text',
},
states: {
danger: {
borderColor: 'danger'
}
}
},
},
},
Expand All @@ -88,15 +107,28 @@ const components: Components = {
Button: {
tag: 'button',
style: {
bg: 'background',
bg: 'primary',
corner: 'm',
color: 'invertedTextColor'
},
states: {
danger: {
bg: 'danger'
}
}
variants: {
primary: {
outlined: {
style: {
bg: 'primary',
color: 'invertedTextColor',
bg: 'unset',
borderColor: 'primary',
borderWidth: '1px'
color: 'text',
},
states: {
danger: {
borderColor: 'danger'
}
}
},
},
},
Expand All @@ -122,25 +154,59 @@ an example of usage, and the correspondent output:
| name | css property | example | output |
| :--------------------- | :-------------------------------------- | :------------------------------------------------ | :-------------------------------------- |
| componentName | `It depends on the theme configuration` | `{ componentName: 'Button' }` | `It depends on the theme configuration` |
| componentName, variant | `It depends on the theme configuration` | `{ componentName: 'Button', variant: 'primary' }` | `It depends on the theme configuration` |
| componentName, variant | `It depends on the theme configuration` | `{ componentName: 'Button', variant: 'outlined' }` | `It depends on the theme configuration` |
| componentName, state | `It depends on the theme configuration` | `{ componentName: 'Button', state: 'danger' }` | `It depends on the theme configuration` |
| componentName, variant, state | `It depends on the theme configuration` | `{ componentName: 'Button', variant: 'outlined', state: 'danger' }` | `It depends on the theme configuration` |

The previous example will generate the style:
The previous example will generate the styles:

```typescript
const style = morfeo.resolve({ componentName: 'Button', variant: 'primary' });
const style = morfeo.resolve({ componentName: 'Button' });
/*
{
borderRadius: '16px',
backgroundColor: '#06f',
color: '#ffffff',
}
*/

const styleWithVariant = morfeo.resolve({ componentName: 'Button', variant: 'outlined' });
/*
{
borderRadius: '16px',
backgroundColor: 'unset',
color: '#ffffff',
borderColor: '#06f',
borderWidth: '1px'
color: '#000',
}
*/

const styleWithState = morfeo.resolve({ componentName: 'Button', state: 'danger' });
/*
{
borderRadius: '16px',
backgroundColor: 'orange',
color: '#ffffff',
}
*/

const styleWithVariantAndState = morfeo.resolve({ componentName: 'Button', variant: 'outlined', state: '' });
/*
{
borderRadius: '16px',
backgroundColor: 'unset',
color: '#ffffff',
borderColor: 'orange',
borderWidth: '1px'
color: '#000',
}
*/
```

## Understanding variants

A variant of a component it's a variation of the component base style, in the previous example, in fact, the variant `primary` of the
component `Button` defines additional style to the base style, this additional style will be added to the base one.
A variant of a component it's a variation of the component base style, in the previous example, in fact, the variant `outlined` of the component `Button` defines additional style to the base style, this additional style will be added to the base one.

In case the variant re-declared some of the properties of the parent, those properties will override the parent one (variants wins).

Expand All @@ -151,22 +217,96 @@ For example:
"Button": {
"tag": "button",
"style": {
"bg": "background",
"corner": "m"
"bg": "primary",
"corner": "m",
"color": "invertedTextColor"
},
"variants": {
"primary": {
"outlined": {
"style": {
"bg": "primary",
"color": "invertedTextColor"
}
}
}
}
"bg": "unset",
"borderColor": "primary",
"borderWidth": "1px",
"color": "text"
},
},
},
},
}
```

The complete style of the variant `primary` is:
The complete style of the `outlined` variant is:

```json
{
"corner": "m",
"bg": "unset",
"color": "text",
"borderColor": "primary",
"borderWidth": "1px"
}
```

Where:

- `corner` comes from the parent
- `bg` overrides the parent (was 'background' not is 'primary')
- `color`,`borderColor` and `borderWidth` are added by the variant

Common use cases for variations of a component could be:

- Variations of Buttons, for example `solid`, `outlined`, `round` and so on...
- Typographies for example a variant for `titles`, `paragraphs`, `captions` or `links`
- Different flex direction for a container like `row` and `column`

:::info Notice
Notice that a variant can re-define or add any configuration that can be define in the parent one, like `tag`,
`props`, `style` and `meta` but NOT `variants`! In fact, a variant **cannot have other variants itself**!
:::

## Understanding states

The state is useful when we need to define a variation of a base component style or of a variant style based on the specific state of the component.

Unlike the variant, the state works only on the level when it has been declared, so, if a variant re-declare a state that is already declared on the base component those 2 states will not affect each others:


For example the given style:

```json
{
"Button": {
"tag": "button",
"style": {
"bg": "primary",
"corner": "m",
"color": "invertedTextColor"
},
"states": {
"danger": {
"bg": "danger"
}
},
"variants": {
"outlined": {
"style": {
"bg": "unset",
"borderColor": "primary",
"borderWidth": "1px",
"color": "text",
},
"states": {
"danger": {
"borderColor": "danger"
}
}
},
},
},
};
```

The complete style for the given definition `{ component: 'Button', state: 'danger' }` is:

```json
{
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/parsers/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import { component } from '../theme';
import { ParserParams } from '../types';

export function components({ value, style }: ParserParams<'componentName'>) {
const { variant } = style || {};
const { variant, state } = style || {};
if (!value) {
return {};
}
const componentStyle = component(value, variant).getStyle();
const componentStyle = component(value, variant, state).getStyle();
return globalThis.__MORFEO_PARSERS.resolve(componentStyle);
}

export const componentsParses = {
componentName: components,
variant: () => {},
state: () => {},
};
Loading

0 comments on commit 835510b

Please sign in to comment.