Skip to content

Commit bd82a99

Browse files
spaenlehpyphilia
andauthored
fix: add alignment setting (#916)
* fix: add alignment setting * fix: sizing container * fix: add sizing stories * fix: update default behavior * fix: allow image to display bigger than the original size * fix: update sizing * fix: add dark variant to primary light * fix: adapt color * fix: use sdk version * fix: comment typo Co-authored-by: Kim Lan Phan Hoang <pyphilia@gmail.com> --------- Co-authored-by: Kim Lan Phan Hoang <pyphilia@gmail.com>
1 parent d80e43a commit bd82a99

File tree

11 files changed

+263
-199
lines changed

11 files changed

+263
-199
lines changed

package.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,14 @@
7575
},
7676
"dependencies": {
7777
"@ag-grid-community/client-side-row-model": "31.3.2",
78-
"@ag-grid-community/react": "^31.3.1",
79-
"@ag-grid-community/styles": "^31.3.1",
78+
"@ag-grid-community/react": "^31.3.2",
79+
"@ag-grid-community/styles": "^31.3.2",
8080
"@storybook/react-vite": "8.1.10",
8181
"http-status-codes": "2.3.0",
8282
"interweave": "13.1.0",
8383
"katex": "0.16.10",
8484
"lodash.truncate": "4.4.2",
85-
"lucide-react": "0.395.0",
85+
"lucide-react": "0.397.0",
8686
"react-cookie-consent": "9.0.0",
8787
"react-dnd": "16.0.1",
8888
"react-dnd-html5-backend": "16.0.1",
@@ -115,7 +115,7 @@
115115
"@emotion/cache": "~11.11.0",
116116
"@emotion/react": "11.11.4",
117117
"@emotion/styled": "11.11.5",
118-
"@graasp/sdk": "4.14.0",
118+
"@graasp/sdk": "4.15.0",
119119
"@mui/icons-material": "5.15.20",
120120
"@mui/lab": "5.0.0-alpha.170",
121121
"@mui/material": "5.15.20",
@@ -138,25 +138,25 @@
138138
"@types/jest": "29.5.12",
139139
"@types/katex": "^0.16.7",
140140
"@types/lodash.truncate": "4.4.9",
141-
"@types/node": "20.14.8",
141+
"@types/node": "20.14.9",
142142
"@types/react": "18.3.3",
143143
"@types/react-dom": "18.3.0",
144144
"@types/react-router-dom": "5.3.3",
145145
"@types/react-text-mask": "5.4.14",
146146
"@types/stylis": "4.2.6",
147-
"@types/uuid": "9.0.8",
148-
"@typescript-eslint/eslint-plugin": "7.13.0",
149-
"@typescript-eslint/parser": "7.13.0",
147+
"@types/uuid": "10.0.0",
148+
"@typescript-eslint/eslint-plugin": "7.14.1",
149+
"@typescript-eslint/parser": "7.14.1",
150150
"@vitejs/plugin-react": "4.3.1",
151151
"concurrently": "8.2.2",
152152
"cross-env": "7.0.3",
153153
"eslint": "^8.57.0",
154154
"eslint-config-prettier": "^9.1.0",
155155
"eslint-plugin-import": "^2.29.1",
156-
"eslint-plugin-jsx-a11y": "6.8.0",
156+
"eslint-plugin-jsx-a11y": "6.9.0",
157157
"eslint-plugin-n": "17.9.0",
158158
"eslint-plugin-prettier": "^5.1.3",
159-
"eslint-plugin-promise": "^6.1.1",
159+
"eslint-plugin-promise": "^6.2.0",
160160
"http-server": "14.1.1",
161161
"husky": "9.0.11",
162162
"jest": "29.7.0",

src/Card/components/CardThumbnail.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const CardThumbnail = ({
3535
display='flex'
3636
alignItems='center'
3737
justifyContent='center'
38-
bgcolor={DEFAULT_LIGHT_PRIMARY_COLOR}
38+
bgcolor={DEFAULT_LIGHT_PRIMARY_COLOR.main}
3939
width={CARD_HEIGHT}
4040
height='100%'
4141
flexShrink={0}

src/items/FileImage.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
1-
export interface FileImageProps {
1+
export type FileImageProps = {
22
alt: string;
33
url?: string;
44
id?: string;
5-
}
5+
};
66

77
const FileImage = ({ id, url, alt }: FileImageProps): JSX.Element => {
88
return (
9-
<img id={id} src={url} alt={alt} title={alt} style={{ maxWidth: '100%' }} />
9+
<img
10+
id={id}
11+
src={url}
12+
alt={alt}
13+
title={alt}
14+
style={{
15+
// do not overflow the parent
16+
maxWidth: '100%',
17+
// display bigger than the original size if the parent wants it
18+
width: '100%',
19+
}}
20+
/>
1021
);
1122
};
1223

src/items/FileItem.tsx

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Box, Container, SxProps } from '@mui/material';
1+
import { Box, SxProps } from '@mui/material';
22
import Alert from '@mui/material/Alert';
33
import Skeleton from '@mui/material/Skeleton';
44

@@ -22,9 +22,10 @@ import FileAudio from './FileAudio';
2222
import FileImage from './FileImage';
2323
import FilePdf from './FilePdf';
2424
import FileVideo from './FileVideo';
25+
import { SizingWrapper } from './SizingWrapper';
2526
import withCaption from './withCaption';
2627

27-
export interface FileItemProps {
28+
export type FileItemProps = {
2829
/**
2930
* blob content of the file, overridden by fileUrl
3031
* */
@@ -47,7 +48,7 @@ export interface FileItemProps {
4748
showCollapse?: boolean;
4849
sx?: SxProps;
4950
onClick?: () => void;
50-
}
51+
};
5152

5253
const FileItem = ({
5354
content,
@@ -159,6 +160,12 @@ const FileItem = ({
159160

160161
let fileItem = getComponent();
161162

163+
fileItem = (
164+
<SizingWrapper size={item.settings.maxWidth ?? MaxWidth.Medium}>
165+
{fileItem}
166+
</SizingWrapper>
167+
);
168+
162169
// display element with caption
163170
if (showCaption) {
164171
fileItem = withCaption({
@@ -170,20 +177,7 @@ const FileItem = ({
170177
fileItem = withCollapse({ item })(fileItem);
171178
}
172179

173-
// the container allows to resize the file to a given responsive standard
174-
// There is a tradeoff because of the description:
175-
// - description does not look good when align to the left while the file is centered
176-
// - description does not look good when centered/cut alongside the centered file
177-
return (
178-
<Container
179-
disableGutters
180-
// m=0 align the file to the left.
181-
sx={{ m: 0, ...sx }}
182-
maxWidth={item.settings.maxWidth ?? MaxWidth.ExtraLarge}
183-
>
184-
{fileItem}
185-
</Container>
186-
);
180+
return fileItem;
187181
};
188182

189183
export default React.memo(FileItem);

src/items/FileVideo.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { SxProps, styled } from '@mui/material';
22

33
import { FC } from 'react';
44

5-
interface FileVideoProps {
5+
type FileVideoProps = {
66
id?: string;
77
url?: string;
88
sx?: SxProps;
9-
}
9+
};
1010

1111
const StyledVideo = styled('video')({
1212
maxWidth: '100%',

src/items/SizingWrapper.stories.tsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { Meta, StoryObj } from '@storybook/react';
2+
3+
import { Container } from '@mui/material';
4+
5+
import { MaxWidth } from '@graasp/sdk';
6+
7+
import { SizingWrapper } from './SizingWrapper';
8+
9+
const children = <img width='100%' src='https://picsum.photos/1000' />;
10+
11+
const meta = {
12+
title: 'Items/SizingWrapper',
13+
component: SizingWrapper,
14+
decorators: [
15+
(Story) => {
16+
return <Container maxWidth='lg'>{Story()}</Container>;
17+
},
18+
],
19+
20+
args: {
21+
children,
22+
},
23+
argTypes: {
24+
size: {
25+
control: 'radio',
26+
options: Object.values(MaxWidth),
27+
},
28+
},
29+
} satisfies Meta<typeof SizingWrapper>;
30+
31+
export default meta;
32+
33+
type Story = StoryObj<typeof meta>;
34+
35+
export const Default = {
36+
args: {
37+
size: MaxWidth.Medium,
38+
},
39+
} satisfies Story;
40+
41+
export const TallImage = {
42+
args: {
43+
size: MaxWidth.Medium,
44+
children: <img width='100%' src='https://picsum.photos/1000/3000' />,
45+
},
46+
};
47+
48+
export const AllSizes = {
49+
render: () =>
50+
Object.values(MaxWidth).map((size) => (
51+
<SizingWrapper size={size} key={size}>
52+
{children}
53+
</SizingWrapper>
54+
)),
55+
};

src/items/SizingWrapper.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Box } from '@mui/material';
2+
3+
import { ReactNode } from 'react';
4+
5+
import { MaxWidth } from '@graasp/sdk';
6+
7+
const getWidthFromSizing = (size: MaxWidth): string => {
8+
switch (size) {
9+
case MaxWidth.ExtraSmall:
10+
return '100px';
11+
case MaxWidth.Small:
12+
return '200px';
13+
case MaxWidth.Medium:
14+
return '400px';
15+
case MaxWidth.Large:
16+
return '800px';
17+
case MaxWidth.ExtraLarge:
18+
default:
19+
return '100%';
20+
}
21+
};
22+
23+
export const SizingWrapper = ({
24+
size,
25+
children,
26+
}: {
27+
size: MaxWidth;
28+
children: ReactNode;
29+
}): JSX.Element => {
30+
const width = getWidthFromSizing(size);
31+
return (
32+
<Box maxWidth='100%' width={width}>
33+
{children}
34+
</Box>
35+
);
36+
};

src/items/withCaption.stories.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import type { Meta, StoryObj } from '@storybook/react';
22

3-
import { DescriptionPlacement, DescriptionPlacementType } from '@graasp/sdk';
3+
import {
4+
Alignment,
5+
AlignmentType,
6+
DescriptionPlacement,
7+
DescriptionPlacementType,
8+
} from '@graasp/sdk';
49

5-
import withCaption, { Alignment, AlignmentType } from './withCaption';
10+
import withCaption from './withCaption';
611

712
const renderComponent = ({
813
description,
@@ -45,3 +50,6 @@ export default meta;
4550
type Story = StoryObj<typeof renderComponent>;
4651

4752
export const CaptionOnImage = {} satisfies Story;
53+
export const CanteredCaption = {
54+
args: { alignment: Alignment.Center },
55+
} satisfies Story;

src/items/withCaption.tsx

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import TextDisplay from '@/TextDisplay/TextDisplay';
33
import { Stack } from '@mui/material';
44

55
import {
6+
AlignmentType,
67
DescriptionPlacement,
78
DescriptionPlacementType,
8-
UnionOfConst,
9+
getAlignItemsFromAlignmentSetting,
910
} from '@graasp/sdk';
1011

1112
const normalizeDescription = (value: string | null | undefined): string => {
@@ -21,28 +22,6 @@ const normalizeDescription = (value: string | null | undefined): string => {
2122
return value;
2223
};
2324

24-
// NOTE: This is experimental and most likely is going to be moved to sdk when implementing the feature
25-
export const Alignment = {
26-
Center: 'center',
27-
Left: 'left',
28-
Right: 'right',
29-
} as const;
30-
export type AlignmentType = UnionOfConst<typeof Alignment>;
31-
32-
const getAlignItemsFromAlignmentSetting = (
33-
alignment: AlignmentType,
34-
): 'flex-start' | 'flex-end' | 'center' => {
35-
switch (alignment) {
36-
case Alignment.Right:
37-
return 'flex-end';
38-
case Alignment.Center:
39-
return 'center';
40-
case Alignment.Left:
41-
default:
42-
return 'flex-start';
43-
}
44-
};
45-
4625
type WithCaptionItem = {
4726
description: string | null;
4827
settings?: {
@@ -60,7 +39,7 @@ function withCaption<T extends WithCaptionItem>({ item }: WithCaptionProps<T>) {
6039
const ChildComponent = (): JSX.Element => {
6140
const descriptionPlacement =
6241
item.settings?.descriptionPlacement ?? 'below';
63-
const alignmentSetting = item.settings?.alignment ?? Alignment.Left;
42+
const alignmentSetting = item.settings?.alignment;
6443
const direction =
6544
descriptionPlacement === DescriptionPlacement.ABOVE
6645
? 'column-reverse'

src/theme.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ export const DEFAULT_ACTIVE_ACTION_COLOR = '#777578';
1919
* Color used as a light version of the primary color for button and icon backgrounds.
2020
* For example in card thumbnails.
2121
*/
22-
export const DEFAULT_LIGHT_PRIMARY_COLOR = '#E4DFFF';
22+
export const DEFAULT_LIGHT_PRIMARY_COLOR = {
23+
main: 'hsl(249, 100%, 94%)',
24+
dark: 'hsl(249, 100%, 90%)',
25+
} as const;
2326

2427
/**
2528
* Very light purple color used as the default background color.

0 commit comments

Comments
 (0)