@styled-kit/mods v1.1.0
Modifiers with autocomplete for Styled Components and Linaria
This library allows you to write modifiers for Styled Components and Linaria via Dot Notation and with autocomplete. As well as automatically generate for them types. And that's not all :sunglasses:.
Features
- Quickly writing styles in relation to modifiers
- Using modifiers via Dot Notation
- Writing modifiers with autocomplete
- Uniform modifiers and their values
- Automatic type generation for modifiers
- Possibility to use custom modifiers
- Applying styles relative to multiple modifiers or multiple values
- Ultra-small size (0.4 KB gzip)
A Quick Look
Demo
Usage
Apply styles for any size property value or any color value:
import { mods, Mods } from '../shared/styled';
export const StyledComponent = styled.div<Mods<'size' | 'color'>>`
// Call as literals
${mods.size`
padding: 20px;
margin: 32px;
`};
// Call as function
${mods.color(
(value) => css`
color: ${value};
border: 1px solid;
`
)};
`;<StyledComponent color="blue" size="small" />Apply styles for size='small' or disabled={true}:
import { mods, Mods } from '../shared/styled';
export const StyledComponent = styled.div<
Mods<'size', 'small' | 'medium'> & Mods<'disabled'>
>`
${mods.size.small`
font-size: 14px;
`};
${mods.size.medium`
font-size: 16px;
`};
${mods.disabled.true`
color: gray;
`};
${mods.disabled.false`
color: black;
`};
`;<StyledComponent size="small" disabled />Apply styles if size is undefined or color is not blue:
import { mods, Mods } from '../shared/styled';
export const StyledComponent = styled.div<Mods<'size' | 'color'>>`
${mods.not.size`
font-size: 14px;
`};
${mods.not.color.blue`
background: transparent;
`};
`;<StyledComponent color="green" />Apply styles for any value of the customProp property:
import { mods, Mods } from '../shared/styled';
export const StyledComponent = styled.div<{ customProp: string }>`
${mods('customProp')`
background: black;
`};
`;<StyledComponent customProp="something" />Apply styles for customProp='customValue':
import { mods, Mods } from '../shared/styled';
export const StyledComponent = styled.div<{ customProp: string }>`
${mods('customProp', 'customValue')`
background: black;
`};
`;<StyledComponent customProp="customValue" />:point_up: These are not all possible uses of modifiers. View more options
Setup
src/shared/styled/config.ts
// Configure modifier names and their values
const config = {
color: ['red', 'green', 'blue'],
size: ['small', 'medium', 'large'],
spacing: [8, 12],
disabled: [true, false],
} as const;src/shared/styled/types.ts
import { ModifiersConfig, Modifiers } from '@styled-kit/mods';
// Creating types for modifiers
type ModsConfig = ModifiersConfig<typeof config>;
export type Mods<
Names extends keyof ModsConfig = keyof ModsConfig,
Value extends ModsConfig[Name] = undefined
> = Modifiers<ModsConfig, Name, Value>;src/shared/styled/index.ts
import { initMods } from '@styled-kit/mods';
import { config } from './config';
// Initializing modifiers by config
export const mods = initMods(config);
export type { Mods } from './types';Documentation
Installation
You can install the library using the npm or Yarn package manager.
Installation example using npm:
npm install @styled-kit/modsAn example installation using Yarn:
yarn add @styled-kit/modsSetup
To be able to use modifiers via Dot Notation, you must define in advance what they can be and what their values are.
Creating a modifiers configuration
To configure modifiers, create a config configuration object.
You can create this object in any file in your project, but as an option, you can make such a file system:
src/shared/styled/config.ts
const config = {
color: ['red', 'green', 'blue'],
size: ['small', 'medium', 'large'],
spacing: [8, 12],
disabled: [true, false],
} as const;Describe in config what modifiers with what values you can have.
Describe those modifiers that you are going to reuse in different components.
Over time, you can add to this object as new modifiers are needed.
Note: In TypeScript you must specify the as const type for the config object,
to fix its values and ensure that typing works correctly.
Creating a types
To use autocomplete and types for modifiers, you must configure the appropriate TypeScript types.
You can make type settings in any file of your project, but as an option, you can make such a file system:
src/shared/styled/types.ts
import { ModifiersConfig, Modifiers } from '@styled-kit/mods';
type ModsConfig = ModifiersConfig<typeof config>;
export type Mods<
Names extends keyof ModsConfig = keyof ModsConfig,
Value extends ModsConfig[Name] = undefined
> = Modifiers<ModsConfig, Name, Value>;
export type RMods<
Names extends keyof ModsConfig = keyof ModsConfig,
Value extends ModsConfig[Name] = undefined
> = Required<Mods<Name, Value>>;ModsConfig is a type representing the configuration structure of modifiers.
It is only needed to create a Mods type.
Mods is a type representing modifiers, where N is the name of the modifier,
and V is the value of the modifier (optional). All modifiers can be undefined.
RMods This is a copy of Mods, but all modifiers Required and cannot be undefined.
Initializing the modifiers
You can initialize the modifiers in any file of your project, but
it is important that the initialization is done only once at application startup.
The mods object can then be reused in components of your application.
src/shared/styled/index.ts
import { initMods } from '@styled-kit/mods';
import { config } from './config';
export const mods = initMods(config);
export type { Mods, RMods } from './types';Initializing options
When initializing modifiers, you can set some options.
export const mods = initMods(config, {
onlyFalseValues: true,
});onlyFalseValues
(default: false)
If true, then modifiers with value false will not work when undefined is set.
onlyFalseValues: true
import { mods, Mods } from '../shared/styled';
export const StyledComponent = styled.div<Mods<'disabled'>>`
${mods.disabled.false`
color: blue;
`};
`;// Styles will not be applied because disabled = undefined
<StyledComponent /> onlyFalseValues: false
import { mods, Mods } from '../shared/styled';
export const StyledComponent = styled.div<Mods<'disabled'>>`
${mods.disabled.false`
color: blue;
`};
`;// Styles will be applied
<StyledComponent /> Usage types
Type Mods
This type allows you to define which properties a particular Styled Component can take.
Mods<'size'> - returns the type of object with the size modifier, with all its values from config:
type ComponentProps = Mods<'size'>;
// ComponentProps = {
// size?: 'small' | 'medium' | 'large';
// }Mods<'size' | 'disabled'> - returns object type with size and disabled modifiers, with all their values
from config:
type ComponentProps = Mods<'size' | 'disabled'>;
// ComponentProps = {
// size?: 'small' | 'medium' | 'large';
// disabled?: boolean;
// }Mods<'size', 'small' | 'large'> – Returns the object type with the size modifier, with small and large values:
type ComponentProps = Mods<'size', 'small' | 'large'>;
// ComponentProps = {
// size?: 'small' | 'large';
// }Mods<'size', 'small'> & Mods<'disabled', true> & Mods<'spacing', 12> – returns the object type with size, disabled
and spacing modifiers, with the selected values:
type ComponentProps = Mods<'size', 'small'> &
Mods<'disabled', true> &
Mods<'spacing', 12>;
// ComponentProps = {
// size?: 'small';
// disabled?: true;
// spacing?: 12;
// }Type RMods
As stated earlier, this is a copy of the Mods type, but wrapped in Required. This removes the possibility of passing
a undefined value to the modifier.
You may need RMods if you want to make the modifier required:
interface ComponentProps extends RMods<'size'> {}
// interface ComponentProps {
// size: 'small' | 'medium' | 'large';
// }Type StyledMods
Since version 16 of
React all specified attributes remain on DOM elements
and are not removed even if React does not recognize them. That said, if these attributes are not known to React,
you will see a Warning in the developer console in the browser.
To avoid these warnings, Styled Components recommends use
prefix $ in front of properties that should not be included in the DOM element.
The StyledMods type will allow you to write Styled Component property types without the $ prefix,
but still have valid typing. Internally, it prefixes all types passed to it with $
to all the types passed to it.
Without the StyledMods type:
export const StyledComponent = styled.div<Mods<'size'> & { padding: string; }>`
${mods.size.small`
font-size: 14px;
`};
padding: ${({ padding }) => padding};
`;<StyledComponent size="small" padding="12px" />With the StyledMods type:
import { StyledMods } from '@styled-kit/mods';
export const StyledComponent = styled.div<
StyledMods<Mods<'size'> & { padding: string }>
>`
${mods.size.small`
font-size: 14px;
`};
padding: ${({ $padding }) => $padding};
`;<StyledComponent $size="small" $padding="12px" />:point_up: You do not need to add the $ prefix to the mods modifiers. Modifiers are automatically searched with and without the prefix.
Usage modifiers
The library assumes a large number of options for using modifiers. Each of them can be called as a literal, as a function, with negation, without negation, in object mode or in function mode.
Let's take a closer look at how modifiers can be used:
Using in Object mode
The Object mode allows you to use Dot Notation to use modifiers that you enter in config beforehand.
This mode is best suited for applying styles relative to common modifiers that will be reused in other components.
The features of Object mode modifiers:
- Writing modifiers with Dot Notation
- When writing modifiers, you will have autocomplete
- Types will be automatically generated based on your
config, which you can use with theModstype that you create when you initialize the library - You will get modifiers that are reused throughout the project in a single format
Styles will be applied if:
color is not undefined
export const ModsColor = styled.div<Mods<'color'>>`
${mods.color`
color: blue;
`};
`;<ModsColor color="blue" />color is undefined
export const ModsNotColor = styled.div<Mods<'color'>>`
${mods.not.color`
color: blue;
`};
`;<ModsNotColor />color is blue and is not undefined
export const ModsColorBlue = styled.div<Mods<'color'>>`
${mods.color.blue`
color: blue;
`};
`;<ModsColorBlue color="blue" />color is not blue and is not undefined
export const ModsNotColorBlue = styled.div<Mods<'color'>>`
${mods.not.color.blue`
color: white;
`};
`;<ModsNotColorBlue color="white" />Using in Function mode
The Function mode allows you to apply styles using modifiers that are not in your config.
This mode is best suited for applying styles relative to private modifiers which will not be reused in other components.
The features of Function mode modifiers:
- Using custom modifiers that are not in
config - Ability to specify styles relative to multiple modifiers
- Ability to specify styles relative to multiple modifier values
- Types for them are written manually
- No autocomplete when writing
Styles will be applied if:
color is not undefined
export const FnModsColor = styled.div<{ color?: string }>`
${mods('color')`
color: blue;
`};
`;<FnModsColor color="blue" />color is undefined
export const FnModsNotColor = styled.div<{ color?: string }>`
${mods.not('color')`
color: blue;
`};
`;<FnModsNotColor />color is blue and is not undefined
export const FnModsColorBlue = styled.div<{ color?: string }>`
${mods('color', 'blue')`
color: blue;
`};
`;<FnModsColorBlue color="blue" />color is not blue and is not undefined
export const FnModsNotColorBlue = styled.div<{ color?: string }>`
${mods.not('color', 'blue')`
color: black;
`};
`;<FnModsNotColorBlue color="black" />color is blue or black and is not undefined
export const FnModsColorBlueBlack = styled.div<{ color?: string }>`
${mods('color', ['blue', 'black'])`
color: black;
`};
`;<FnModsColorBlueBlack color="black" />color is not blue or black and is not undefined
export const FnModsNotColorBlueBlack = styled.div<{ color?: string }>`
${mods.not('color', ['blue', 'black'])`
color: white;
`};
`;<FnModsNotColorBlueBlack color="white" />color and bg is not undefined
export const FnModsColorBg = styled.div<{ color?: string; bg?: string }>`
${mods(['color', 'bg'])`
color: black;
`};
`;<FnModsColorBg color="black" bg="green" />color and bg is undefined
export const FnModsNotColorBg = styled.div<{ color?: string; bg?: string }>`
${mods.not(['color', 'bg'])`
color: black;
`};
`;<FnModsNotColorBg />color and bg is blue and is not undefined
export const FnModsColorBgBlue = styled.div<{ color?: string; bg?: string }>`
${mods(['color', 'bg'], 'blue')`
color: black;
`};
`;<FnModsColorBgBlue color="blue" bg="blue" />color and bg is not blue and is not undefined
export const FnModsNotColorBgBlue = styled.div<{ color?: string; bg?: string }>`
${mods.not(['color', 'bg'], 'blue')`
color: black;
`};
`;<FnModsNotColorBgBlue color="black" bg="green" />color and bg together is blue or green and is not undefined
export const FnModsColorBgBlueGreen = styled.div<{
color?: string;
bg?: string;
}>`
${mods(['color', 'bg'], ['blue', 'green'])`
color: black;
`};
`;<FnModsColorBgBlueGreen color="blue" bg="blue" />color and bg together is not blue or green and is not undefined
export const FnModsNotColorBgBlueGreen = styled.div<{
color?: string;
bg?: string;
}>`
${mods.not(['color', 'bg'], ['blue', 'green'])`
color: black;
`};
`;<FnModsNotColorBgBlueGreen color="blue" bg="green" />Call as a literals
You can call any modifier, regardless of mode, as a literal and immediately pass the necessary styles.
Object mode
export const StyledComponent = styled.div<Mods<'size'>>`
${mods.size`
padding: 20px;
`};
${mods.size.small`
font-size: 14px;
`};
`;<StyledComponent size="small" />Function mode
export const StyledComponent = styled.div<Mods<'size'>`
${mods('size')`
font-size: 16px;
`};
${mods('size', 'small')`
font-size: 14px;
`};
`;<StyledComponent size="small" />Call as a function
You can call any modifier, regardless of mode, as a function that will return the css method from styled-components.
The feature of this method is that you get possible values and all the properties of the styled component in the arguments of the passed callback function.
Object mode
export const StyledComponent = styled.div<Mods<'size'> & { padding: string }>`
${mods.size(
(value, props) => css`
font-size: ${value === 'small' ? '14px' : '16px'};
padding: ${props.padding};
`
)};
${mods.size.small(
(value, props) => css`
font-size: 14px;
padding: ${props.padding};
`
)};
`;<StyledComponent size="small" />Function mode
export const StyledComponent = styled.div<Mods<'size'> & { padding: string }>`
${mods('size')(
(value, props) => css`
font-size: ${value === 'small' ? '14px' : '16px'};
padding: ${props.padding};
`
)};
${mods(
'size',
'small'
)(
(value, props) => css`
font-size: 14px;
padding: ${props.padding};
`
)};
`;<StyledComponent size="small" />:point_up: IMPORTANT:
If you use Function mode, use modifiers from config with type Mods and pass an array of modifiers or an array of modifier values, be sure to put as const after the array so that TypeScript correctly displays which properties will be available in the value argument passed to the callback function.
For example:
const config = {
color: 'white' | 'blue' | 'black',
bg: 'green' | 'blue' | 'black',
...
};
export const StyledComponent = styled.div<Mods<'color' | 'bg'>>`
${mods('color', ['blue', 'black'] as const)(
(value, props) => css`
// value: 'blue' | 'black'
`
)};
${mods.not('color', ['blue', 'black'] as const)(
(value, props) => css`
// value: 'white'
`
)};
${mods(['color', 'bg'] as const)(
(value, props) => css`
// value: { color: 'white' | 'blue' | 'black', bg: 'green' | 'blue' | 'black' }
`
)};
${mods.not(['color', 'bg'] as const)(
(value, props) => css`
// value: { color: undefined, bg: undefined }
`
)};
${mods(['color', 'bg'] as const, 'blue')(
(value, props) => css`
// value: 'blue'
`
)};
${mods.not(['color', 'bg'] as const, 'blue')(
(value, props) => css`
// value: { color: 'white' | 'black', bg: 'green' | 'black' }
`
)};
${mods(['color', 'bg'] as const, ['blue', 'black'] as const)(
(value, props) => css`
// value: { color: 'blue' | 'black', bg: 'blue' | 'black' }
`
)};
${mods.not(['color', 'bg'] as const, ['blue', 'black'] as const)(
(value, props) => css`
// value: { color: 'white' | 'blue' | 'black', bg: 'green' | 'blue' | 'black' }
`
)};
`;Using mixins
To apply a set of styles for different modifier values, you can create mixins.
const sizeMixin = (
spacing: RMods['spacing'],
fontSize: RMods['fontSize']
) => css`
padding: ${spacing}px;
font-size: ${fontSize}px;
`;
const StyledComponen = styled.div<Mods<'size'>>`
${mods.size.small(sizeMixin(12, 16))};
${mods.size.medium(sizeMixin(16, 20))};
${mods.size.large(sizeMixin(20, 24))};
`;Additional features
You can use modifiers with boolean values and pass them as string and as boolean:
export const StyledComponent = styled.div<Mods<'disabled'>>`
${mods.disabled.true`
color: gray;
`};
${mods('disabled', true)`
color: gray;
`};
${mods('disabled', 'true')`
color: gray;
`};
${mods.disabled.false`
color: black;
`};
${mods('disabled', false)`
color: black;
`};
${mods('disabled', 'false')`
color: black;
`};
`;<StyledComponent disabled />You can use modifiers with number values:
export const StyledComponent = styled.div<Mods<'spacing'>>`
${mods.spacing[12]`
padding: 12px;
`};
${mods.spacing[24]`
padding: 24px;
`};
`;<StyledComponent spacing={12} />You can do any nesting of modifiers:
export const StyledComponent = styled.div<Mods<'spacing' | 'size'>>`
${mods.size.small`
font-size: 14px;
`};
${mods.spacing[12]`
padding: 12px;
${mods.size.small`
font-size: 16px;
`};
`};
`;<StyledComponent spacing={12} size="small" />You can write additional logic for processing modifier values:
export const StyledComponent = styled.div<{ src: string }>`
${mods('src')(
(value) => css`
color: ${value.includes('facebook') ? 'blue' : 'orange'};
`
)};
`;<StyledComponent src='https://www.facebook.com/' />
<StyledComponent src='https://www.instagram.com/' />Highlight syntax
In order to make syntax highlighting in the IDE, you need to install the styled-components plugin.
In most of the plugins for styled-components it is possible to add a keyword in relation to which the syntax highlighting will be performed.
For example, plugin for IDE WebStorm.
After installing the plugin, go to WebStorm/Preferences/Languages & Frameworks/JavaScript/Styled Components,
click on + and add the keyword mods.
After that, the CSS syntax will be highlighted in the styles defined in mods.
Editor Plugins
VS Code
- Syntax Highlighting - language-babel
- Autocompletion - vscode-styled-components
- Linting - stylelint
WebStorm
- Syntax Highlighting & Autocompletion - webstorm-styled-components
Atom
- Syntax Highlighting and Autocompletion - language-babel
Sublime Text
- Syntax Highlighting & Autocompletion - Naomi, JSCustom ( refer to document on how to turn on Styled Component syntax)
- Linting - SublimeLinter-stylelint, LSP Stylelint
1 year ago
1 year ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago