Skip to content

Commit

Permalink
migrate patterns
Browse files Browse the repository at this point in the history
remove react-day-picker

migrate patterns/color

remove background-color: white

sidebar: show index as primary

migrate patterns/form

nits

migrate patterns/icon

fix lint
  • Loading branch information
NgocNhi123 committed Jun 26, 2024
1 parent d950b0c commit 7cd039b
Show file tree
Hide file tree
Showing 33 changed files with 1,127 additions and 8 deletions.
1 change: 0 additions & 1 deletion core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
"dependencies": {
"@popperjs/core": "^2.11.8",
"@tippyjs/react": "^4.2.6",
"react-day-picker": "^8.10.1",
"react-hot-toast": "^2.4.1",
"react-icons": "^5.2.1",
"react-popper": "^2.3.0"
Expand Down
1 change: 0 additions & 1 deletion core/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ const bundleMain = {
external: [
"@tippyjs/react/headless",
"focus-visible",
"react-day-picker/DayPickerInput",
"react-dom",
"react-hot-toast",
"react-icons/go",
Expand Down
5 changes: 2 additions & 3 deletions core/src/date-input/date-input.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// TODO: Rewrite date input using the new DayPicker component
import { ReactElement } from "react";
import { DayPicker } from "react-day-picker";

// TODO: Rewrite date input using the new DayPicker component from react-day-picker
export const DateInput = (): ReactElement => {
return <DayPicker />;
return <input type="date" />;
};

// import { ReactNode, useState } from "react";
Expand Down
2 changes: 2 additions & 0 deletions new-docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
"dependencies": {
"@types/react": "latest",
"color": "^4.2.3",
"formik": "^2.4.6",
"react": "latest",
"react-dom": "latest",
"react-hook-form": "^7.52.0",
"typescript": "latest",
"vocs": "latest"
},
Expand Down
34 changes: 34 additions & 0 deletions new-docs/pages/patterns/color/background.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ColorBackground } from "./background/background";

# Background Color

The `background` utility contains classes that set the
[CSS `background-color`][1] property. This is the recommended way to set
background color since they automatically change based on the current theme.

```ts
import { background } from "@moai/core";

<div className={background.weak}>Text</div>;
```

There are only 2 colors in the `background` utility at the moment:

<ColorBackground rows={[{ key: "weak" }, { key: "strong" }]} />

The `weak` value sets a light gray background on light theme and a daker
background on dark theme. It should be used for underlying backgrounds, like
the background of your app. It can also be used to separate an area, such as
the header of a table.

The `strong` value sets a white background on light theme and a lighter
background on dark theme. It should be used for elevated containers, such as
panes, toolbars or popovers.

## See also

- The [Pane][2] component uses `strong` background along with border and shadow
to better elevate contents.

[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/background-color
[2]: /components/pane
11 changes: 11 additions & 0 deletions new-docs/pages/patterns/color/background/background.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.name {
font-family: "Source Code Pro", monospace;
width: 160px;
min-width: 160px;
}

.container {
overflow: auto;
white-space: nowrap;
border-width: 2px;
}
48 changes: 48 additions & 0 deletions new-docs/pages/patterns/color/background/background.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { border, background, Table, text } from "../../../../../core/src";
import { ColorSample } from "../sample/sample";
import s from "./background.module.css";

type BackgroundKey = keyof typeof background;

interface Row {
key: BackgroundKey;
}

const MakeColumn =
(theme: "light" | "dark", text: string) =>
(row: Row): JSX.Element => (
<div className={theme}>
<ColorSample
background={background[row.key]}
foreground={{ type: "text", cls: text, usage: "both" }}
/>
</div>
);

const LightStrong = MakeColumn("light", text.normal);
const LightWeak = MakeColumn("light", text.muted);
const DarkStrong = MakeColumn("dark", text.normal);
const DarkWeak = MakeColumn("dark", text.muted);

interface Props {
rows: Row[];
}

export const ColorBackground = (props: Props): JSX.Element => (
<div className={[s.container, border.weak].join(" ")}>
<Table<Row>
size={Table.sizes.small}
fixed={{ firstColumn: true }}
fill
rows={props.rows}
rowKey={(row) => row.key}
columns={[
{ title: "Name", className: s.name, render: "key" },
{ title: "Light", render: LightStrong },
{ title: "Light (muted)", render: LightWeak },
{ title: "Dark", render: DarkStrong },
{ title: "Dark (muted)", render: DarkWeak },
]}
/>
</div>
);
25 changes: 25 additions & 0 deletions new-docs/pages/patterns/color/border.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ColorBorder } from "./border/border";

# Border Color

The `border` utility contains classes that set the [CSS `border-color`][1]
property. This is the recommended way to set border color since they
automatically change based on the current theme.

Note that this only set the color. To have a border, you also need to set a
width, e.g. using the "border" class from Tailwind. You don't need to set the
border style since it's already default to "solid" in our [CSS reset][2].

```ts
import { border } from "@moai/core";

// The "border" class comes from Tailwind to set the border width
<div className={[border.weak, "border"].join(" ")}>Text</div>;
```

There are 2 colors in the `border` utility at the moment:

<ColorBorder rows={[{ key: "weak" }, { key: "strong" }]} />

[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/border-color
[2]: https://github.com/moaijs/moai/blob/739a87de82bd061bb41f38c5a51a410b59944a3d/lib/core/src/style/reset.css#L404-L417
11 changes: 11 additions & 0 deletions new-docs/pages/patterns/color/border/border.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.name {
font-family: "Source Code Pro", monospace;
width: 160px;
min-width: 160px;
}

.container {
overflow: auto;
white-space: nowrap;
border-width: 2px;
}
48 changes: 48 additions & 0 deletions new-docs/pages/patterns/color/border/border.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { background, border, Table } from "../../../../../core/src";
import { ColorSample } from "../sample/sample";
import s from "./border.module.css";

type BorderKey = keyof typeof border;

interface Row {
key: BorderKey;
}

const MakeColumn =
(theme: "light" | "dark", back: string) =>
(row: Row): JSX.Element => (
<div className={theme}>
<ColorSample
background={back}
foreground={{ type: "border", cls: border[row.key] }}
/>
</div>
);

const LightStrong = MakeColumn("light", background.strong);
const LightWeak = MakeColumn("light", background.weak);
const DarkStrong = MakeColumn("dark", background.strong);
const DarkWeak = MakeColumn("dark", background.weak);

interface Props {
rows: Row[];
}

export const ColorBorder = (props: Props): JSX.Element => (
<div className={s.container}>
<Table<Row>
size={Table.sizes.small}
fixed={{ firstColumn: true }}
fill
rows={props.rows}
rowKey={(row) => row.key}
columns={[
{ title: "Name", className: s.name, render: "key" },
{ title: "Light", render: LightStrong },
{ title: "Light (alt bg)", render: LightWeak },
{ title: "Dark", render: DarkStrong },
{ title: "Dark (alt bg)", render: DarkWeak },
]}
/>
</div>
);
16 changes: 16 additions & 0 deletions new-docs/pages/patterns/color/index.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Colors (index page)

For recommended color usages, see [Text][1], [Background][2], and [Border][3].
They provide accessible colors that are automatically changed based on the
current theme.

For colors that are persistent across themes, see [Static Colors][4].

For colors that have no semantic meaning and should be used for data
visualizations, see [Category Colors][5]

[1]: /patterns/color/text
[2]: /patterns/color/background
[3]: /patterns/color/border
[4]: /patterns/color/static
[5]: /patterns/color/category
17 changes: 17 additions & 0 deletions new-docs/pages/patterns/color/sample/sample.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.container {
padding: 12px;
width: 120px;
font-variant-numeric: "tabular-nums";
border-radius: 4px;

display: flex;
justify-content: space-between;
align-items: center;
}

.border {
width: 16px;
height: 16px;
border-radius: 16px;
border-width: 1px;
}
87 changes: 87 additions & 0 deletions new-docs/pages/patterns/color/sample/sample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import Color from "color";
import { useEffect, useRef, useState } from "react";
import { HiCheckCircle } from "react-icons/hi";
import {
CategoryColor,
categoryColors,
Icon,
Tag,
} from "../../../../../core/src";
import s from "./sample.module.css";

export type ColorSampleUsage = "text" | "icon" | "both";

interface Props {
background: string;
foreground:
| { type: "text"; cls: string; usage: ColorSampleUsage }
| { type: "border"; cls: string };
}

const getColor = (contrast: number): CategoryColor => {
const rounded = Math.round(contrast * 10) / 10;
if (rounded >= 4.5) return categoryColors.green;
if (rounded >= 3) return categoryColors.yellow;
return categoryColors.red;
};

const getContrast = (
props: Props,
backElement: HTMLDivElement,
foreElement: HTMLElement,
): number => {
const back = window.getComputedStyle(backElement).backgroundColor;
const foreStyle = window.getComputedStyle(foreElement);
const isText = props.foreground.type === "text";
// Only use long hand name.
// See: https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle#notes
const fore = foreStyle[isText ? "color" : "borderLeftColor"];
return Color(back).contrast(Color(fore));
};

const ColorIcon = (): JSX.Element => (
<Icon component={HiCheckCircle} size={16} display="inline" />
);

export const ColorSample = (props: Props): JSX.Element => {
const backRef = useRef<HTMLDivElement>(null);
const foreRef = useRef<HTMLElement>(null);
const [contrast, setContrast] = useState(0);

useEffect(() => {
window.setTimeout(() => {
const [back, fore] = [backRef.current, foreRef.current];
if (back === null) throw Error("backElm is null");
if (fore === null) throw Error("foreElm is null");
setContrast(getContrast(props, back, fore));
}, 0); // Wait for all styles are applied
}, [setContrast]);

return (
<div
ref={backRef}
className={[props.background, s.container].join(" ")}
>
{/* "background" also set color so the "fore" must be in another
element of the "back" */}
{props.foreground.type === "text" ? (
<span ref={foreRef} className={props.foreground.cls}>
{props.foreground.usage !== "icon" && <span>Aa</span>}
{props.foreground.usage === "both" && <span> </span>}
{props.foreground.usage !== "text" && <ColorIcon />}
</span>
) : (
<span
ref={foreRef}
className={[s.border, props.foreground.cls].join(" ")}
/>
)}
<span title="Color contrast" aria-label="Color contrast">
<Tag
color={getColor(contrast)}
children={contrast.toFixed(1)}
/>
</span>
</div>
);
};
52 changes: 52 additions & 0 deletions new-docs/pages/patterns/color/static.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ColorStaticGrid } from "./static/grid";

# Static Colors

Static colors are persistent across themes. They are the low-level palette
that Moai is built on top of. They ensure consistency across all parts of the
interface.

In practice, however, you usually don't need to use static colors directly.
Instead, use high-level utilities like [`text`][1], [`background`][2], and
[`border`][3] which provide dynamic colors that are changed based on the
current theme and [always accessible][4].

## Usage

Static colors are defined as [CSS variables][5] at [`root`][6]. They are
available everywhere in the app:

```css
.heading {
color: var(--highlight-5);
}
```

Since static colors are persistent across themes, you usually want to provide
the value for each theme manually:

```css
html.light .heading {
color: var(--highlight-6);
}
html.dark .heading {
color: var(--highlight-4);
}
```

In fact, the [implementations][7] of `text`, `background`, and `border`
utilities are good examples of handling colors in both light and dark themes.

## Colors

The below tables list all static colors in Moai and their variable names.

<ColorStaticGrid />

[1]: /patterns/color/text
[2]: /patterns/color/background
[3]: /patterns/color/border
[4]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast
[5]: https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
[6]: https://developer.mozilla.org/en-US/docs/Web/CSS/:root
[7]: https://github.com/moaijs/moai/blob/739a87de82bd061bb41f38c5a51a410b59944a3d/lib/core/src/text/text.module.css
Loading

0 comments on commit 7cd039b

Please sign in to comment.