Skip to content

Commit

Permalink
Merge pull request #589 from LifeSG/uneditable-section-width
Browse files Browse the repository at this point in the history
Allow uneditable section to stretch full width
  • Loading branch information
weili-govtech authored Oct 9, 2024
2 parents 1828bb2 + 5900305 commit d6a0169
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 21 deletions.
6 changes: 3 additions & 3 deletions src/uneditable-section/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { UneditableSectionBase } from "./uneditable-section";
import { GridUl } from "./uneditable-section.styles";
import { UneditableItemSection } from "./item-section";
import { UneditableSectionItem } from "./section-item";
import { UneditableSectionBase } from "./uneditable-section";

export * from "./types";
export const UneditableSection = Object.assign(UneditableSectionBase, {
ItemSection: GridUl,
ItemSection: UneditableItemSection,
Item: UneditableSectionItem,
});
12 changes: 12 additions & 0 deletions src/uneditable-section/item-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react";
import { UneditableSectionItemSectionProps } from "./types";
import { GridUl } from "./uneditable-section.styles";

export const Component = (
{ stretch, ...otherProps }: UneditableSectionItemSectionProps,
ref: React.Ref<HTMLUListElement>
) => {
return <GridUl ref={ref} $stretch={stretch} {...otherProps} />;
};

export const UneditableItemSection = React.forwardRef(Component);
9 changes: 9 additions & 0 deletions src/uneditable-section/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from "react";
import { AlertProps } from "../alert";
import { MaskAttributeProps } from "../masked-input";

Expand Down Expand Up @@ -32,6 +33,12 @@ export interface UneditableSectionItemProps extends MaskAttributeProps {
alert?: AlertProps | undefined;
}

export interface UneditableSectionItemSectionProps
extends React.HTMLAttributes<HTMLUListElement> {
/** Specifies if contents should take up the full width of the section */
stretch?: boolean | undefined;
}

