Shopify / restyle

A type-enforced system for building UI components in React Native with TypeScript.

Home Page:https://shopify.github.io/restyle/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Negative spacing values

tamlyn opened this issue · comments

Is there a way to specify negative spacing values?

Assuming I have my theme spacing set up with t-shirt sizes, I'd love to be able to do something like

<Box marginVertical="m" marginHorizontal="-m"> ... </Box>

If it's not currently possible, is it something you would be open to PRs for?

You could add negative spacing values manually like so

const spacing = {
 "-m": -8,
  "-sm": -4,
  sm: 4,
  m: 8
}

but it's not ideal for a few reasons (you will probably enable padding to be negative, unwanted mirroring/duplication of tokens, semantics, etc).

As for me, I added style prop bleed that flips the sign of my space token and applies it to margin.

import {
  createBox,
  createRestyleComponent,
  createRestyleFunction,
  boxRestyleFunctions,
  ResponsiveValue,
} from "@shopify/restyle";
import { Theme } from "../../theme.config";

type BleedTransform = { value: keyof Theme["spacing"]; theme: Theme };

const SHORTHANDS = ["", "Horizontal", "Vertical"] as const;

const bleedRestyleFunctions = SHORTHANDS.map((shorthand) =>
  createRestyleFunction({
    property: ("bleed" + shorthand) as `bleed${typeof shorthand}`,
    styleProperty: ("margin" + shorthand) as `margin${typeof shorthand}`,
    transform: ({ value, theme }: BleedTransform) => -theme.spacing[value],
  })
);

type BleedProps = {
  [key in typeof bleedRestyleFunctions[number]["property"]]?: ResponsiveValue<
    BleedTransform["value"],
    Theme
  >;
};

const BaseBox = createBox<Theme>();

const restyleFns = [
  // Default
  ...boxRestyleFunctions,
  // Extensions
  ...bleedRestyleFunctions,
];

export interface BoxProps
  extends React.ComponentProps<typeof BaseBox>,
    BleedProps {}

export const Box = createRestyleComponent<BoxProps, Theme>(restyleFns, BaseBox);

Edit: While it's probably the correct way of dealing with negative margin, I realise it doesn't provide an answer to your exact question.

If you want the syntax marginHorizontal="-m" you can probably achieve it by overriding like so

type MarginTransform = {
  value: keyof Theme["spacing"] | `-${keyof Theme["spacing"]}`;
  theme: Theme;
};

const marginRestyleFn = createRestyleFunction({
  property: "margin",
  transform: ({ value, theme }: MarginTransform) => {
    if (value[0] === "-") {
      return -theme.spacing[value as keyof Theme["spacing"]];
    }
    return theme.spacing[value as keyof Theme["spacing"]];
  },
});