@abstractpoint/subatomic 中文文档教程

发布于 5年前 浏览 24 项目主页 更新于 3年前

subatomic
Inline style props for emotion and styled-components.
Spend less time naming things. Iterate faster ⚡️




Subatomic 允许您内联设置 React 组件的样式,这样您就可以花更多的时间编写样式,而花更少的时间思考新的组件名称。 它集成了情感和样式组件,让您拥有两全其美:您最喜欢的 css-in-js 库的强大功能以及内联样式系统,可帮助您快速行动并尝试新想法。

Basic Usage

npm install --save subatomic

通过使 subatomic('element') 成为根元素来增强任何组件。

import styled from 'emotion';
import subatomic from 'subatomic/emotion';

// Our components
const Box = subatomic('div');
const H1 = subatomic('h1');
const Button = styled(subatomic('button'))`
  color: white;
  background-color: blue;
  &:hover {
   background-color: lightblue;
  }
`

// Now we have style props! Tweak any style inline.
<Box padding="20px" backgroundColor="white">
  <H1 fontSize="48px" fontWeight="700">
    My Awesome Website
  </H1>
  <Box fontSize="32px" fontWeight="300">
    All other websites are significantly less awesome
  </Box>
  <Button backgroundColor="green">
    Get Started
  </Button>
</Box>

如果您使用从 subatomic/styled-components 导入的样式组件。

虽然这就是您开始时需要了解的全部内容,但我们还支持响应式样式自定义道具逻辑伪类动态元素。 继续阅读以了解这些功能中的每一个将如何影响上面的代码示例。

Responsive Style Props

因此,假设您对出色的网站标题感到满意,但在移动设备上一切都太大了。 只需对上面的示例进行一些调整,我们就可以在较小的屏幕上减少填充和字体大小。

<Box padding={["10px", "20px"]} backgroundColor="white">
  <H1 fontSize={["32px", "48px"]} fontWeight="700">
    My Awesome Website
  </H1>
  <Box fontSize={["24px", "32px"]} fontWeight="300">
    All other websites are significantly less awesome
  </Box>
  <Button backgroundColor="green">
    Get Started
  </Button>
</Box>

如您所见,我们现在将一组值传递给 paddingfontSize 道具。 这些映射到屏幕宽度数组(或“响应断点”)。 亚原子使用一组默认断点,因此上面的示例无需任何额外配置即可运行,但您也可以直接在您的网站主题中覆盖它们。

// theme.js
export default {
  // These are the default breakpoints
  breakpoints: ['576px', '768px', '992px', '1200px']
}

// App
import { ThemeProvider } from 'emotion-theming'
import theme from './theme.js'

const App = props => (
  <ThemeProvider theme={theme}>
    {/* ... */}
  </ThemeProvider>
)

一旦您的主题通过 ThemeProvider 可用,subatomic 将自动使用这些值。 有关主题的更多信息,请参阅 emotion样式组件

Custom Style Props

想要使用更短的道具名称或将它们连接到您的设计系统中? 我们也让这一切变得简单。 在这个例子中,我们使用了一些名称较短的自定义道具(因为少打字很酷),道具值现在映射到我们主题中的这些位置:theme.spacing[i], theme.fontSizes[i]theme.colors.green[2]

<Box p={[2, 3]} bg="white">
  <H1 f={[5, 6]} fontWeight="700">
    My Awesome Website
  </H1>
  <Box f={[4, 5]} fontWeight="300">
    All other websites are significantly less awesome
  </Box>
  <Button bg="greens.2">
    Get Started
  </Button>
</Box>

配置部分,我们将向您展示如何实际设置它,但基本思想是您可以快速定义内联样式,而不会放弃设计系统。

Psuedo-classes

通过将任何伪类或伪元素附加到道具名称来使用它。 在这里,我们修改

<Button bg="greens.2" hoverBg="greens.1">
   Get Started
</Button>

您甚至可以将多个伪类链接在一起。 例如:hoverPlaceholderColor

Dynamic Elements

