feat(SW-441): Added table block component

This commit is contained in:
Erik Tiekstra
2024-10-04 11:51:39 +02:00
committed by Pontus Dreij
parent ef411b4cf9
commit dfd40aa7aa
23 changed files with 431 additions and 29 deletions

View File

@@ -0,0 +1,35 @@
"use client"
import { useMemo } from "react"
import useScrollShadows from "@/hooks/useScrollShadows"
import { ScrollWrapperProps } from "./scrollWrapper"
import styles from "./scrollWrapper.module.css"
export default function ScrollWrapper({
className,
children,
}: ScrollWrapperProps) {
const { containerRef, showLeftShadow, showRightShadow } = useScrollShadows()
const classNames = useMemo(() => {
const cls = [styles.scrollWrapper, className]
if (showLeftShadow) {
cls.push(styles.leftShadow)
}
if (showRightShadow) {
cls.push(styles.rightShadow)
}
return cls.join(" ")
}, [showLeftShadow, showRightShadow, className])
return (
<div className={classNames}>
<div className={styles.content} ref={containerRef}>
{children}
</div>
</div>
)
}

View File

@@ -0,0 +1,33 @@
.scrollWrapper {
position: relative;
overflow: hidden;
}
.scrollWrapper::before,
.scrollWrapper::after {
content: "";
position: absolute;
top: 0;
height: 100%;
pointer-events: none;
z-index: 1;
transition: opacity 0.2s ease;
opacity: 0;
width: 50px;
}
.scrollWrapper.leftShadow::before {
left: 0;
background: linear-gradient(to right, rgba(0, 0, 0, 0.3), transparent);
opacity: 1;
}
.scrollWrapper.rightShadow::after {
right: 0;
background: linear-gradient(to left, rgba(0, 0, 0, 0.3), transparent);
opacity: 1;
}
.content {
overflow-x: auto;
}

View File

@@ -0,0 +1,2 @@
export interface ScrollWrapperProps
extends React.PropsWithChildren<React.HTMLAttributes<HTMLDivElement>> {}

View File

@@ -1,4 +0,0 @@
.container {
display: flex;
justify-content: center;
}

View File

