-
Notifications
You must be signed in to change notification settings - Fork 4
feat: added user avatar and story #127
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
Conversation
WalkthroughThis change introduces the initial setup for the Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UIComponent
participant Storybook
participant InlangPlugin
participant LocalizationFiles
User->>UIComponent: Uses Avatar/Button/Icon with props
UIComponent->>UIComponent: Applies Tailwind classes, renders SVG/images
User->>Storybook: Views component stories
Storybook->>UIComponent: Renders component variants
InlangPlugin->>LocalizationFiles: Loads/Saves JSON messages per locale
InlangPlugin->>InlangPlugin: Parses, imports, exports, and migrates messages
Assessment against linked issues
Possibly related PRs
Poem
Tip ⚡️ Faster reviews with caching
Enjoy the performance boost—your workflow just got faster. ✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
the component itself is perfect, but the pr seems to be adding files that already exist, pl. update to address the same
{ | ||
"useTabs": true, | ||
"singleQuote": true, | ||
"trailingComma": "none", | ||
"printWidth": 100, | ||
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], | ||
"overrides": [ | ||
{ | ||
"files": "*.svelte", | ||
"options": { | ||
"parser": "svelte" | ||
} |
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.
add this to package.json instead as we have it in that in other projects, the key is just straight up "prettier" instead
{ | ||
"$schema": "https://inlang.com/schema/project-settings", | ||
"modules": [ | ||
"https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js", | ||
"https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js" | ||
], | ||
"plugin.inlang.messageFormat": { | ||
"pathPattern": "../messages/{locale}.json" | ||
}, | ||
"baseLocale": "en", | ||
"locales": ["en", "es"] | ||
} |
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.
this has been removed, pl merge from main
@layer base { | ||
h1 { | ||
@apply font-geist text-xl/[1] font-semibold; | ||
} | ||
h2 { | ||
@apply font-geist text-lg/[1] font-medium; | ||
} | ||
h3 { | ||
@apply font-geist text-base/[1] font-normal; | ||
} | ||
p { | ||
@apply font-geist text-[15px]/[1] font-normal; | ||
} |
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.
you seem to be readding files that already exist
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.
Actionable comments posted: 11
🔭 Outside diff range comments (1)
platforms/metagram/project.inlang/cache/plugins/ygx0uiahq6uw (1)
1-17
: 🛠️ Refactor suggestion
⚠️ Potential issueDo not commit generated / cache plugin bundles – add the folder to
.gitignore
.This file is a minified bundle (≈ 8 000 LOC when prettified). Keeping such artifacts under VCS has several drawbacks:
- Repository bloat – large diffs & clone size.
- Noise in PRs – reviewers cannot meaningfully audit the code.
- High churn – every rebuild rewrites the file, triggering merge conflicts.
- Licence & security visibility – vendored code may hide vulnerabilities and licence obligations.
Please depend on the official
@inlang/*
packages (or pin an exact version inpackage.json
) and let the build step populate theproject.inlang/cache/plugins
directory locally/in CI.Proposed fix (root-level
.gitignore
):+# Inlang cache (generated) +platforms/metagram/project.inlang/cache/plugins/
♻️ Duplicate comments (2)
platforms/metagram/project.inlang/cache/plugins/2sy648wh9sugi (1)
1-2
:⚠️ Potential issueSame issue – generated cache artefact committed.
See the comment on
ygx0uiahq6uw
. This second bundle (~30 000 LOC) compounds the problems and should be excluded from version control together with the entireproject.inlang/cache/plugins
subtree.platforms/metagram/.prettierrc (1)
1-15
: Prettier config placement
You’ve defined Prettier settings in a standalone.prettierrc
. In other Metagram projects, we’ve centralized Prettier config under the"prettier"
key inpackage.json
. Consider consolidating here for consistency across repositories.
🧹 Nitpick comments (25)
platforms/metagram/src/lib/index.ts (1)
1-3
: Placeholder barrel file is correctly initialized.
This stub establishes the$lib
alias without exporting anything yet, which is acceptable for now. Consider centralizing your new UI components here to simplify imports (e.g.,Avatar
,Button
, etc.).export {}; +// Optional: re-export common modules for cleaner imports +// export { default as Avatar } from './ui/avatar/Avatar.svelte'; +// export { default as Button } from './ui/button/Button.svelte';platforms/metagram/src/lib/types.ts (1)
3-6
: Consider adding JSDoc for clarityAdding a brief JSDoc comment above
ISvgProps
can help future consumers understand the intended units (px vs. CSS strings) and usage examples:/** * SVG icon props. * @property size - width & height (number = pixels or CSS string). * @property color - fill color (CSS color string). */ export interface ISvgProps extends SVGAttributes<SVGElement> { size?: number | string; color?: string; }platforms/metagram/src/lib/icons/Icons.svelte (1)
5-13
: Enhance accessibility with ARIA attributes
This component renders a set of decorative icons. To improve screen reader experience, consider:
- Wrapping the icons in a container with
role="group"
and a descriptivearia-label
.- Marking each decorative icon with
aria-hidden="true"
.Example diff:
<div class="flex flex-wrap items-center gap-2" role="group" aria-label="Metagram icons"> - <Like /> + <Like aria-hidden="true" /> <Refresh aria-hidden="true" /> <Comment aria-hidden="true" /> <VerticalDots aria-hidden="true" /> <Home aria-hidden="true" /> <Flash aria-hidden="true" /> <CommentsTwo aria-hidden="true" /> </div>platforms/metagram/.storybook/preview.ts (1)
1-3
: Validate global CSS import path
The importimport '../src/app.css'
relies on a relative path that may break if story files move. Consider using a module alias (e.g.,@/app.css
or$lib/app.css
) configured intsconfig.json
/vite.config.ts
for more resilient imports.platforms/metagram/src/lib/icons/Refresh.svelte (2)
2-2
: Simplify type import path.
Use a cleaner relative path:- import type { ISvgProps } from './../types'; + import type { ISvgProps } from '../types';
7-14
: Add accessibility attributes for screen readers.
SVGs without explicitrole
oraria-label
may not convey meaning to assistive technologies. Consider:<svg role="img" aria-label={$$restProps['aria-label'] ?? 'Refresh icon'} {...$$restProps} >If the icon is purely decorative, add
aria-hidden="true"
instead.platforms/metagram/src/routes/+page.svelte (1)
6-8
: Placeholder text and styling.
The repeated "metagram" strings appear to be placeholders. Consider integrating internationalization (e.g., via the Inlang SDK) for static content.platforms/metagram/.storybook/main.ts (1)
3-3
: Use thenode:
import protocol for built-in modules.To explicitly signal that
path
is a Node.js core module and satisfy Biome’s lint rule, update the import to use thenode:
prefix:- import { join, dirname } from 'path'; + import { join, dirname } from 'node:path';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
platforms/metagram/src/lib/icons/Icons.stories.ts (1)
1-7
: Optional: Add Storybook typing for stronger type safety.To leverage TypeScript in Storybook, you can import
Meta
andStoryObj
from@storybook/svelte
and type your default export and stories:- import Icons from './Icons.svelte'; + import type { Meta, StoryObj } from '@storybook/svelte'; + import Icons from './Icons.svelte'; + + const meta: Meta<typeof Icons> = { + title: 'UI/Icons', + component: Icons, + tags: ['autodocs'], + // decorators can be removed if they return null + }; + export default meta; + + type Story = StoryObj<typeof meta>; - export default { - title: 'UI/Icons', - component: Icons, - tags: ['autodocs'], - decorators: [() => null], - render: (args: Record<string, unknown>) => ({ - Component: Icons, - props: args - }) - }; + // export const Default: Story = { args: {} };This boost in typing will improve autocomplete and catch mismatches at compile time.
platforms/metagram/README.md (3)
1-4
: Clarify project context and prerequisites.
The header# sv
is generic; consider renaming to something like# Metagram Platform
and adding a brief description of this app. Also include a Prerequisites section (e.g., Node.js ≥16, npm/pnpm/yarn) so contributors know what to install before running commands.
9-16
: Adapt “Creating a project” instructions for this repo.
These steps assume you’re scaffolding a new Svelte app, but in this directory users should clone the existing Metagram repo. Replace or augment with instructions like:- npx sv create - npx sv create my-app + git clone <repo-url> + cd platforms/metagram + npm install # or pnpm install / yarnThis will reduce confusion for first-time contributors.
17-27
: Add Storybook usage section.
Since this project includes a Storybook setup (for Avatar, Button, Icons, etc.), it’s helpful to document how to launch it:## Storybook ```bash npm run storybookThis empowers designers and devs to preview components in isolation. </blockquote></details> <details> <summary>platforms/metagram/src/lib/icons/CommentsTwo.svelte (1)</summary><blockquote> `15-27`: **Ensure consistent stroke-linecap on both paths.** The first `<path>` sets `stroke-linecap="round"`, but the second omits it (defaulting to `butt`). For visual consistency, add `stroke-linecap="round"` to the second path. ```diff - <path … stroke-width="2" stroke-linejoin="round" /> + <path … stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
platforms/metagram/src/lib/icons/VerticalDots.svelte (1)
15-35
: Use<circle>
elements for cleaner “dot” icons.
Drawing three almost-zero-length lines can be replaced with circles for clarity and better scaling:- <path d="M11.9919 12H12.0009" …/> - <path d="M11.9843 18H11.9933" …/> - <path d="M11.9998 6H12.0088" …/> + <circle cx="12" cy="6" r="1.25" stroke={color} stroke-width="2.5" stroke-linecap="round" fill="none" /> + <circle cx="12" cy="12" r="1.25" stroke={color} stroke-width="2.5" stroke-linecap="round" fill="none" /> + <circle cx="12" cy="18" r="1.25" stroke={color} stroke-width="2.5" stroke-linecap="round" fill="none" />This makes the intent explicit and simplifies the SVG.
platforms/metagram/src/lib/icons/Comment.svelte (1)
2-2
: Consider using path aliasesInstead of relative imports like
./../types
, consider using path aliases for improved maintainability and cleaner imports.- import type { ISvgProps } from './../types'; + import type { ISvgProps } from '$lib/types';This assumes you have configured path aliases in your tsconfig.json, which is common in SvelteKit projects.
platforms/metagram/src/lib/ui/Avatar/Avatar.stories.ts (2)
8-14
: Simplify render functionThe render function can be simplified as the current implementation is unnecessarily verbose.
- render: (args: { - Component: Avatar; - props: ComponentProps<typeof Avatar>; - }) => ({ - Component: Avatar, - props: args, - }), + render: (args: ComponentProps<typeof Avatar>) => ({ + Component: Avatar, + props: args, + }),
17-43
: Add more diverse avatar examplesAll avatar stories currently use the same image URL. Consider adding more diverse examples:
- Different images for different sizes
- A story with a broken/missing image to test fallback behavior
- An example with alt text for accessibility
You could add a story like this:
export const WithFallback = { args: { src: "https://example.com/non-existent-image.jpg", size: "md", alt: "User profile picture that fails to load" }, };platforms/metagram/src/lib/ui/Button/Button.stories.snippet.svelte (3)
17-22
: Consider semantic HTML improvements for button contentWhile the current implementation works, using an
h1
tag inside a button is semantically incorrect. Headings should represent page structure, not button content.- <h1>Settings</h1> + <span class="text-lg font-medium">Settings</span>
19-19
: Avoid CSS variables without fallback valuesUsing CSS variables without fallback values can cause rendering issues if the variable is undefined.
- <HugeiconsIcon icon={SettingsIcon} size={30} color="var(--color-black-500)" /> + <HugeiconsIcon icon={SettingsIcon} size={30} color="var(--color-black-500, #333)" />
23-23
: Avoid CSS variables without fallback valuesUsing CSS variables without fallback values can cause rendering issues if the variable is undefined.
- <HugeiconsIcon size={30} color="var(--color-black-500)" icon={ArrowRight01Icon} /> + <HugeiconsIcon size={30} color="var(--color-black-500, #333)" icon={ArrowRight01Icon} />platforms/metagram/src/lib/ui/Avatar/Avatar.svelte (1)
30-30
: Improve class name concatenation for better readabilityThe current class concatenation approach is unnecessarily complex. Svelte's
cn()
already handles arrays, so the additional.join(' ')
is redundant.- class={cn([classes.common, classes.size, restProps.class].join(' '))} + class={cn(classes.common, classes.size, restProps.class)}platforms/metagram/src/lib/ui/Button/Button.stories.ts (1)
27-35
: BlockingClick story demonstrates async functionalityThe BlockingClick story effectively demonstrates how the button handles asynchronous operations with a simulated delay. Consider adding a comment to explain the purpose of this test case for better documentation.
export const BlockingClick = { args: { blockingClick: true, children: ButtonText, callback: async () => { + // Simulate a 2-second network request or processing delay await new Promise((resolve) => setTimeout(resolve, 2000)); } } };
platforms/metagram/src/lib/ui/Button/Button.svelte (3)
41-54
: Consider using design tokens for colors.While the variant classes are well organized, hardcoding colors like
bg-grey
andbg-red-500
can make future theme changes difficult. Consider using semantic color variables from your design system.const variantClasses = { - primary: { background: 'bg-grey', text: 'text-black-800' }, - danger: { background: 'bg-red-500', text: 'text-white' } + primary: { background: 'bg-primary', text: 'text-primary-content' }, + danger: { background: 'bg-error', text: 'text-error-content' } };
113-113
: Documentation mentions non-existent prop.The documentation mentions an
icon
prop, but this isn't defined in the interface or implemented in the component.- - icon: A slot for an icon to be displayed inside the button. + <!-- Remove this line or add the icon implementation -->
122-124
: Inconsistency in usage example.The documentation shows
Button.Action
but the component is exported asButton
. Update the example to match the actual implementation.- <Button.Action variant="primary" callback={() => console.log('clicked')}> - Click me - </Button.Action> + <Button variant="primary" callback={() => console.log('clicked')}> + Click me + </Button>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
platforms/metagram/static/favicon.png
is excluded by!**/*.png
platforms/metagram/static/fonts/Geist-VariableFont_wght.ttf
is excluded by!**/*.ttf
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (47)
.node-version
(1 hunks).vscode/settings.json
(1 hunks)platforms/metagram/.gitignore
(1 hunks)platforms/metagram/.npmrc
(1 hunks)platforms/metagram/.prettierignore
(1 hunks)platforms/metagram/.prettierrc
(1 hunks)platforms/metagram/.storybook/main.ts
(1 hunks)platforms/metagram/.storybook/preview.ts
(1 hunks)platforms/metagram/README.md
(1 hunks)platforms/metagram/eslint.config.js
(1 hunks)platforms/metagram/messages/en.json
(1 hunks)platforms/metagram/messages/es.json
(1 hunks)platforms/metagram/package.json
(1 hunks)platforms/metagram/project.inlang/.gitignore
(1 hunks)platforms/metagram/project.inlang/cache/plugins/2sy648wh9sugi
(1 hunks)platforms/metagram/project.inlang/cache/plugins/ygx0uiahq6uw
(1 hunks)platforms/metagram/project.inlang/project_id
(1 hunks)platforms/metagram/project.inlang/settings.json
(1 hunks)platforms/metagram/src/app.css
(1 hunks)platforms/metagram/src/app.d.ts
(1 hunks)platforms/metagram/src/app.html
(1 hunks)platforms/metagram/src/lib/icons/Comment.svelte
(1 hunks)platforms/metagram/src/lib/icons/CommentsTwo.svelte
(1 hunks)platforms/metagram/src/lib/icons/Flash.svelte
(1 hunks)platforms/metagram/src/lib/icons/Home.svelte
(1 hunks)platforms/metagram/src/lib/icons/Icons.stories.ts
(1 hunks)platforms/metagram/src/lib/icons/Icons.svelte
(1 hunks)platforms/metagram/src/lib/icons/Like.svelte
(1 hunks)platforms/metagram/src/lib/icons/Refresh.svelte
(1 hunks)platforms/metagram/src/lib/icons/VerticalDots.svelte
(1 hunks)platforms/metagram/src/lib/icons/index.ts
(1 hunks)platforms/metagram/src/lib/index.ts
(1 hunks)platforms/metagram/src/lib/types.ts
(1 hunks)platforms/metagram/src/lib/ui/Avatar/Avatar.stories.ts
(1 hunks)platforms/metagram/src/lib/ui/Avatar/Avatar.svelte
(1 hunks)platforms/metagram/src/lib/ui/Button/Button.stories.snippet.svelte
(1 hunks)platforms/metagram/src/lib/ui/Button/Button.stories.ts
(1 hunks)platforms/metagram/src/lib/ui/Button/Button.svelte
(1 hunks)platforms/metagram/src/lib/ui/index.ts
(1 hunks)platforms/metagram/src/lib/utils/index.ts
(1 hunks)platforms/metagram/src/lib/utils/mergeClasses.ts
(1 hunks)platforms/metagram/src/routes/+layout.svelte
(1 hunks)platforms/metagram/src/routes/+layout.ts
(1 hunks)platforms/metagram/src/routes/+page.svelte
(1 hunks)platforms/metagram/svelte.config.js
(1 hunks)platforms/metagram/tsconfig.json
(1 hunks)platforms/metagram/vite.config.ts
(1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
platforms/metagram/src/lib/types.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
platforms/metagram/.storybook/main.ts
[error] 3-3: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.
(lint/style/useNodejsImportProtocol)
🔇 Additional comments (53)
platforms/metagram/project.inlang/.gitignore (1)
1-1
: .gitignore configuration for cache is correct.The entry
cache
will ignore thecache/
directory and its contents withinproject.inlang
, preventing plugin cache artifacts from being committed.platforms/metagram/project.inlang/project_id (1)
1-1
: Project ID file content looks appropriate.The
project_id
uniquely identifies the Inlang configuration and does not expose sensitive information.platforms/metagram/messages/en.json (1)
1-4
: English messages file is correctly formatted.The JSON structure, schema URL, and
hello_world
message with placeholder{name}
follow the inlang message format spec.platforms/metagram/messages/es.json (1)
1-4
: Verify Spanish locale translation.The Spanish file currently uses an English greeting (
"Hello, {name} from es!"
). Should this be localized into Spanish (e.g.,"¡Hola, {name} desde es!"
or another appropriate phrasing)? Please confirm the intended translation.platforms/metagram/project.inlang/settings.json (3)
3-6
: Confirm plugin module URLs and versions.Ensure that the JSDelivr URLs for
@inlang/plugin-message-format@4
and@inlang/plugin-m-function-matcher@2
resolve to the correct, stable plugin versions required by your setup.
7-9
: ValidatepathPattern
configuration.The
plugin.inlang.messageFormat.pathPattern
points to../messages/{locale}.json
. Confirm that this relative path correctly resolves fromproject.inlang/settings.json
to your locale files.
10-12
: Locale configuration matches the provided files.The
baseLocale: "en"
andlocales: ["en", "es"]
align withmessages/en.json
andmessages/es.json
. This setup correctly defines your internationalization targets..vscode/settings.json (1)
24-30
: Align Svelte formatter with project conventionsUpdating the Svelte block to use
"svelte.svelte-vscode"
ensures consistency with the SvelteKit, ESLint, Prettier, and Storybook setup inplatforms/metagram
.platforms/metagram/src/lib/types.ts (1)
1-6
: Useimport type
for type-only importsYou've correctly applied the Biome lint recommendation by using:
import { type SVGAttributes } from 'svelte/elements';This ensures the import is erased at compile time and avoids runtime overhead.
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
platforms/metagram/.gitignore (1)
1-25
: Comprehensive ignore patterns for build artifactsThe
.gitignore
coversnode_modules
, all relevant build directories (.output
,.svelte-kit
, etc.), OS files, env files (with exceptions), Vite timestamps, and Storybook logs. This aligns well with standard SvelteKit and Storybook workflows.platforms/metagram/src/app.css (1)
32-52
: Verify support for the custom@theme
at-ruleThe
@theme { … }
block isn’t standard CSS—ensure your PostCSS/Tailwind plugin chain (or other tooling) correctly processes it into usable custom properties..node-version (1)
1-1
: Update Node version to match engine-strict settingsChanging from
22.x
to20.x
aligns with the.npmrc
engine-strict=true
and targets the current LTS stream.platforms/metagram/.prettierignore (1)
1-6
: .prettierignore correctly excludes lockfiles
This file ensures that package manager lock files (e.g.,package-lock.json
,yarn.lock
,pnpm-lock.yaml
,bun.lock
,bun.lockb
) aren’t reformatted by Prettier, which aligns with best practices for avoiding diffs in auto-generated files.platforms/metagram/.npmrc (1)
1-1
: Enforce Node.js engine version
Theengine-strict=true
setting will prevent installations on mismatched Node versions. Please verify that your.node-version
file orpackage.json
engines.node
field is set to the intended version (e.g.,20.x
) to avoid installation failures.platforms/metagram/src/lib/utils/index.ts (1)
1-1
: Export themergeClasses
utility
Re-exporting from./mergeClasses
provides a single entry point for thecn
helper, improving import ergonomics and modularity.platforms/metagram/src/lib/ui/index.ts (1)
1-2
: Centralize UI component exports
Re-exportingButton
andAvatar
from this index file streamlines imports elsewhere and aligns with a modular component structure.platforms/metagram/vite.config.ts (1)
1-2
: Verify Tailwind CSS plugin import
The lineimport tailwindcss from '@tailwindcss/vite'
isn’t part of the official Tailwind distribution. Ensure you have installed the correct Vite plugin (and that it’s named@tailwindcss/vite
) or consider using the standard PostCSS setup viapostcss.config.cjs
.platforms/metagram/src/routes/+layout.ts (1)
1-2
: Confirm prerender and SSR settings align with routing needs
Turning off SSR (ssr = false
) and enabling prerendering (prerender = true
) forces a fully static site. Verify that no dynamic data or authenticated routes require runtime rendering.platforms/metagram/svelte.config.js (3)
1-2
: Imports are correct and minimal. All required dependencies for the static adapter and Vite preprocessing are imported.
4-7
: Configuration object is properly set up. Thepreprocess
andkit.adapter
settings follow SvelteKit guidelines for a static build.
9-9
: Export of configuration. The default export ensures SvelteKit picks up the configuration.platforms/metagram/src/app.d.ts (3)
1-2
: Clarifying documentation comments. The reference to SvelteKit’s docs provides clear guidance for future interface augmentations.
3-11
: GlobalApp
namespace placeholder. All SvelteKit interfaces are stubbed out and ready for future extension.
13-13
: Module export stub.export {}
ensures this file is treated as a module by TypeScript.platforms/metagram/tsconfig.json (3)
2-3
: Extends base SvelteKit tsconfig. Inheriting default settings from the auto-generated SvelteKit config is correct.
4-12
: Compiler options align with project needs. Enablingstrict
,esModuleInterop
, and using"moduleResolution": "bundler"
are appropriate for this SvelteKit + TypeScript setup.
14-18
: Informational comments on alias handling. Clear guidance on how path aliases and include/exclude behavior work.platforms/metagram/src/routes/+page.svelte (2)
1-3
: Semantic structure is sound.
Wrapping content in<main>
and using<section>
witharia-labelledby
follows accessibility best practices.
3-5
: Heading hierarchy and ARIA labeling.
Using<h1>
through<h3>
in proper order is good. Ensure that the IDs (main-title
,subtitle
,section-title
) remain unique across the document.platforms/metagram/src/lib/utils/mergeClasses.ts (1)
1-6
: Utility function for class merging is well implemented.Good use of
clsx
for conditional class concatenation followed bytwMerge
to optimize Tailwind CSS classes. This pattern is concise and reusable.platforms/metagram/src/lib/icons/CommentsTwo.svelte (1)
2-5
: Verify Svelte props destructuring.
The use of$props()
requires Svelte v4+. Please confirm yoursvelte.config.js
andpackage.json
target Svelte 4+ so this pattern compiles as expected.platforms/metagram/package.json (2)
6-17
: LGTM: Scripts configurationThe scripts configuration is well-organized and includes all necessary commands for development, building, testing, and Storybook integration.
19-48
:✅ Verification successful
Verify package versions
Some of the devDependencies have unusually high version numbers that may not exist yet (e.g., eslint v9.18.0, tailwindcss v4.0.0). Please verify these versions are correct.
🌐 Web query:
Are eslint v9.18.0 and tailwindcss v4.0.0 currently available?
💡 Result:
Yes, both ESLint v9.18.0 and Tailwind CSS v4.0.0 are currently available.
ESLint v9.18.0: This version was released on January 10, 2025. Although it's not the latest version (the latest is v9.26.0), it is available for use[1][2].
Tailwind CSS v4.0.0: This version was released on January 22, 2025. It introduces significant performance improvements and new features like CSS-first configuration[6][9].
Citations:
- 1: https://eslint.org/blog/2025/01/eslint-v9.18.0-released/
- 2: https://www.npmjs.com/package/eslint
- 3: https://github.com/eslint/eslint/blob/main/CHANGELOG.md
- 4: eslint/eslint#19337
- 5: https://eslint.org/blog/2024/04/eslint-v9.0.0-released/
- 6: https://fireup.pro/news/tailwind-css-v4-0-released-lightning-fast-builds-advanced-features-and-simplified-setup
- 7: https://www.npmjs.com/package/eslint-plugin-tailwindcss
- 8: https://typescript-eslint.io/users/releases/
- 9: https://dev.to/falselight/tailwindcss-version-400-has-been-released-29pp
- 10: https://github.com/francoismassart/eslint-plugin-tailwindcss/releases
Package versions verified
ESLint v9.18.0 (released Jan 10 2025) and Tailwind CSS v4.0.0 (released Jan 22 2025) are valid, published versions. No changes required.platforms/metagram/src/lib/icons/index.ts (1)
1-8
: LGTM: Well-organized icon exportsThe barrel file pattern used here provides a clean way to export all icon components from a single entry point, making imports cleaner throughout the application.
platforms/metagram/src/lib/icons/Comment.svelte (1)
7-28
: LGTM: Well-structured SVG icon componentThe SVG icon implementation is clean, with appropriate viewBox settings and parameterized size and color. The spread operator for additional props is also a good practice.
platforms/metagram/src/lib/ui/Avatar/Avatar.stories.ts (4)
38-43
: LGTM: ExtraSmall avatar size matches requirementsThe extra small (xs) avatar size variant matches the PR requirements of implementing an extra small 24px avatar.
17-22
: LGTM: Large avatar size matches requirementsThe large (lg) avatar size variant matches the PR requirements of implementing a large 120px avatar.
24-29
: LGTM: Medium avatar size matches requirementsThe medium (md) avatar size variant matches the PR requirements of implementing a medium 48px avatar set as default.
31-36
: LGTM: Small avatar size matches requirementsThe small (sm) avatar size variant matches the PR requirements of implementing a small 40px avatar.
platforms/metagram/src/lib/ui/Button/Button.stories.snippet.svelte (2)
1-6
: The code looks good!The module properly imports and exports the necessary components and snippets. The organization is clean and follows good practices.
8-14
: The snippet implementation looks good!These basic text snippets are well implemented and will work effectively with the Button component.
platforms/metagram/src/lib/ui/Avatar/Avatar.svelte (3)
5-9
: Good interface design with appropriate propsThe interface design is excellent, with a required
src
property and optional properties with sensible defaults. The size variants match the requirements specified in the PR description (xs: 24px, sm: 40px, md: 48px, lg: 120px).
13-18
: Avatar size implementation matches requirementsThe size variants perfectly match the PR requirements:
- xs: w-6 h-6 (24px)
- sm: w-10 h-10 (40px)
- md: w-12 h-12 (48px, default)
- lg: w-30 h-30 (120px)
33-47
: Excellent documentationThe component documentation is thorough and helpful, providing clear information about the component, its props, and usage examples. This is an excellent practice that enhances code maintainability.
platforms/metagram/eslint.config.js (2)
1-9
: Well-structured imports for ESLint configurationThe imports are well-organized, bringing in all necessary plugins and configurations for a comprehensive linting setup for a SvelteKit project with TypeScript.
12-42
: Comprehensive ESLint configurationThe ESLint configuration is thorough and well-structured:
- Properly integrates JavaScript, TypeScript, and Svelte recommendations
- Configures Prettier for consistent formatting
- Sets up appropriate overrides for Svelte files
- Configures proper parser options for TypeScript in Svelte files
This setup will ensure code quality and consistency throughout the project.
platforms/metagram/src/lib/ui/Button/Button.stories.ts (2)
5-13
: Well-structured Storybook configurationThe Storybook configuration follows best practices:
- Proper title for component organization
- Component reference
- Autodocs tag for automatic documentation generation
- Clean render function implementation
15-25
: Good coverage of button variantsThe stories for Primary, Danger, and Loading button states provide good coverage of the button's variants and states. This allows for effective visual testing.
platforms/metagram/src/lib/ui/Button/Button.svelte (5)
5-12
: Well-structured interface with good type safety.The interface definition for button props extends HTMLButtonAttributes and provides clear type constraints for all customizable properties. This ensures type safety and makes the component API clear for consumers.
25-26
: State management is well implemented.The use of
$state
and$derived
for reactive state management is clean and effective. The disabled state correctly combines all conditions that should disable the button.
28-39
: Good error handling and async flow.The click handler correctly:
- Validates the callback is a function
- Manages the submitting state
- Handles errors gracefully
- Ensures submitting state is reset in the finally block
This approach prevents UI bugs when callbacks fail unexpectedly.
23-23
:✅ Verification successful
Svelte 5 syntax detected.
The use of
$props()
indicates you're using Svelte 5's runes API. Make sure this aligns with your project's Svelte version, as this syntax is not compatible with Svelte 4 or earlier.
🏁 Script executed:
#!/bin/bash # Check the Svelte version in package.json cat platforms/metagram/package.json | grep '"svelte":'Length of output: 78
No action needed: Svelte 5 props syntax is correct
The project’s package.json specifies"svelte": "^5.0.0"
, so using$props()
aligns with Svelte 5’s runes API and requires no changes.
91-91
:✅ Verification successful
Children rendering approach is Svelte 5 specific.
The
{@render children?.()}
syntax is specific to Svelte 5. If this is intentional, make sure your project is configured for Svelte 5. Otherwise, use the standard slot approach.
🏁 Script executed:
#!/bin/bash # Check if the new features are being used elsewhere in the project rg -g "*.svelte" "@render|$state|$props|$derived" platforms/metagram/src/Length of output: 35522
Children rendering is valid under Svelte 5
The project consistently uses Svelte 5 patterns (e.g.$props
,$state
,$derived
, and{@render children()}
in+layout.svelte
), so{@render children?.()}
inButton.svelte
is intentional. No changes required.
@import 'tailwindcss'; | ||
|
||
@font-face { | ||
font-family: 'Geist', sans-serif; | ||
font-style: normal; | ||
font-weight: 700; | ||
font-display: swap; | ||
src: url('/fonts/Geist-VariableFont_wght.ttf') format('truetype'); | ||
} |
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.
🛠️ Refactor suggestion
Use Tailwind’s @tailwind
directives instead of @import
The line @import 'tailwindcss';
may not pull in the full base, components, and utilities. Replace it with the official Tailwind directives:
-@import 'tailwindcss';
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
@import 'tailwindcss'; | |
@font-face { | |
font-family: 'Geist', sans-serif; | |
font-style: normal; | |
font-weight: 700; | |
font-display: swap; | |
src: url('/fonts/Geist-VariableFont_wght.ttf') format('truetype'); | |
} | |
@tailwind base; | |
@tailwind components; | |
@tailwind utilities; | |
@font-face { | |
font-family: 'Geist', sans-serif; | |
font-style: normal; | |
font-weight: 700; | |
font-display: swap; | |
src: url('/fonts/Geist-VariableFont_wght.ttf') format('truetype'); | |
} |
let { children } = $props(); | ||
</script> | ||
|
||
{@render children()} |
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.
🛠️ Refactor suggestion
Use standard Svelte slots instead of $props
and {@render}
SvelteKit layouts should render nested routes using <slot />
. The current usage of $props()
and {@render children()}
is non-standard and may break on update or in SSR contexts.
Apply this diff to simplify the component:
<script lang="ts">
- import '../app.css';
- let { children } = $props();
+ import '../app.css';
</script>
- {@render children()}
+ <slot />
import type { ISvgProps } from './../types'; | ||
|
||
let { size = '20px', color = '#A5A5A5', ...restProps }: ISvgProps = $props(); | ||
</script> |
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.
Incorrect prop handling – Svelte does not support $props()
destructuring.
The line:
let { size = '20px', color = '#A5A5A5', ...restProps }: ISvgProps = $props();
is invalid in Svelte and will not compile. Use export let
for props and forward extra attributes via $$restProps
.
Proposed fix:
<script lang="ts">
- import type { ISvgProps } from './../types';
- let { size = '20px', color = '#A5A5A5', ...restProps }: ISvgProps = $props();
+ import type { ISvgProps } from '../types';
+ export let size: ISvgProps['size'] = '20px';
+ export let color: ISvgProps['color'] = '#A5A5A5';
+ // Additional attributes are forwarded via the $$restProps store
</script>
<svg
- {...restProps}
+ {...$$restProps}
function getAbsolutePath(value: string): string { | ||
return dirname(require.resolve(join(value, 'package.json'))); | ||
} |
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.
🛠️ Refactor suggestion
Ensure compatibility in ESM by creating a require
function.
require.resolve
isn’t available in native ESM contexts. Wrap it via createRequire
from the module
package:
- function getAbsolutePath(value: string): string {
- return dirname(require.resolve(join(value, 'package.json')));
- }
+ import { createRequire } from 'module';
+
+ const require = createRequire(import.meta.url);
+
+ function getAbsolutePath(value: string): string {
+ return dirname(require.resolve(join(value, 'package.json')));
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
function getAbsolutePath(value: string): string { | |
return dirname(require.resolve(join(value, 'package.json'))); | |
} | |
import { createRequire } from 'module'; | |
const require = createRequire(import.meta.url); | |
function getAbsolutePath(value: string): string { | |
return dirname(require.resolve(join(value, 'package.json'))); | |
} |
let { size = '20px', color = '#A5A5A5', ...restProps }: ISvgProps = $props(); | ||
</script> |
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.
🛠️ Refactor suggestion
Incorrect prop handling: $props()
is not a valid Svelte API.
Svelte components must declare incoming props with export let
and use $$restProps
to capture additional attributes. For example:
<script lang="ts">
- let { size = '20px', color = '#A5A5A5', ...restProps }: ISvgProps = $props();
+ export let size: string = '20px';
+ export let color: string = '#A5A5A5';
+
+ // Other passed-in attributes are available via $$restProps
</script>
Then spread $$restProps
in the SVG tag:
- <svg
- {...restProps}
+ <svg
+ {...$$restProps}
width={size}
height={size}
viewBox="0 0 20 20"
This aligns with Svelte’s compiler expectations and ensures proper typing.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
let { size = '20px', color = '#A5A5A5', ...restProps }: ISvgProps = $props(); | |
</script> | |
<script lang="ts"> | |
export let size: string = '20px'; | |
export let color: string = '#A5A5A5'; | |
// Other passed-in attributes are available via $$restProps | |
</script> | |
<svg | |
{...$$restProps} | |
width={size} | |
height={size} | |
viewBox="0 0 20 20" | |
> | |
<!-- existing icon markup --> | |
</svg> |
<head> | ||
<meta charset="utf-8" /> | ||
<link rel="icon" href="%sveltekit.assets%/favicon.png" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
%sveltekit.head% |
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.
🛠️ Refactor suggestion
Add <title>
and meta description for SEO & accessibility.
Right now the <head>
is missing a <title>
tag and a <meta name="description">
. I recommend:
<head>
<meta charset="utf-8" />
+ <title>Metagram</title>
+ <meta name="description" content="Metagram – a SvelteKit-powered social feed demo" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
…
This ensures each page has a meaningful title and description.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
<head> | |
<meta charset="utf-8" /> | |
<link rel="icon" href="%sveltekit.assets%/favicon.png" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1" /> | |
%sveltekit.head% | |
<head> | |
<meta charset="utf-8" /> | |
<title>Metagram</title> | |
<meta name="description" content="Metagram – a SvelteKit-powered social feed demo" /> | |
<link rel="icon" href="%sveltekit.assets%/favicon.png" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1" /> | |
%sveltekit.head% |
<svg | ||
width={size} | ||
height={size} | ||
viewBox="0 0 24 24" | ||
fill="none" | ||
xmlns="http://www.w3.org/2000/svg" | ||
{...restProps} | ||
> |
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.
🛠️ Refactor suggestion
Improve accessibility by annotating the SVG.
Add role="img"
to the <svg>
and include a <title>
(or accept an export let title: string
/aria-label
) for screen readers:
- <svg width={size} … {...restProps}>
+ <svg role="img" width={size} … {...restProps}>
+ <title>{$$restProps['aria-label'] || 'Home icon'}</title>
This ensures the icon isn’t hidden from assistive technologies.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
<svg | |
width={size} | |
height={size} | |
viewBox="0 0 24 24" | |
fill="none" | |
xmlns="http://www.w3.org/2000/svg" | |
{...restProps} | |
> | |
<svg | |
role="img" | |
width={size} | |
height={size} | |
viewBox="0 0 24 24" | |
fill="none" | |
xmlns="http://www.w3.org/2000/svg" | |
{...restProps} | |
> | |
<title>{$$restProps['aria-label'] || 'Home icon'}</title> |
"dependencies": { | ||
"-": "^0.0.1", | ||
"D": "^1.0.0", | ||
"tailwind-merge": "^3.0.2" |
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.
Remove invalid dependencies
The dependencies section contains two unusual entries: "-" (version 0.0.1) and "D" (version 1.0.0). These appear to be typographical errors or artifacts that should be removed.
"dependencies": {
- "-": "^0.0.1",
- "D": "^1.0.0",
"tailwind-merge": "^3.0.2"
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
"dependencies": { | |
"-": "^0.0.1", | |
"D": "^1.0.0", | |
"tailwind-merge": "^3.0.2" | |
"dependencies": { | |
"tailwind-merge": "^3.0.2" | |
} |
].join(' ') | ||
)} | ||
{disabled} | ||
onclick={handleClick} |
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.
Fix event handler syntax.
Svelte uses on:click
for event binding, not onclick
. The current implementation won't work as expected.
- onclick={handleClick}
+ on:click={handleClick}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
onclick={handleClick} | |
on:click={handleClick} |
{#if isLoading || isSubmitting} | ||
<div | ||
class="border-black-800 absolute h-6 w-6 animate-spin rounded-full border-2 border-t-transparent" | ||
></div> | ||
{/if} |
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.
🛠️ Refactor suggestion
Add ARIA attributes for accessibility.
The loading spinner is visually implemented, but screen readers won't detect this state change. Add ARIA attributes to improve accessibility.
<button
{...restProps}
class={cn(
[
classes.common,
classes.background,
classes.text,
disabled && classes.disabled,
restProps.class
].join(' ')
)}
{disabled}
on:click={handleClick}
{type}
+ aria-busy={isLoading || isSubmitting}
>
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
{#if isLoading || isSubmitting} | |
<div | |
class="border-black-800 absolute h-6 w-6 animate-spin rounded-full border-2 border-t-transparent" | |
></div> | |
{/if} | |
<button | |
{...restProps} | |
class={cn( | |
[ | |
classes.common, | |
classes.background, | |
classes.text, | |
disabled && classes.disabled, | |
restProps.class | |
].join(' ') | |
)} | |
{disabled} | |
on:click={handleClick} | |
{type} | |
aria-busy={isLoading || isSubmitting} | |
> |
Continued in #130 |
Description of change
Added all the 4 variants of the user avatar as in the design:
Story made.
Issue Number
Closes #123
Type of change
How the change has been tested
Using storybook and inspect element to match the sizes with figma design.
Change checklist
Summary by CodeRabbit
New Features
Documentation
Chores