有时您想要更改底层元素。 您可以使用 is 属性来做到这一点。 在下面的示例中,我们将 H1 重命名为 Heading,现在使用 is 属性将副标题设为 h2 元素。 我们还制作了 Button 一个 a 元素,因为我们希望它是一个看起来像按钮的链接。

const Heading = subatomic('h1');

<Box p={[2, 3]} bg="white">
  <Heading f={[5, 6]} fontWeight="700">
    My Awesome Website
  </Heading>
  <Heading is="h2" f={[4, 5]} fontWeight="300">
    All other websites are significantly less awesome
  </Heading>
  <Button is="a" href="/start" bg="greens.2" hoverBg="greens.1">
    Get Started
  </Button>
</Box>

您甚至可以传递一个组件。 示例:

????‍♀️ Tips and Tricks

Composition Is Your Friend

如果您决定要将一段代码转换为命名组件,您当然可以使用 styled() 语法重写,但考虑使用组合代替并使用 {...props} (扩展语法)传递道具。

// Our example from above
<Box p={[2, 3]} bg="white">
  <Heading f={[5, 6]} fontWeight="700">
    My Awesome Website
  </Heading>
  <Heading is="h2" f={[4, 5]} fontWeight="300">
    All other websites are significantly less awesome
  </Heading>
  <Button is="a" href="/start" bg="greens.2" hoverBg="greens.1">
    Get Started
  </Button>
</Box>

// ⬇ Becomes a reusable component

const PageHeading ({ title, subtitle, ...props }) => (
  <Box p={[2, 3]} bg="white" {...props}>
    <Heading f={[5, 6]} fontWeight="700">
      {title}
    </Heading>
    <Heading is="h2" f={[4, 5]} fontWeight="300">
      {subtitle}
    </Heading>
  </Box>
);

// Lets also break the button out into its own component
const GreenButton = props => (
  <Button 
    bg="greens.2" 
    hoverBg="greens.1" 
    {...props} 
  />;
);

// ⬇ Which is rendered like so

<PageHeading
  title="My Awesome Website"
  subtitle="All other websites are significantly less awesome"
  // We can still pass in style props
  textAlign="center"
/>

<GreenButton is="a" href="/start">
  Get Started
</GreenButton>

Fall Back to Styled When Needed

亚原子建立在情感和样式组件之上,因此您始终可以在需要时使用它们的样式语法。 目标是帮助您更快地工作,而不是完全改变您的工作流程。 在某些情况下,您可能只想创建一个普通的 styled() 组件(或使用 emotion 的 css 属性)。

  • You need to do do css animations with @keyframes
  • Component has a lot of hover styles and props like hoverPlaceholderColor are getting unwieldy
  • Cases where you need more advanced media queries (such as using both min and max width in one rule)
  • You'd rather just use subatomic for spacing and layout components

Theme Configuration

亚原子将自动使用以下默认主题,它带有基本样式系统和一些有用的自定义道具。 请参阅下面的内联注释以了解每个属性的说明和底部的代码示例,该示例显示如何扩展此主题以添加您自己的样式系统和道具。

export default {
  breakpoints: ['576px', '768px', '992px', '1200px'],
  space: [0, 4, 8, 16, 32, 64, 128, 256, 512 ],
  fontSizes: [12, 14, 16, 20, 24, 32, 48, 64, 72],
  // Custom style props go in the props object
  props: {
    f: {
      // Where to find values in theme
      themeKey: 'fontSizes',
      // Default unit if none specified
      defaultUnit: 'px',
      // Resulting css property
      style: 'fontSize'
    },
    color: {
      // Extend theme and add colors object
      themeKey: 'colors',
      style: 'color'
    },
    bg: {
      themeKey: 'colors',
      style: 'backgroundColor'
    },
    borderColor: {
      themeKey: 'colors',
      style: 'borderColor'
    },
    d: {
      style: 'display'
    },
    p: {
      themeKey: 'space',
      defaultUnit: 'px',
      style: 'padding',
      // Directional variations
      variations: {
        pt: 'paddingTop',
        pr: 'paddingRight',
        pb: 'paddingBottom',
        pl: 'paddingLeft',
        px: ['paddingLeft', 'paddingRight'],
        py: ['paddingTop', 'paddingBottom']
      }
    },
    m: {
      themeKey: 'space',
      defaultUnit: 'px',
      style: 'margin',
      variations: {
        mt: 'marginTop',
        mr: 'marginRight',
        mb: 'marginBottom',
        ml: 'marginLeft',
        mx: ['marginLeft', 'marginRight'],
        my: ['marginTop', 'marginBottom']
      }
    },
    h: {
      style: 'height'
    },
    // Advanced width prop
    w: {
      // Style is a function instead of a string
      style: value => {
        let width = value;
        // If less than 1 make it a fraction of 100% (1/3 = 33.33...%, etc)
        // Nice for column widths (<Row><Col w={1/3}><Col w={2/3}></Row>)
        if (isNumber(width) && width <= 1) {
          width = `${width * 100}%`;
        }
        return {
          width: width
        };
      }
    }
  }
}

