diff --git a/docs/components/DocsLayout.module.scss b/docs/components/DocsLayout.module.scss
index 1724de0..6f3d0a1 100644
--- a/docs/components/DocsLayout.module.scss
+++ b/docs/components/DocsLayout.module.scss
@@ -6,6 +6,7 @@
.NavLink {
background-color: var(--palette-white-3);
+ transition: background-color 300ms cubic-bezier(0.23, 1, 0.32, 1);
&[aria-current="page"] {
background-color: var(--palette-white-2);
}
diff --git a/docs/components/DocsLayout.tsx b/docs/components/DocsLayout.tsx
index e2a52a0..8afff7f 100644
--- a/docs/components/DocsLayout.tsx
+++ b/docs/components/DocsLayout.tsx
@@ -5,7 +5,7 @@ import styles from "./DocsLayout.module.scss";
import { useRouter } from "next/router";
const links = [
- { href: "/", text: "Home" },
+ { href: "/test-index", text: "Home" },
{ href: "/getting-started", text: "Getting Started" },
{ href: "/box", text: "Box" },
{ href: "/type", text: "Type" },
@@ -17,7 +17,8 @@ export default function DocsLayout({ children }: { children: ReactNode }) {
-
+
{children}
@@ -67,6 +68,7 @@ function SidebarLink({
pl={4}
pr={8}
{...(active ? { "aria-current": "page" } : {})}
+ hover={{ background: "palette-white-2" }}
>
{text}
diff --git a/docs/components/slang/config.ts b/docs/components/slang/config.ts
index 9d8d8c6..f579a6e 100644
--- a/docs/components/slang/config.ts
+++ b/docs/components/slang/config.ts
@@ -4,16 +4,17 @@ const config: Partial = {
baseFontFamily: "Neue Montreal",
baseFontSizePx: 20,
baseFontSizeMobilePx: 16,
- baseFontLineHeight: 1.5,
+ baseFontLineHeight: 1.4,
baseFontLineHeightMobile: 1.5,
baseContainerSizePx: 700,
- baseSpacingPx: 22.4,
+ baseSpacingPx: 30,
+ spacerPx: 4,
baseSpacingScale: 1.1,
errorCorrectionTopPx: -1.32,
errorCorrectionTopScale: 1.5,
errorCorrectionBottomPx: 1.67,
errorCorrectionBottomScale: 1.486,
- typeScaleBase: 1.25,
+ typeScaleBase: 1.4,
typeScaleBaseMobile: 1.16,
inverseTypeScaleLineHeight: 0.96,
inverseTypeScaleLineHeightMobile: 0.969,
@@ -23,7 +24,7 @@ const config: Partial = {
fluidMaxScreenSizePx: 1200,
palette: {
white: ["#ffffff", "#f3f2f2", "#dadada", "#e7ebec"],
- black: ["#000000"],
+ black: ["#000000", "#121212", "#333333"],
},
colors: {
background: "var(--palette-white-1)",
diff --git a/docs/components/slang/index.tsx b/docs/components/slang/index.tsx
index d3e3932..3028788 100644
--- a/docs/components/slang/index.tsx
+++ b/docs/components/slang/index.tsx
@@ -16,7 +16,9 @@ type Colors =
| "palette-white-1"
| "palette-white-2"
| "palette-white-3"
- | "palette-black-0";
+ | "palette-black-0"
+ | "palette-black-1"
+ | "palette-black-2";
export type BoxProps = PropsWithAs>;
export type TypeProps = PropsWithAs>;
const Box = forwardRefWithAs(BoxComponent);
diff --git a/docs/components/slang/slang.css b/docs/components/slang/slang.css
index de7a030..db0fcee 100644
--- a/docs/components/slang/slang.css
+++ b/docs/components/slang/slang.css
@@ -500,12 +500,12 @@ body {
--base-font-size:20;
--base-font-size-mobile-px:16px;
--base-font-size-mobile:16;
- --base-font-line-height:1.5;
+ --base-font-line-height:1.4;
--base-font-line-height-mobile:1.5;
--spacer-px:4px;
--spacer:4;
- --base-spacing-px:22.4px;
- --base-spacing:22.4;
+ --base-spacing-px:30px;
+ --base-spacing:30;
--base-container-size-px:700px;
--base-container-size:700;
--base-spacing-scale:1.1;
@@ -515,7 +515,7 @@ body {
--error-correction-bottom-px:1.67px;
--error-correction-bottom:1.67;
--error-correction-bottom-scale:1.486;
- --type-scale-base:1.25;
+ --type-scale-base:1.4;
--type-scale-base-mobile:1.16;
--inverse-type-scale-line-height:0.96;
--inverse-type-scale-line-height-mobile:0.969;
@@ -526,18 +526,18 @@ body {
--fluid-min-screen-size:375;
--fluid-max-screen-size-px:1200px;
--fluid-max-screen-size:1200;
- --multiplier--3:0.512;
- --multiplier--2:0.64;
- --multiplier--1:0.8;
+ --multiplier--3:0.36443148688046656;
+ --multiplier--2:0.5102040816326531;
+ --multiplier--1:0.7142857142857143;
--multiplier-0:1;
- --multiplier-1:1.25;
- --multiplier-2:1.5625;
- --multiplier-3:1.953125;
- --multiplier-4:2.44140625;
- --multiplier-5:3.0517578125;
- --multiplier-6:3.814697265625;
- --multiplier-7:4.76837158203125;
- --multiplier-8:5.9604644775390625;
+ --multiplier-1:1.4;
+ --multiplier-2:1.9599999999999997;
+ --multiplier-3:2.7439999999999993;
+ --multiplier-4:3.841599999999999;
+ --multiplier-5:5.378239999999998;
+ --multiplier-6:7.529535999999997;
+ --multiplier-7:10.541350399999995;
+ --multiplier-8:14.757890559999993;
--mobile-multiplier--3:0.6406576735413507;
--mobile-multiplier--2:0.7431629013079668;
--mobile-multiplier--1:0.8620689655172414;
@@ -603,6 +603,8 @@ body {
--palette-white-2:#dadada;
--palette-white-3:#e7ebec;
--palette-black-0:#000000;
+ --palette-black-1:#121212;
+ --palette-black-2:#333333;
--color-background:var(--palette-white-1);
--color-foreground:var(--palette-black-0);
}
@@ -610,54 +612,117 @@ body {
.slang-box.flow {
grid-auto-flow: var(--flow);
}
+.slang-box.flow_hover:hover {
+grid-auto-flow: var(--flow_hover);
+}
.slang-box.content {
place-content: var(--content);
}
+.slang-box.content_hover:hover {
+place-content: var(--content_hover);
+}
.slang-box.items {
place-items: var(--items);
}
+.slang-box.items_hover:hover {
+place-items: var(--items_hover);
+}
.slang-box.self {
place-self: var(--self);
}
+.slang-box.self_hover:hover {
+place-self: var(--self_hover);
+}
.slang-box.p {
padding: calc(var(--spacer-px) * var(--p));
}
+.slang-box.p_hover:hover {
+padding: calc(var(--spacer-px) * var(--p_hover));
+}
.slang-box.py {
padding-top: calc(var(--spacer-px) * var(--py)); padding-bottom: calc(var(--spacer-px) * var(--py));
}
+.slang-box.py_hover:hover {
+padding-top: calc(var(--spacer-px) * var(--py_hover)); padding-bottom: calc(var(--spacer-px) * var(--py_hover));
+}
.slang-box.px {
padding-left: calc(var(--spacer-px) * var(--px)); padding-right: calc(var(--spacer-px) * var(--px));
}
+.slang-box.px_hover:hover {
+padding-left: calc(var(--spacer-px) * var(--px_hover)); padding-right: calc(var(--spacer-px) * var(--px_hover));
+}
.slang-box.pt {
padding-top: calc(var(--spacer-px) * var(--pt));
}
+.slang-box.pt_hover:hover {
+padding-top: calc(var(--spacer-px) * var(--pt_hover));
+}
.slang-box.pr {
padding-right: calc(var(--spacer-px) * var(--pr));
}
+.slang-box.pr_hover:hover {
+padding-right: calc(var(--spacer-px) * var(--pr_hover));
+}
.slang-box.pb {
padding-bottom: calc(var(--spacer-px) * var(--pb));
}
+.slang-box.pb_hover:hover {
+padding-bottom: calc(var(--spacer-px) * var(--pb_hover));
+}
.slang-box.pl {
padding-left: calc(var(--spacer-px) * var(--pl));
}
+.slang-box.pl_hover:hover {
+padding-left: calc(var(--spacer-px) * var(--pl_hover));
+}
.slang-box.gap {
gap: calc(var(--spacer-px) * var(--gap));
}
+.slang-box.gap_hover:hover {
+gap: calc(var(--spacer-px) * var(--gap_hover));
+}
+.slang-box.columnGap {
+column-gap: calc(var(--spacer-px) * var(--columnGap));
+}
+.slang-box.columnGap_hover:hover {
+column-gap: calc(var(--spacer-px) * var(--columnGap_hover));
+}
+.slang-box.rowGap {
+row-gap: calc(var(--spacer-px) * var(--rowGap));
+}
+.slang-box.rowGap_hover:hover {
+row-gap: calc(var(--spacer-px) * var(--rowGap_hover));
+}
.slang-box.template {
grid-template: var(--template);
}
+.slang-box.template_hover:hover {
+grid-template: var(--template_hover);
+}
.slang-box.display {
display: var(--display);
}
+.slang-box.display_hover:hover {
+display: var(--display_hover);
+}
.slang-box.overflow {
overflow: var(--overflow);
}
+.slang-box.overflow_hover:hover {
+overflow: var(--overflow_hover);
+}
.slang-box.h {
height: var(--h);
}
+.slang-box.h_hover:hover {
+height: var(--h_hover);
+}
.slang-box.root {
min-height: var(--root);
}
+.slang-box.root_hover:hover {
+min-height: var(--root_hover);
+}
@supports (-webkit-touch-callout: none) {
.slang-box.root-safari {
min-height: var(--root-safari);
@@ -666,155 +731,344 @@ min-height: var(--root-safari);
.slang-box.background {
background-color: var(--background);
}
+.slang-box.background_hover:hover {
+background-color: var(--background_hover);
+}
+.slang-box.color {
+color: var(--color);
+}
+.slang-box.color_hover:hover {
+color: var(--color_hover);
+}
.slang-box.contain {
max-width: var(--contain);
}
+.slang-box.contain_hover:hover {
+max-width: var(--contain_hover);
+}
.slang-box.rad {
border-radius: calc(var(--smallest-border-radius-px) * var(--rad));
}
+.slang-box.rad_hover:hover {
+border-radius: calc(var(--smallest-border-radius-px) * var(--rad_hover));
+}
@media(min-width: 768px) {
.slang-box.flow-tablet {
grid-auto-flow: var(--flow-tablet);
}
+.slang-box.flow-tablet_hover:hover {
+grid-auto-flow: var(--flow-tablet_hover);
+}
.slang-box.content-tablet {
place-content: var(--content-tablet);
}
+.slang-box.content-tablet_hover:hover {
+place-content: var(--content-tablet_hover);
+}
.slang-box.items-tablet {
place-items: var(--items-tablet);
}
+.slang-box.items-tablet_hover:hover {
+place-items: var(--items-tablet_hover);
+}
.slang-box.self-tablet {
place-self: var(--self-tablet);
}
+.slang-box.self-tablet_hover:hover {
+place-self: var(--self-tablet_hover);
+}
.slang-box.p-tablet {
padding: calc(var(--spacer-px) * var(--p-tablet));
}
+.slang-box.p-tablet_hover:hover {
+padding: calc(var(--spacer-px) * var(--p-tablet_hover));
+}
.slang-box.py-tablet {
padding-top: calc(var(--spacer-px) * var(--py-tablet)); padding-bottom: calc(var(--spacer-px) * var(--py-tablet));
}
+.slang-box.py-tablet_hover:hover {
+padding-top: calc(var(--spacer-px) * var(--py-tablet_hover)); padding-bottom: calc(var(--spacer-px) * var(--py-tablet_hover));
+}
.slang-box.px-tablet {
padding-left: calc(var(--spacer-px) * var(--px-tablet)); padding-right: calc(var(--spacer-px) * var(--px-tablet));
}
+.slang-box.px-tablet_hover:hover {
+padding-left: calc(var(--spacer-px) * var(--px-tablet_hover)); padding-right: calc(var(--spacer-px) * var(--px-tablet_hover));
+}
.slang-box.pt-tablet {
padding-top: calc(var(--spacer-px) * var(--pt-tablet));
}
+.slang-box.pt-tablet_hover:hover {
+padding-top: calc(var(--spacer-px) * var(--pt-tablet_hover));
+}
.slang-box.pr-tablet {
padding-right: calc(var(--spacer-px) * var(--pr-tablet));
}
+.slang-box.pr-tablet_hover:hover {
+padding-right: calc(var(--spacer-px) * var(--pr-tablet_hover));
+}
.slang-box.pb-tablet {
padding-bottom: calc(var(--spacer-px) * var(--pb-tablet));
}
+.slang-box.pb-tablet_hover:hover {
+padding-bottom: calc(var(--spacer-px) * var(--pb-tablet_hover));
+}
.slang-box.pl-tablet {
padding-left: calc(var(--spacer-px) * var(--pl-tablet));
}
+.slang-box.pl-tablet_hover:hover {
+padding-left: calc(var(--spacer-px) * var(--pl-tablet_hover));
+}
.slang-box.gap-tablet {
gap: calc(var(--spacer-px) * var(--gap-tablet));
}
+.slang-box.gap-tablet_hover:hover {
+gap: calc(var(--spacer-px) * var(--gap-tablet_hover));
+}
+.slang-box.columnGap-tablet {
+column-gap: calc(var(--spacer-px) * var(--columnGap-tablet));
+}
+.slang-box.columnGap-tablet_hover:hover {
+column-gap: calc(var(--spacer-px) * var(--columnGap-tablet_hover));
+}
+.slang-box.rowGap-tablet {
+row-gap: calc(var(--spacer-px) * var(--rowGap-tablet));
+}
+.slang-box.rowGap-tablet_hover:hover {
+row-gap: calc(var(--spacer-px) * var(--rowGap-tablet_hover));
+}
.slang-box.template-tablet {
grid-template: var(--template-tablet);
}
+.slang-box.template-tablet_hover:hover {
+grid-template: var(--template-tablet_hover);
+}
.slang-box.display-tablet {
display: var(--display-tablet);
}
+.slang-box.display-tablet_hover:hover {
+display: var(--display-tablet_hover);
+}
.slang-box.overflow-tablet {
overflow: var(--overflow-tablet);
}
+.slang-box.overflow-tablet_hover:hover {
+overflow: var(--overflow-tablet_hover);
+}
.slang-box.h-tablet {
height: var(--h-tablet);
}
+.slang-box.h-tablet_hover:hover {
+height: var(--h-tablet_hover);
+}
.slang-box.root-tablet {
min-height: var(--root-tablet);
}
+.slang-box.root-tablet_hover:hover {
+min-height: var(--root-tablet_hover);
+}
.slang-box.background-tablet {
background-color: var(--background-tablet);
}
+.slang-box.background-tablet_hover:hover {
+background-color: var(--background-tablet_hover);
+}
+.slang-box.color-tablet {
+color: var(--color-tablet);
+}
+.slang-box.color-tablet_hover:hover {
+color: var(--color-tablet_hover);
+}
.slang-box.contain-tablet {
max-width: var(--contain-tablet);
}
+.slang-box.contain-tablet_hover:hover {
+max-width: var(--contain-tablet_hover);
+}
.slang-box.rad-tablet {
border-radius: calc(var(--smallest-border-radius-px) * var(--rad-tablet));
}
+.slang-box.rad-tablet_hover:hover {
+border-radius: calc(var(--smallest-border-radius-px) * var(--rad-tablet_hover));
+}
}
@media(min-width: 1024px) {
.slang-box.flow-desktop {
grid-auto-flow: var(--flow-desktop);
}
+.slang-box.flow-desktop_hover:hover {
+grid-auto-flow: var(--flow-desktop_hover);
+}
.slang-box.content-desktop {
place-content: var(--content-desktop);
}
+.slang-box.content-desktop_hover:hover {
+place-content: var(--content-desktop_hover);
+}
.slang-box.items-desktop {
place-items: var(--items-desktop);
}
+.slang-box.items-desktop_hover:hover {
+place-items: var(--items-desktop_hover);
+}
.slang-box.self-desktop {
place-self: var(--self-desktop);
}
+.slang-box.self-desktop_hover:hover {
+place-self: var(--self-desktop_hover);
+}
.slang-box.p-desktop {
padding: calc(var(--spacer-px) * var(--p-desktop));
}
+.slang-box.p-desktop_hover:hover {
+padding: calc(var(--spacer-px) * var(--p-desktop_hover));
+}
.slang-box.py-desktop {
padding-top: calc(var(--spacer-px) * var(--py-desktop)); padding-bottom: calc(var(--spacer-px) * var(--py-desktop));
}
+.slang-box.py-desktop_hover:hover {
+padding-top: calc(var(--spacer-px) * var(--py-desktop_hover)); padding-bottom: calc(var(--spacer-px) * var(--py-desktop_hover));
+}
.slang-box.px-desktop {
padding-left: calc(var(--spacer-px) * var(--px-desktop)); padding-right: calc(var(--spacer-px) * var(--px-desktop));
}
+.slang-box.px-desktop_hover:hover {
+padding-left: calc(var(--spacer-px) * var(--px-desktop_hover)); padding-right: calc(var(--spacer-px) * var(--px-desktop_hover));
+}
.slang-box.pt-desktop {
padding-top: calc(var(--spacer-px) * var(--pt-desktop));
}
+.slang-box.pt-desktop_hover:hover {
+padding-top: calc(var(--spacer-px) * var(--pt-desktop_hover));
+}
.slang-box.pr-desktop {
padding-right: calc(var(--spacer-px) * var(--pr-desktop));
}
+.slang-box.pr-desktop_hover:hover {
+padding-right: calc(var(--spacer-px) * var(--pr-desktop_hover));
+}
.slang-box.pb-desktop {
padding-bottom: calc(var(--spacer-px) * var(--pb-desktop));
}
+.slang-box.pb-desktop_hover:hover {
+padding-bottom: calc(var(--spacer-px) * var(--pb-desktop_hover));
+}
.slang-box.pl-desktop {
padding-left: calc(var(--spacer-px) * var(--pl-desktop));
}
+.slang-box.pl-desktop_hover:hover {
+padding-left: calc(var(--spacer-px) * var(--pl-desktop_hover));
+}
.slang-box.gap-desktop {
gap: calc(var(--spacer-px) * var(--gap-desktop));
}
+.slang-box.gap-desktop_hover:hover {
+gap: calc(var(--spacer-px) * var(--gap-desktop_hover));
+}
+.slang-box.columnGap-desktop {
+column-gap: calc(var(--spacer-px) * var(--columnGap-desktop));
+}
+.slang-box.columnGap-desktop_hover:hover {
+column-gap: calc(var(--spacer-px) * var(--columnGap-desktop_hover));
+}
+.slang-box.rowGap-desktop {
+row-gap: calc(var(--spacer-px) * var(--rowGap-desktop));
+}
+.slang-box.rowGap-desktop_hover:hover {
+row-gap: calc(var(--spacer-px) * var(--rowGap-desktop_hover));
+}
.slang-box.template-desktop {
grid-template: var(--template-desktop);
}
+.slang-box.template-desktop_hover:hover {
+grid-template: var(--template-desktop_hover);
+}
.slang-box.display-desktop {
display: var(--display-desktop);
}
+.slang-box.display-desktop_hover:hover {
+display: var(--display-desktop_hover);
+}
.slang-box.overflow-desktop {
overflow: var(--overflow-desktop);
}
+.slang-box.overflow-desktop_hover:hover {
+overflow: var(--overflow-desktop_hover);
+}
.slang-box.h-desktop {
height: var(--h-desktop);
}
+.slang-box.h-desktop_hover:hover {
+height: var(--h-desktop_hover);
+}
.slang-box.root-desktop {
min-height: var(--root-desktop);
}
+.slang-box.root-desktop_hover:hover {
+min-height: var(--root-desktop_hover);
+}
.slang-box.background-desktop {
background-color: var(--background-desktop);
}
+.slang-box.background-desktop_hover:hover {
+background-color: var(--background-desktop_hover);
+}
+.slang-box.color-desktop {
+color: var(--color-desktop);
+}
+.slang-box.color-desktop_hover:hover {
+color: var(--color-desktop_hover);
+}
.slang-box.contain-desktop {
max-width: var(--contain-desktop);
}
+.slang-box.contain-desktop_hover:hover {
+max-width: var(--contain-desktop_hover);
+}
.slang-box.rad-desktop {
border-radius: calc(var(--smallest-border-radius-px) * var(--rad-desktop));
}
+.slang-box.rad-desktop_hover:hover {
+border-radius: calc(var(--smallest-border-radius-px) * var(--rad-desktop_hover));
+}
}
.slang-type.weight {
font-weight: var(--weight);
}
+.slang-type.weight_hover:hover {
+font-weight: var(--weight_hover);
+}
.slang-type.color {
color: var(--color);
}
+.slang-type.color_hover:hover {
+color: var(--color_hover);
+}
@media(min-width: 768px) {
.slang-type.weight-tablet {
font-weight: var(--weight-tablet);
}
+.slang-type.weight-tablet_hover:hover {
+font-weight: var(--weight-tablet_hover);
+}
.slang-type.color-tablet {
color: var(--color-tablet);
}
+.slang-type.color-tablet_hover:hover {
+color: var(--color-tablet_hover);
+}
}
@media(min-width: 1024px) {
.slang-type.weight-desktop {
font-weight: var(--weight-desktop);
}
+.slang-type.weight-desktop_hover:hover {
+font-weight: var(--weight-desktop_hover);
+}
.slang-type.color-desktop {
color: var(--color-desktop);
}
+.slang-type.color-desktop_hover:hover {
+color: var(--color-desktop_hover);
+}
}
\ No newline at end of file
diff --git a/docs/components/theme.tsx b/docs/components/theme.tsx
index 9971902..9cd079b 100644
--- a/docs/components/theme.tsx
+++ b/docs/components/theme.tsx
@@ -3,16 +3,17 @@ import { Box, BoxProps, Type, TypeProps } from "slang";
import styles from "./theme.module.scss";
const sharedCodeStyle: Partial = {
- rad: 1,
- background: "palette-white-3",
+ rad: 2,
+ background: "palette-black-1",
+ color: "palette-white-1",
};
export function Code(props: BoxProps) {
return (
@@ -33,7 +34,7 @@ export function InlineCode(props: BoxProps) {
}
export function Section(props: BoxProps) {
- return ;
+ return ;
}
export function Page(props: BoxProps) {
@@ -41,9 +42,9 @@ export function Page(props: BoxProps) {
}
export function Title(props: TypeProps) {
- return ;
+ return ;
}
export function Subtitle(props: TypeProps) {
- return ;
+ return ;
}
diff --git a/docs/pages/_app.tsx b/docs/pages/_app.tsx
index dd6ca4a..56b09c8 100644
--- a/docs/pages/_app.tsx
+++ b/docs/pages/_app.tsx
@@ -2,8 +2,11 @@ import "../styles/globals.css";
import "../components/slang/slang.css";
import DocsLayout from "../components/DocsLayout";
import Head from "next/head";
+import { useRouter } from "next/router";
function MyApp({ Component, pageProps }) {
+ const { pathname } = useRouter();
+ const withLayout = !(pathname === "/");
return (
<>
@@ -14,10 +17,13 @@ function MyApp({ Component, pageProps }) {
src="https://plausible.io/js/plausible.js"
/>
-
- {/*
+ {withLayout ? (
+
+
+
+ ) : (
- */}
+ )}
>
);
}
diff --git a/docs/pages/box.tsx b/docs/pages/box.tsx
index 85a198e..19f8090 100644
--- a/docs/pages/box.tsx
+++ b/docs/pages/box.tsx
@@ -1,4 +1,11 @@
-import { Code, InlineCode, Page, Section } from "components/theme";
+import {
+ Code,
+ InlineCode,
+ Page,
+ Section,
+ Subtitle,
+ Title,
+} from "components/theme";
import React from "react";
import { Type, Box } from "slang";
@@ -6,9 +13,7 @@ export default function BoxPage() {
return (
-
- Box
-
+ Box
The box is the swiss-army-knife of layout in Slang. Because it does so
much, I thought instead of organizing this page around what the box
@@ -18,9 +23,7 @@ export default function BoxPage() {
-
- The Right Height
-
+ The Right Height
It can be difficult to get your app to be the right height. As best we
can tell, it's beneficial for every site to be at least the
@@ -51,6 +54,7 @@ export default function BoxPage() {
content (blogs), and h for SPA's.
+ Test
);
}
diff --git a/docs/pages/.index.tsx b/docs/pages/test-index.tsx
similarity index 64%
rename from docs/pages/.index.tsx
rename to docs/pages/test-index.tsx
index 22f50cb..a28b57f 100644
--- a/docs/pages/.index.tsx
+++ b/docs/pages/test-index.tsx
@@ -1,22 +1,23 @@
-import { Code, InlineCode, Page, Section, Title } from "../components/theme";
-import { Type, Box } from "slang";
+import {
+ InlineCode,
+ Page,
+ Section,
+ Subtitle,
+ Title,
+} from "../components/theme";
+import { Type } from "slang";
import React from "react";
-import Link from "next/link";
export default function Home() {
return (
Slang
-
- Welcome! This the documentation for the open source UI component
- library called Slang. It's not quite ready to use but it will be soon.
-
- Stay tuned, there's more to come! 🍿
-
-
-
- Why?
+ Open-source UI framework for rapid development.
+
+ Slang is a component library with a small set of swiss-army-knife-like
+ components coupled with a CSS generation pipeline. Slang is mainly
+ built with DX in mind.
The idea driving Slang is that we can do a large part of what's needed
@@ -26,9 +27,7 @@ export default function Home() {
In additon to that, Slang is:
-
- ✅ CSS First
-
+ ✅ CSS First
The internet has a had a zero-runtime approach to styling since 1996.
@@ -41,9 +40,7 @@ export default function Home() {
-
- ✅ Continuous By Design
-
+ ✅ Continuous By Design
Although there are plenty of reasons we still need media queries,
there is a lot to be gained by making our designs more fluid at the
@@ -52,9 +49,6 @@ export default function Home() {
better use of screen-space over a broader range of devices.
-
- Cool Button!
-
);
}
diff --git a/docs/pages/type.tsx b/docs/pages/type.tsx
index 8419157..3f9908c 100644
--- a/docs/pages/type.tsx
+++ b/docs/pages/type.tsx
@@ -1,12 +1,10 @@
-import { Section } from "components/theme";
+import { Section, Title } from "components/theme";
import { Type } from "slang";
export default function TypePage() {
return (
-
- Type
-
+ Type
This is the type page.
);
diff --git a/slang/src/Box/Box.tsx b/slang/src/Box/Box.tsx
index b55680d..203fda4 100644
--- a/slang/src/Box/Box.tsx
+++ b/slang/src/Box/Box.tsx
@@ -1,9 +1,10 @@
import React, { Ref } from "react";
import {
- ResponsifyComponentProps,
+ Responsify,
PropsWithAs,
produceComponentClassesPropsGetter,
separateComponentProps,
+ Hoverify,
} from "../utils";
import "./Box.css";
import { boxConfig, propKeys, ResponsiveProps } from "./props";
@@ -11,9 +12,9 @@ import { boxConfig, propKeys, ResponsiveProps } from "./props";
export type BaseBoxProps<
Breakpoint extends string = "tablet" | "desktop",
Colors extends string = "foreground" | "background"
-> = ResponsifyComponentProps, Breakpoint>;
+> = Responsify>, Breakpoint>;
-const componentKeys = [...propKeys, "at"];
+const componentKeys = [...propKeys, "at", "hover"];
const getCssClasses = produceComponentClassesPropsGetter<
BaseBoxProps,
diff --git a/slang/src/Box/props.ts b/slang/src/Box/props.ts
index d933b0e..8aaf1e7 100644
--- a/slang/src/Box/props.ts
+++ b/slang/src/Box/props.ts
@@ -38,6 +38,8 @@ export interface ResponsiveProps<
items?: string;
self?: string;
gap?: number;
+ columnGap?: number;
+ rowGap?: number;
flow?: "column" | "row";
display?: boolean | string;
@@ -66,6 +68,7 @@ export interface ResponsiveProps<
// Colors
background?: Colors;
+ color?: Colors;
}
// Must include all Keys!!
@@ -90,6 +93,9 @@ export const propKeys = [
"root",
"rad",
"background",
+ "color",
+ "columnGap",
+ "rowGap",
];
export const boxConfig: ComponentConfig[] = [
@@ -146,6 +152,16 @@ export const boxConfig: ComponentConfig[] = [
defaultValue: "0",
cssFromVariable: (v) => `gap: calc(var(--spacer-px) * ${v});`,
},
+ {
+ key: "columnGap",
+ defaultValue: "0",
+ cssFromVariable: (v) => `column-gap: calc(var(--spacer-px) * ${v});`,
+ },
+ {
+ key: "rowGap",
+ defaultValue: "0",
+ cssFromVariable: (v) => `row-gap: calc(var(--spacer-px) * ${v});`,
+ },
{
key: "template",
defaultValue: "none / none",
@@ -207,6 +223,12 @@ export const boxConfig: ComponentConfig[] = [
cssFromVariable: (v) => `background-color: ${v};`,
propValueToCssValue: (s) => s && `var(--${s})`,
},
+ {
+ key: "color",
+ defaultValue: "var(--color)",
+ cssFromVariable: (v) => `color: ${v};`,
+ propValueToCssValue: (s) => s && `var(--${s})`,
+ },
{
key: "contain",
defaultValue: "var(--base-container-size-px)",
diff --git a/slang/src/Type/Type.tsx b/slang/src/Type/Type.tsx
index 14e3dfa..cfbebbf 100644
--- a/slang/src/Type/Type.tsx
+++ b/slang/src/Type/Type.tsx
@@ -1,9 +1,10 @@
import React, { Ref } from "react";
import "./Type.scss";
import {
+ Hoverify,
produceComponentClassesPropsGetter,
PropsWithAs,
- ResponsifyComponentProps,
+ Responsify,
separateComponentProps,
} from "../utils";
import { typeConfig, ResponsiveProps, propKeys } from "./props";
@@ -11,7 +12,7 @@ import { typeConfig, ResponsiveProps, propKeys } from "./props";
export interface BaseTypeProps<
Breakpoint extends string = "tablet" | "desktop",
Colors extends string = "foreground" | "background"
-> extends ResponsifyComponentProps, Breakpoint> {
+> extends Responsify>, Breakpoint> {
size?: number;
}
diff --git a/slang/src/createComponentCss.ts b/slang/src/createComponentCss.ts
new file mode 100644
index 0000000..f08f06d
--- /dev/null
+++ b/slang/src/createComponentCss.ts
@@ -0,0 +1,96 @@
+import { SlangConfig, defaultConfig, componentClassesConfig } from "./config";
+import { SAFARI_PATCH_KEY } from "./constants";
+
+export function createComponentCss(userConfig?: Partial): string {
+ let cssLines: string[] = [""];
+ const config = { ...defaultConfig, ...userConfig };
+
+ // Loop over each component's responsive property list
+ for (const [className, configList] of Object.entries(
+ componentClassesConfig,
+ )) {
+ // Loop over each property
+ for (const prop of configList) {
+ cssLines = cssLines.concat(
+ `.${className}.${prop.key.toString()} {`,
+ prop.cssFromVariable(`var(--${prop.key.toString()})`),
+ `}`,
+ );
+
+ // add hover
+ cssLines = cssLines.concat(
+ `.${className}.${prop.key.toString()}_hover:hover {`,
+ prop.cssFromVariable(`var(--${prop.key.toString()}_hover)`),
+ `}`,
+ );
+
+ // Check for safari patch and do the same
+ if ("iosSafariPatch" in prop) {
+ cssLines = cssLines.concat(
+ "@supports (-webkit-touch-callout: none) {",
+ `.${className}.${prop.key.toString()}-${SAFARI_PATCH_KEY} {`,
+ prop.cssFromVariable(
+ `var(--${prop.key.toString()}-${SAFARI_PATCH_KEY})`,
+ ),
+ "}",
+ "}",
+ );
+ }
+ }
+
+ // Loop over each breakpoint
+ for (const [breakpoint, size] of Object.entries(config.breakpoints)) {
+ cssLines = cssLines.concat([
+ `@media(min-width: ${size}px) {`,
+ ...configList.reduce(
+ (acc, p) =>
+ acc.concat([
+ `.${className}.${p.key.toString()}-${breakpoint} {`,
+ p.cssFromVariable(`var(--${p.key.toString()}-${breakpoint})`),
+ `}`,
+ // hover
+ `.${className}.${p.key.toString()}-${breakpoint}_hover:hover {`,
+ p.cssFromVariable(
+ `var(--${p.key.toString()}-${breakpoint}_hover)`,
+ ),
+ `}`,
+ ]),
+ [],
+ ),
+ `}`,
+ ]);
+ }
+ }
+
+ return cssLines.join("\n");
+}
+
+/*
+- root class, classes to apply (replacing properties)
+- for each class:
+ -
+
+
+what is the real point of scoping these classes under a given main class?
+to ensure that they perform their supposed duty. but really maybe it's more of a many-to-many dependency graph
+that ensure that a specific class performs its duty.
+for instance if you add gap then it will automatically add display grid or flex or whatever is needed
+
+the logic is like
+
+for any given class-property module, it either accomplishes what it sets out to accomplish OR
+there is one or more smallest sets which are also needed to accomplish the function of the class-property-module CPM
+so it automatically applies the other class
+
+i guess the question is when do we finally apply those styles to a component?
+if the CPM is functionally self-contained. can it truly be used on any element?
+do we use the CSS types to know if an element can truly perform the task of the type :\
+
+there's a class
+ and it does two things:
+ - its a function of (one or more css properties) => the css to accomplish it
+ - and a function that maps from (what you pass to a component) => to what value gets set on the css property value
+
+
+
+*/
diff --git a/slang/src/createResponsiveCss.ts b/slang/src/createResponsiveCss.ts
deleted file mode 100644
index e8adcaf..0000000
--- a/slang/src/createResponsiveCss.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import { SlangConfig, defaultConfig, componentClassesConfig } from "./config";
-import { SAFARI_PATCH_KEY } from "./constants";
-
-export function createResponsiveCss(userConfig?: Partial): string {
- let cssLines: string[] = [""];
- const config = { ...defaultConfig, ...userConfig };
-
- // Loop over each component's responsive property list
- for (const [className, configList] of Object.entries(
- componentClassesConfig,
- )) {
- // Loop over each property
- for (const prop of configList) {
- cssLines = cssLines.concat(
- `.${className}.${prop.key.toString()} {`,
- prop.cssFromVariable(`var(--${prop.key.toString()})`),
- `}`,
- );
-
- // Check for safari patch and do the same
- if ("iosSafariPatch" in prop) {
- cssLines = cssLines.concat(
- "@supports (-webkit-touch-callout: none) {",
- `.${className}.${prop.key.toString()}-${SAFARI_PATCH_KEY} {`,
- prop.cssFromVariable(
- `var(--${prop.key.toString()}-${SAFARI_PATCH_KEY})`,
- ),
- "}",
- "}",
- );
- }
- }
-
- // Loop over each breakpoint
- for (const [breakpoint, size] of Object.entries(config.breakpoints)) {
- cssLines = cssLines.concat([
- `@media(min-width: ${size}px) {`,
- ...configList.reduce(
- (acc, p) =>
- acc.concat([
- `.${className}.${p.key.toString()}-${breakpoint} {`,
- p.cssFromVariable(`var(--${p.key.toString()}-${breakpoint})`),
- `}`,
- ]),
- [],
- ),
- `}`,
- ]);
- }
- }
-
- return cssLines.join("\n");
-}
diff --git a/slang/src/makeCSS.ts b/slang/src/makeCSS.ts
index 40e4338..29a9797 100644
--- a/slang/src/makeCSS.ts
+++ b/slang/src/makeCSS.ts
@@ -1,11 +1,11 @@
-import { createResponsiveCss } from "./createResponsiveCss";
+import { createComponentCss } from "./createComponentCss";
import { defaultConfig, SlangConfig } from "./config";
export function makeCSS(config?: Partial) {
const cssProperties = createProperties(config);
const derivedProperties = createDerivedProperties(config);
const colorProperties = createColorProperties(config);
- const responsiveCss = createResponsiveCss(config);
+ const responsiveCss = createComponentCss(config);
return [":root {"]
.concat(
Object.entries({
diff --git a/slang/src/utils.ts b/slang/src/utils.ts
index 5e6289b..414f777 100644
--- a/slang/src/utils.ts
+++ b/slang/src/utils.ts
@@ -26,11 +26,11 @@ export function forwardRefWithAs(
>;
}
-type ResponsiveComponentProperty = {
+type ResponsiveComponentProperty = {
/**
* CSS Custom Property Name
*/
- key: keyof X;
+ key: keyof ResponsiveProperties;
/**
* Initial value, if prop is passed to component
@@ -50,7 +50,7 @@ type ResponsiveComponentProperty = {
* Custom logic in converting what the user passes
* into the component, into the value that will be assed to the custom property
*/
- propValueToCssValue?: (x: keyof X) => string | undefined;
+ propValueToCssValue?: (x: keyof ResponsiveProperties) => string | undefined;
/**
* Declares that a patch needs to be made to make ios safari behavior consistent
@@ -62,7 +62,7 @@ type ResponsiveComponentProperty = {
*/
iosSafariPatch?: {
cssFromVariable: (customProperty: string) => string;
- propValueToCssValue?: (x: keyof X) => string | undefined;
+ propValueToCssValue?: (x: keyof ResponsiveProperties) => string | undefined;
};
};
@@ -70,10 +70,17 @@ export type ComponentConfig = {
[T in keyof X]-?: ResponsiveComponentProperty;
}[keyof X];
-export type ResponsifyComponentProps = {
+export type Hoverify = {
+ hover?: Partial;
+} & CProps;
+
+export type Responsify = {
at?: Partial>;
} & CProps;
+// A prop accepts an object with pseudo states as well...
+export type AllowPseudo = T | { default?: T; hover?: T };
+
/**
* Returns a function, which takes the component's props
* and returns the components classes and css custom properties
@@ -83,7 +90,7 @@ export type ResponsifyComponentProps = {
* `const [cssProperties, dynamicClasses] = getComponentClassesProps(props);`
*/
export function produceComponentClassesPropsGetter(
- toReduce: any[],
+ configArray: any[],
) {
/*
function getComponentClassesProps(node: PropsWithAs, "div">): [React.CSSProperties, string[]]
@@ -95,7 +102,7 @@ export function produceComponentClassesPropsGetter(
return function getComponentClassesProps(
node: ComponentProps,
): [CSSProperties, string[]] {
- const [props, classes] = toReduce.reduce<[CSSProperties, string[]]>(
+ const [props, classes] = configArray.reduce<[CSSProperties, string[]]>(
(acc, prop) => {
const [properties, classes] = getIndividualChildCssProp<
ComponentProps,
@@ -129,23 +136,46 @@ function getIndividualChildCssProp<
node,
iosSafariPatch,
}: ComponentConfig & {
- node: ResponsifyComponentProps;
+ node: Responsify, Breakpoint>;
}): [Record, string[]] {
// Setup
const classes: string[] = [];
const properties = {} as Record;
let last = defaultValue;
+ // hover classes/properties need to be added at root & breakpoint sizes
+ function handleHover(
+ cProps: Partial>,
+ key: string | number | symbol,
+ breakpoint?: string,
+ ) {
+ // add return hover classes/properties or nothing
+ if ("hover" in cProps) {
+ const value = propValueToCssValue(cProps.hover?.[key]);
+ if (value) {
+ const thisKey = [key, breakpoint].filter(Boolean).join("-");
+ // add the class
+ classes.push(`${thisKey}_hover`);
+ // which activates the property value
+ properties[`--${thisKey}_hover`] = value;
+ }
+ }
+ }
+
// Setup default
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const v = propValueToCssValue(node?.[key]);
if (v) {
last = v;
+ // add the class
classes.push(key.toString());
+ // which activates the property value
properties[`--${key}`] = last;
}
+ handleHover(node, key);
+
if (iosSafariPatch && iosSafariPatch.propValueToCssValue) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
@@ -174,6 +204,8 @@ function getIndividualChildCssProp<
last = value;
}
properties[`--${key}-${breakpoint}`] = v;
+
+ handleHover(node.at[breakpoint], key, breakpoint);
}
}
return [properties, classes];