export interface UneditableSectionProps {
items?: UneditableSectionItemProps[] | undefined;
title?: string | undefined;
Expand All @@ -47,6 +54,8 @@ export interface UneditableSectionProps {
id?: string | undefined;
/** If specified false, the background will be transparent. Else it is grey by default */
background?: boolean | undefined;
/** Specifies if contents should take up the full width of the section */
stretch?: boolean | undefined;
/** The callback function when the mask icon is clicked */
onMask?: ((item: UneditableSectionItemProps) => void) | undefined;
/** The callback function when the unmask icon is clicked */
Expand Down
31 changes: 21 additions & 10 deletions src/uneditable-section/uneditable-section.styles.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import styled from "styled-components";
import styled, { css } from "styled-components";
import { Layout } from "../layout";
import { Color } from "../color";
import { MediaQuery } from "../media";
Expand All @@ -11,32 +11,44 @@ interface WrapperStyleProps {
$background: boolean;
}

interface ContentStyleProps {
$stretch: boolean;
}

// =============================================================================
// STYLING
// =============================================================================
const columnWidthStyle = css<ContentStyleProps>`
grid-column: ${(props) => (props.$stretch ? "1 / -1" : "span 8")};
${MediaQuery.MaxWidth.mobileL} {
grid-column: 1 / -1;
}
`;

export const Wrapper = styled(Layout.Content)<WrapperStyleProps>`
background: ${({ $background }) =>
$background ? Color.Neutral[7] : "transparent"};
padding-top: 2rem;
padding-bottom: 2rem;
`;

export const Title = styled(Text.H3)`
export const Title = styled(Text.H3)<ContentStyleProps>`
margin-bottom: 1rem;
grid-column: span 8;
${columnWidthStyle}
`;

export const Description = styled(Text.Body)`
export const Description = styled(Text.Body)<ContentStyleProps>`
margin-bottom: 2rem;
grid-column: span 8;
${columnWidthStyle}
`;

export const CustomSection = styled.div`
grid-column: span 8;
export const CustomSection = styled.div<ContentStyleProps>`
${columnWidthStyle}
`;

export const GridUl = styled.ul`
grid-column: span 8;
export const GridUl = styled.ul<ContentStyleProps>`
${columnWidthStyle}
column-gap: 2rem;
row-gap: 2rem;
display: grid;
Expand All @@ -47,7 +59,6 @@ export const GridUl = styled.ul`
}
${MediaQuery.MaxWidth.mobileL} {
grid-column: 0 / span 4;
column-gap: 1rem;
grid-template-columns: repeat(4, minmax(0, 1fr));
}
Expand Down
17 changes: 12 additions & 5 deletions src/uneditable-section/uneditable-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const UneditableSectionBase = ({
bottomSection,
children,
background = true,
stretch,
onMask,
onUnmask,
onTryAgain,
Expand Down Expand Up @@ -53,7 +54,7 @@ export const UneditableSectionBase = ({
);
});

return <GridUl>{renderedItems}</GridUl>;
return <GridUl $stretch={stretch}>{renderedItems}</GridUl>;
}

return null;
Expand All @@ -66,16 +67,22 @@ export const UneditableSectionBase = ({

return (
<>
{title && <Title weight="semibold">{title}</Title>}
{description && <Description>{description}</Description>}
{title && (
<Title weight="semibold" $stretch={stretch}>
{title}
</Title>
)}
{description && (
<Description $stretch={stretch}>{description}</Description>
)}
{topSection && (
<CustomSection data-id="top-section">
<CustomSection data-id="top-section" $stretch={stretch}>
{topSection}
</CustomSection>
)}
{renderItems()}
{bottomSection && (
<CustomSection data-id="bottom-section">
<CustomSection data-id="bottom-section" $stretch={stretch}>
{bottomSection}
</CustomSection>
)}
Expand Down
16 changes: 16 additions & 0 deletions stories/uneditable-section/props-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ const MAIN_DATA: ApiTableSectionProps[] = [
propTypes: ["boolean"],
defaultValue: "true",
},
{
name: "stretch",
description:
"Specifies if contents should take up the full width of the section",
propTypes: ["boolean"],
},
{
name: "onMask",
description: "Called when the mask icon is clicked",
Expand Down Expand Up @@ -202,6 +208,16 @@ const SECTION_DATA: ApiTableSectionProps[] = [
</>
),
},
{
name: "stretch",
description: (
<>
Specifies if contents should take up the full width of
the <code>UneditableSection</code>
</>
),
propTypes: ["boolean"],
},
],
},
];
Expand Down
9 changes: 8 additions & 1 deletion stories/uneditable-section/uneditable-section.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Canvas, Meta } from "@storybook/blocks";
import { Heading3, Secondary, Title } from "../storybook-common";
import * as UneditableSectionStories from "./uneditable-section.stories";
import { PropsTable } from "./props-table";
import * as UneditableSectionStories from "./uneditable-section.stories";

<Meta of={UneditableSectionStories} />

Expand Down Expand Up @@ -75,6 +75,13 @@ to render the details at any position you intend.

<Canvas of={UneditableSectionStories.ComposingFromScratch} />

<Heading3>Stretch</Heading3>

If rendering this inside of another container, the contents can take up the full
width using the `stretch` prop.

<Canvas of={UneditableSectionStories.Stretch} />

<Secondary>Component API</Secondary>

<PropsTable />
20 changes: 18 additions & 2 deletions stories/uneditable-section/uneditable-section.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
import { Alert } from "src/alert";
import { BoxContainer } from "src/box-container";
import { Button } from "src/button";
import { Text } from "src/text";
import {
UneditableSection,
UneditableSectionItemMaskState,
UneditableSectionItemProps,
} from "src/uneditable-section";
import { SAMPLE_ITEMS } from "./doc-elements";
import { useState } from "react";

type Component = typeof UneditableSection;

Expand Down Expand Up @@ -354,3 +354,19 @@ export const ComposingFromScratch: StoryObj<Component> = {
);
},
};

export const Stretch: StoryObj<Component> = {
render: () => {
return (
<BoxContainer title="Review" collapsible={false}>
<UneditableSection
title="Your personal information"
description="Retrieved on 27 Jun 2023"
items={SAMPLE_ITEMS}
background={false}
stretch
/>
</BoxContainer>
);
},
};

0 comments on commit d6a0169

Please sign in to comment.