Extending the Default Theme

以下是您如何扩展上述主题,为默认的 colors prop 添加一个 colors 对象来读取,以及一个用于处理字体的自定义 prop。

import defaultTheme from "subatomic/themes/default";

export default {
  breakpoints: defaultTheme.breakpoints,
  space: defaultTheme.space,
  fontSizes: defaultTheme.fontSizes,
  fonts: {
    primary: 'avenir, -apple-system, BlinkMacSystemFont',
    monospace: '"SF Mono", "Roboto Mono", Menlo, monospace'
  },
  colors: { 
    greens: ['#84e47b', '#11cc00', '#0da200'] 
  },
  props: {
    ...defaultTheme.props,
    // And then add any other custom props you want
    fontFamily: {
      themeKey: 'fonts',
      style: 'fontFamily'
    },
  }
};

// App
import { ThemeProvider } from 'emotion-theming'
import theme from './theme.js'

const App = props => (
  <ThemeProvider theme={theme}>
    {/* ... */}
  </ThemeProvider>
)

您通过 ThemeProvider 提供的任何主题都将覆盖默认主题,因此您可以扩展(合并您想要的部分)或编写您自己的自定义主题。

有兴趣帮助我们添加模仿各种 UI 套件(如 tachyons、bulma 等)的外观和实用程序类的新主题吗? 随意在拉取请求中添加到我们的主题目录。

Inspiration

亚原子的灵感来自于这些优秀的项目:

subatomic
Inline style props for emotion and styled-components.
Spend less time naming things. Iterate faster ⚡️




Subatomic allows you to style your React components inline so that you can spend more time writing styles and less time thinking of new component names. It integrates with emotion and styled-components so that you have the best of both worlds: The power of your favorite css-in-js library plus an inline style system to help you move fast and try out new ideas.

???? Basic Usage

npm install --save subatomic

Supercharge any component by making subatomic('element') the root element.

import styled from 'emotion';
import subatomic from 'subatomic/emotion';

// Our components
const Box = subatomic('div');
const H1 = subatomic('h1');
const Button = styled(subatomic('button'))`
  color: white;
  background-color: blue;
  &:hover {
   background-color: lightblue;
  }
`

// Now we have style props! Tweak any style inline.
<Box padding="20px" backgroundColor="white">
  <H1 fontSize="48px" fontWeight="700">
    My Awesome Website
  </H1>
  <Box fontSize="32px" fontWeight="300">
    All other websites are significantly less awesome
  </Box>
  <Button backgroundColor="green">
    Get Started
  </Button>
</Box>

If you use styled-components import from subatomic/styled-components instead.

While that's all you need to know to get started, we also support responsive styles, custom prop logic, pseudo-classes and dynamic elements. Read on to see how each of these features would affect the code example above.

???? Responsive Style Props

So let's say you're happy with the awesome website header but everything is way too big on mobile. With just a few tweaks to our example above we can decrease padding and font size on smaller screens.

<Box padding={["10px", "20px"]} backgroundColor="white">
  <H1 fontSize={["32px", "48px"]} fontWeight="700">
    My Awesome Website
  </H1>
  <Box fontSize={["24px", "32px"]} fontWeight="300">
    All other websites are significantly less awesome
  </Box>
  <Button backgroundColor="green">
    Get Started
  </Button>