@@ -5,18 +5,29 @@ import { useIntl } from "react-intl"
import { ChevronDownIcon } from "@/components/Icons"
import Button from "@/components/TempDesignSystem/Button"
import styles from "./button.module.css"
import { showMoreButtonVariants } from "./variants"
import type { ShowMoreButtonParams } from "@/types/components/myPages/stays/button"
import styles from "./showMoreButton.module.css"
import type { ShowMoreButtonProps } from "./showMoreButton"
export default function ShowMoreButton({
className,
intent,
disabled,
showLess,
loadMoreData,
}: ShowMoreButtonParams) {
const { formatMessage } = useIntl()
}: ShowMoreButtonProps) {
const intl = useIntl()
const classNames = showMoreButtonVariants({
className,
intent,
})
return (
<div className={styles.container}>
<div className={`${classNames} ${showLess ? styles.showLess : ""}`}>
<Button
className={styles.button}
disabled={disabled}
onClick={loadMoreData}
variant="icon"
@@ -24,8 +35,8 @@ export default function ShowMoreButton({
theme="base"
intent="text"
>
<ChevronDownIcon />
{formatMessage({ id: "Show more" })}
<ChevronDownIcon className={styles.icon} />
{intl.formatMessage({ id: showLess ? "Show less" : "Show more" })}
</Button>
</div>
)

View File

@@ -0,0 +1,23 @@
.container {
display: flex;
justify-content: center;
}
.table {
display: grid;
justify-content: stretch;
border-top: 1px solid var(--Base-Border-Subtle);
background-color: var(--Base-Surface-Primary-light-Normal);
}
.table .button {
border-radius: 0;
}
.icon {
transition: transform 0.3s;
}
.showLess .icon {
transform: rotate(180deg);
}

View File

@@ -0,0 +1,11 @@
import { showMoreButtonVariants } from "./variants"
import type { VariantProps } from "class-variance-authority"
export interface ShowMoreButtonProps
extends React.PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>,
VariantProps<typeof showMoreButtonVariants> {
disabled?: boolean
showLess?: boolean
loadMoreData: () => void
}

View File

@@ -0,0 +1,11 @@
import { cva } from "class-variance-authority"
import styles from "./showMoreButton.module.css"
export const showMoreButtonVariants = cva(styles.container, {
variants: {
intent: {
table: styles.table,
},
},
})

View File

@@ -1,7 +1,13 @@
import styles from "./table.module.css"
function TH({ children }: React.PropsWithChildren) {
return <th className={styles.th}>{children}</th>
import type { THeadProps } from "./table"
function TH({ children, width = "auto", ...props }: THeadProps) {
return (
<th className={styles.th} style={{ width }} {...props}>
{children}
</th>
)
}
export default TH

View File

@@ -1,13 +1,34 @@
import { TableProps } from "./table"
import TBody from "./TBody"
import TD from "./TD"
import TH from "./TH"
import THead from "./THead"
import TR from "./TR"
import { tableVariants } from "./variants"
import styles from "./table.module.css"
function Table({
className,
intent,
borderRadius,
variant,
layout,
width = "100%",
children,
...props
}: TableProps) {
const classNames = tableVariants({
className,
borderRadius,
intent,
layout,
variant,
})
function Table({ children }: React.PropsWithChildren) {
return <table className={styles.table}>{children}</table>
return (
<table className={classNames} style={{ width }} {...props}>
{children}
</table>
)
}
Table.THead = THead

View File

@@ -1,20 +1,20 @@
.table {
border-radius: var(--Corner-radius-Medium);
border-collapse: collapse;
overflow: hidden;
width: 100%;
min-width: 100%;
}
.thead {
background-color: var(--Base-Background-Secondary-Normal, #f7e1d5);
color: var(--Base-Text-High-contrast);
background-color: var(--Base-Surface-Primary-dark-Normal);
}
.tbody {
background-color: var(--Base-Surface-Primary-light-Normal, #fff);
background-color: var(--Base-Surface-Primary-light-Normal);
}
.tr:not(:last-of-type) {
border-bottom: 1px solid var(--Primary-Light-On-Surface-Divider, #f0c1b6);
border-bottom: 1px solid var(--Base-Border-Subtle);
}
.th {
@@ -28,6 +28,35 @@
padding: var(--Spacing-x2);
}
.fixed {
table-layout: fixed;
}
.smallRadius {
border-radius: var(--Corner-radius-Small);
}
.mediumRadius {
border-radius: var(--Corner-radius-Medium);
}
.largeRadius {
border-radius: var(--Corner-radius-Large);
}
.content .thead {
background-color: var(--Base-Surface-Subtle-Hover);
}
.content .tbody {
background-color: var(--Base-Background-Primary-Normal);
}
.content.striped .tbody .tr:nth-child(odd) {
background-color: var(--Base-Surface-Subtle-Normal);
}
.content.striped .tbody .tr:nth-child(even) {
background-color: var(--Base-Background-Primary-Normal);
}
@media screen and (min-width: 768px) {
.th {
padding: var(--Spacing-x2) var(--Spacing-x3);

View File

@@ -0,0 +1,14 @@
import { tableVariants } from "./variants"
import type { VariantProps } from "class-variance-authority"
export interface TableProps
extends React.PropsWithChildren<React.HTMLAttributes<HTMLTableElement>>,
VariantProps<typeof tableVariants> {
width?: string
}
export interface THeadProps
extends React.PropsWithChildren<React.HTMLAttributes<HTMLTableCellElement>> {
width?: string
}

View File

@@ -0,0 +1,27 @@
import { cva } from "class-variance-authority"
import styles from "./table.module.css"
export const tableVariants = cva(styles.table, {
variants: {
intent: {
light: styles.light,
striped: styles.striped,
},
variant: {
content: styles.content,
},
borderRadius: {
none: "",
small: styles.smallRadius,
medium: styles.mediumRadius,
large: styles.largeRadius,
},
layout: {
fixed: styles.fixed,
},
},
defaultVariants: {
borderRadius: "medium",
},
})