-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEAT] Marker 컴포넌트, 스토리북 #19
Changes from 5 commits
a14492b
230e5b6
c4064a0
fe6d819
3d2e9a0
cab22ef
9e98806
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,41 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/* eslint-disable no-restricted-exports */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import type { Meta, StoryObj } from '@storybook/react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { Marker } from '.'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const meta = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
title: 'components/common/Marker', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
component: Marker, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tags: ['autodocs'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} satisfies Meta<typeof Marker>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export default meta; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type Story = StoryObj<typeof Marker>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const categoryNames: Array< | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'restaurant' | 'cafe' | 'bar' | 'shopping' | 'travel' | 'public' | 'hospital' | 'other' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
> = ['restaurant', 'cafe', 'bar', 'shopping', 'travel', 'public', 'hospital', 'other']; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const Basic: Story = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
args: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
categoryName: 'restaurant', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
argTypes: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
categoryName: { control: { type: 'select' }, options: categoryNames }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
render: (args) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return <Marker {...args} />; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const ALL: Story = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
render: () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{categoryNames.map((item) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Marker key={item} categoryName={item} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
))} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance the ALL story with description and layout Add a description for the story and improve the layout to better showcase all variants. export const ALL: Story = {
+ parameters: {
+ docs: {
+ description: {
+ story: 'Displays all available marker categories in a grid layout.',
+ },
+ },
+ },
render: () => {
return (
- <>
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '1rem' }}>
{categoryNames.map((item) => (
<Marker key={item} categoryName={item} />
))}
- </>
+ </div>
);
},
}; 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { ComponentPropsWithoutRef } from 'react'; | ||
|
||
export type Props = { | ||
/** | ||
* category name to be displayed. | ||
*/ | ||
categoryName: | ||
| 'restaurant' | ||
| 'cafe' | ||
| 'bar' | ||
| 'shopping' | ||
| 'travel' | ||
| 'public' | ||
| 'hospital' | ||
| 'other'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider enhancing type safety and reusability. A few suggestions to improve the type definition:
Here's how you could improve it: import { ComponentPropsWithoutRef } from 'react';
+export const MARKER_CATEGORIES = {
+ RESTAURANT: 'restaurant',
+ CAFE: 'cafe',
+ BAR: 'bar',
+ SHOPPING: 'shopping',
+ TRAVEL: 'travel',
+ PUBLIC: 'public',
+ HOSPITAL: 'hospital',
+ OTHER: 'other',
+} as const;
+
+export type MarkerCategory = typeof MARKER_CATEGORIES[keyof typeof MARKER_CATEGORIES];
+
export type Props = {
/**
* category name to be displayed.
+ * @example
+ * ```tsx
+ * <Marker categoryName="restaurant" />
+ * ```
*/
- categoryName:
- | 'restaurant'
- | 'cafe'
- | 'bar'
- | 'shopping'
- | 'travel'
- | 'public'
- | 'hospital'
- | 'other';
+ categoryName: MarkerCategory;
} & ComponentPropsWithoutRef<'button'>; This approach:
|
||
} & ComponentPropsWithoutRef<'button'>; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,18 @@ | ||||||||||||||||||||
import MarkerIcon from '@/assets/icons/marker.svg'; | ||||||||||||||||||||
|
||||||||||||||||||||
import { Props } from './Marker.types'; | ||||||||||||||||||||
|
||||||||||||||||||||
import { Icon } from '../Icon'; | ||||||||||||||||||||
|
||||||||||||||||||||
export const Marker = ({ categoryName, ...props }: Props) => { | ||||||||||||||||||||
return ( | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add accessibility attributes to the button The button lacks accessibility attributes which are crucial for screen readers. Add an appropriate aria-label: -<button className="relative inline-block" {...props}>
+<button
+ aria-label={`${categoryName} location marker`}
+ className="relative inline-block"
+ {...props}
+> 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||
<button className="relative inline-block" {...props}> | ||||||||||||||||||||
<MarkerIcon /> | ||||||||||||||||||||
<Icon | ||||||||||||||||||||
name={categoryName} | ||||||||||||||||||||
size={35} | ||||||||||||||||||||
className={`absolute left-[51%] ${categoryName == 'restaurant' ? 'top-[55%]' : 'top-1/2'} -translate-x-1/2 -translate-y-1/2`} | ||||||||||||||||||||
/> | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider extracting magic numbers and improving maintainability The component has several hard-coded values that could be made more maintainable:
Consider creating constants or theme variables: +const ICON_SIZE = 35;
+const ICON_POSITIONS = {
+ default: { left: '51%', top: '50%' },
+ restaurant: { left: '51%', top: '55%' }
+} as const;
+
export const Marker = ({ categoryName, ...props }: Props) => {
+ const position = categoryName === 'restaurant'
+ ? ICON_POSITIONS.restaurant
+ : ICON_POSITIONS.default;
+
return (
<button className="relative inline-block" {...props}>
<MarkerIcon />
<Icon
name={categoryName}
- size={35}
- className={`absolute left-[51%] ${categoryName == 'restaurant' ? 'top-[55%]' : 'top-1/2'} -translate-x-1/2 -translate-y-1/2`}
+ size={ICON_SIZE}
+ className={`absolute left-[${position.left}] top-[${position.top}] -translate-x-1/2 -translate-y-1/2`}
/>
|
||||||||||||||||||||
</button> | ||||||||||||||||||||
); | ||||||||||||||||||||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
🛠️ Refactor suggestion
Now I have enough information to provide the final response:
The review suggestion is valid and important
The category names are currently defined in two places:
src/components/common/Marker/Marker.types.ts
src/components/common/Marker/Marker.stories.tsx
Moving these categories to a shared constants file would be beneficial because:
Example structure for the proposed constants file:
🔗 Analysis chain
Consider moving category names to a shared constants file
The category names array should be moved to a shared constants file (e.g.,
src/constants/categories.ts
) since these values are likely needed by both the Marker component and its stories. This ensures consistency and makes maintenance easier.Let's check if these categories are defined elsewhere:
Let me search for any usage of these category names individually to ensure we're not missing any other definitions or usages.
Let me check the content of Marker.types.ts to see how these categories are defined there, as it seems to be the main type definition file.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 122
Script:
Length of output: 2926
Script:
Length of output: 350