</Box>

As you can see we're now passing an array of values to the padding and fontSize props. These map to an array of screen widths (or "responsive breakpoints"). Subatomic uses a default set of breakpoints, so the above example works without any extra configuration, but you can also override them right in your website theme.

// theme.js
export default {
  // These are the default breakpoints
  breakpoints: ['576px', '768px', '992px', '1200px']
}

// App
import { ThemeProvider } from 'emotion-theming'
import theme from './theme.js'

const App = props => (
  <ThemeProvider theme={theme}>
    {/* ... */}
  </ThemeProvider>
)

Once your theme is made available via ThemeProvider subatomic will automatically use those values instead. For more info about theming see the ThemeProvider docs for emotion or styled-components.

???? Custom Style Props

Want to use shorter prop names or hook them into your design system? We make that easy as well. In this example we're using some custom props with shorter names (because less typing is cool) and the prop values now map to these locations in our theme: theme.spacing[i], theme.fontSizes[i], theme.colors.green[2].

<Box p={[2, 3]} bg="white">
  <H1 f={[5, 6]} fontWeight="700">
    My Awesome Website
  </H1>
  <Box f={[4, 5]} fontWeight="300">
    All other websites are significantly less awesome
  </Box>
  <Button bg="greens.2">
    Get Started
  </Button>
</Box>

In the configuration section we'll show you how actually set this up, but the basic idea is that you can quickly define styles inline without giving the up the wonderful consistency of a design system.

???? Psuedo-classes

Use any psuedo-class or pseudo-element by prepending it to the prop name. Here we modify <Button> so that its hover color fits better with its green background-color.

<Button bg="greens.2" hoverBg="greens.1">
   Get Started
</Button>

You can even chain multiple pseudo-classes together. For example: hoverPlaceholderColor

???? Dynamic Elements

Sometimes you want to change the underlying element. You can do that with the is prop. In the example below we've renamed H1 to Heading and now use the is prop to make the subheading an h2 element. We also made Button an a element because we want it to be a link that looks like a button.

const Heading = subatomic('h1');

<Box p={[2, 3]} bg="white">
  <Heading f={[5, 6]} fontWeight="700">
    My Awesome Website
  </Heading>
  <Heading is="h2" f={[4, 5]} fontWeight="300">
    All other websites are significantly less awesome
  </Heading>
  <Button is="a" href="/start" bg="greens.2" hoverBg="greens.1">
    Get Started
  </Button>
</Box>

You can even pass a component. Example: <Button is={RouterLink} to="/start">Get Started</Button>

????‍♀️ Tips and Tricks

Composition Is Your Friend

If you decide you want to turn a chunk of code into a named component you can of course re-write using styled() syntax, but consider using composition instead and pass along props using {...props} (spread syntax).

// Our example from above
<Box p={[2, 3]} bg="white">
  <Heading f={[5, 6]} fontWeight="700">
    My Awesome Website
  </Heading>
  <Heading is="h2" f={[4, 5]} fontWeight="300">
    All other websites are significantly less awesome
  </Heading>
  <Button is="a" href="/start" bg="greens.2" hoverBg="greens.1">
    Get Started
  </Button>
</Box>

// ⬇ Becomes a reusable component

const PageHeading ({ title, subtitle, ...props }) => (
  <Box p={[2, 3]} bg="white" {...props}>
    <Heading f={[5, 6]} fontWeight="700">
      {title}
    </Heading>
    <Heading is="h2" f={[4, 5]} fontWeight="300">
      {subtitle}
    </Heading>
  </Box>
);

// Lets also break the button out into its own component
const GreenButton = props => (
  <Button 
    bg="greens.2" 
    hoverBg="greens.1" 
    {...props} 
  />;
);

// ⬇ Which is rendered like so

<PageHeading
  title="My Awesome Website"
  subtitle="All other websites are significantly less awesome"
  // We can still pass in style props
  textAlign="center"
/>

<GreenButton is="a" href="/start">
  Get Started
</GreenButton>

Fall Back to Styled When Needed

Subatomic builds on emotion and styled-components so that you always have their styling syntax to fall back on when needed. The goal is to help you work faster, not completely change your workflow. Here are some cases where you might want to just create a normal styled() component (or use emotion's css prop).

  • You need to do do css animations with @keyframes
  • Component has a lot of hover styles and props like hoverPlaceholderColor are getting unwieldy
  • Cases where you need more advanced media queries (such as using both min and max width in one rule)
  • You'd rather just use subatomic for spacing and layout components

???? Theme Configuration

Subatomic will automatically use the following default theme which comes with a basic style system and some useful custom props. See the inline comments below for an explanation of each property and a code example at the bottom that shows how to extend this theme to add your own style system and props.

export default {
  breakpoints: ['576px', '768px', '992px', '1200px'],
  space: [0, 4, 8, 16, 32, 64, 128, 256, 512 ],
  fontSizes: [12, 14, 16, 20, 24, 32, 48, 64, 72],
  // Custom style props go in the props object
  props: {
    f: {
      // Where to find values in theme
      themeKey: 'fontSizes',
      // Default unit if none specified
      defaultUnit: 'px',
      // Resulting css property
      style: 'fontSize'
    },
    color: {
      // Extend theme and add colors object
      themeKey: 'colors',
      style: 'color'
    },
    bg: {
      themeKey: 'colors',
      style: 'backgroundColor'
    },
    borderColor: {
      themeKey: 'colors',
      style: 'borderColor'
    },
    d: {
      style: 'display'
    },
    p: {
      themeKey: 'space',
      defaultUnit: 'px',
      style: 'padding',
      // Directional variations
      variations: {
        pt: 'paddingTop',
        pr: 'paddingRight',
        pb: 'paddingBottom',
        pl: 'paddingLeft',
        px: ['paddingLeft', 'paddingRight'],
        py: ['paddingTop', 'paddingBottom']
      }
    },
    m: {
      themeKey: 'space',
      defaultUnit: 'px',
      style: 'margin',
      variations: {
        mt: 'marginTop',
        mr: 'marginRight',
        mb: 'marginBottom',
        ml: 'marginLeft',
        mx: ['marginLeft', 'marginRight'],
        my: ['marginTop', 'marginBottom']
      }
    },
    h: {
      style: 'height'
    },
    // Advanced width prop
    w: {
      // Style is a function instead of a string
      style: value => {
        let width = value;
        // If less than 1 make it a fraction of 100% (1/3 = 33.33...%, etc)
        // Nice for column widths (<Row><Col w={1/3}><Col w={2/3}></Row>)
        if (isNumber(width) && width <= 1) {
          width = `${width * 100}%`;
        }
        return {
          width: width
        };
      }
    }
  }
}

Extending the Default Theme

Here's how you'd extend the above theme to add a colors object for the default colors prop to read from, as well as a custom prop for dealing with fonts.

import defaultTheme from "subatomic/themes/default";

export default {
  breakpoints: defaultTheme.breakpoints,
  space: defaultTheme.space,
  fontSizes: defaultTheme.fontSizes,
  fonts: {
    primary: 'avenir, -apple-system, BlinkMacSystemFont',
    monospace: '"SF Mono", "Roboto Mono", Menlo, monospace'
  },
  colors: { 
    greens: ['#84e47b', '#11cc00', '#0da200'] 
  },
  props: {
    ...defaultTheme.props,
    // And then add any other custom props you want
    fontFamily: {
      themeKey: 'fonts',
      style: 'fontFamily'
    },
  }
};

// App
import { ThemeProvider } from 'emotion-theming'
import theme from './theme.js'

const App = props => (
  <ThemeProvider theme={theme}>
    {/* ... */}
  </ThemeProvider>
)

Any theme you make available via ThemeProvider will override the default theme, so you can either extend (merge in the parts you want) or write your own custom theme.

Interested in helping us add new themes that mimic the look and utility classes of various UI kits like tachyons, bulma, etc? Feel free to add to our themes directory in a pull request.

???? Inspiration

Subatomic was inspired by these excellent projects:

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文