Skip to content
Merged

Next #144

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 0 additions & 48 deletions .eslintrc.js

This file was deleted.

1 change: 0 additions & 1 deletion astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import compress from 'astro-compress'
import icon from 'astro-icon'
import tailwindcss from '@tailwindcss/vite'
import { fileURLToPath } from 'url'
import path from 'path'

// https://astro.build/config
export default defineConfig({
Expand Down
119 changes: 119 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import globals from 'globals'
import js from '@eslint/js'
import astro from 'eslint-plugin-astro'
import jsxA11y from 'eslint-plugin-jsx-a11y'
import tseslint from '@typescript-eslint/eslint-plugin'
import tsParser from '@typescript-eslint/parser'
import astroParser from 'astro-eslint-parser'

export default [
// Ignore patterns
{
ignores: [
'dist/**',
'node_modules/**',
'.astro/**',
'**/*.d.ts', // Ignore generated TypeScript declaration files
],
},

// Base configuration for all files
{
languageOptions: {
globals: {
...globals.node,
...globals.browser,
},
ecmaVersion: 'latest',
sourceType: 'module',
},
},

// ESLint recommended rules
js.configs.recommended,

// JavaScript files
{
files: ['**/*.js'],
rules: {
'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'],
},
},

// Astro files
{
files: ['**/*.astro'],
plugins: {
astro,
},
languageOptions: {
parser: astroParser,
parserOptions: {
parser: '@typescript-eslint/parser',
extraFileExtensions: ['.astro'],
},
},
rules: {
...astro.configs.recommended.rules,
...astro.configs['jsx-a11y-strict'].rules,
'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'],
},
},
Comment on lines +44 to +61
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify Astro configuration handles TypeScript properly.

The Astro configuration already includes TypeScript parsing with parser: '@typescript-eslint/parser' as a sub-parser. Ensure this setup properly lints TypeScript code within Astro files, making the separate TypeScript-in-Astro configuration (lines 121-129) unnecessary.

Run the following script to test the ESLint configuration:


🏁 Script executed:

#!/bin/bash
# Test ESLint configuration on sample files

# Check if ESLint can parse the configuration
npx eslint --print-config src/components/example.astro 2>/dev/null || echo "ESLint config parsing failed for Astro files"

# Test configuration validation
npx eslint --validate-config eslint.config.js

Length of output: 548


I’ll verify that the config file itself loads and that ESLint is actually picking up .astro files when given the proper flags.


🏁 Script executed:

#!/bin/bash
# 1. Ensure the ESLint config file has no syntax errors
node -e "require('./eslint.config.js')" && echo "Config syntax OK" || echo "Syntax error in eslint.config.js"

# 2. Try printing the resolved config for an .astro file, explicitly including the .astro extension
npx eslint src/components/example.astro --ext .astro --print-config 2>/dev/null \
  && echo "Print-config OK for .astro" \
  || echo "Failed to print config for .astro with --ext"

# 3. Attempt to actually lint the .astro file to confirm parser is applied
npx eslint src/components/example.astro --ext .astro --max-warnings=0 \
  && echo "Lint run OK for .astro" \
  || echo "Lint run failed or file ignored"

Length of output: 1689


I need to inspect how astroParser is being imported/defined in your config to pinpoint the missing module. Let’s dump the top of eslint.config.js and locate astroParser:


🏁 Script executed:

#!/bin/bash
# Show all import statements in the config
grep -R "^import" -n eslint.config.js

# Locate where astroParser is defined or referenced
grep -R "astroParser" -n eslint.config.js

Length of output: 467


Fix missing astro-eslint-parser dependency

The ESLint config is importing astroParser from astro-eslint-parser but that package isn’t installed, so require('./eslint.config.js') fails with “Cannot find package 'astro-eslint-parser’.” Add or correct the parser package installation and reference:

• In eslint.config.js:

  • Line 7: import astroParser from 'astro-eslint-parser'
  • Line 50: parser: astroParser,

Recommended fixes:

  1. Install the parser as a dev-dependency:
    npm install --save-dev astro-eslint-parser
  2. (Alternative) Drop the import and reference the parser by name:
    parser: 'astro-eslint-parser',

After this, rerun ESLint on your .astro files to confirm parsing and TypeScript linting work correctly.

🤖 Prompt for AI Agents
In eslint.config.js around lines 44 to 61, the configuration imports and uses
astroParser from 'astro-eslint-parser' but this package is missing, causing
ESLint to fail loading the config. Fix this by installing 'astro-eslint-parser'
as a dev dependency using npm or yarn, or alternatively remove the import and
set the parser property to the string 'astro-eslint-parser' instead of the
imported variable. After applying one of these fixes, rerun ESLint on .astro
files to verify proper parsing and linting.


// TypeScript files
{
files: ['**/*.ts'],
plugins: {
'@typescript-eslint': tseslint,
},
languageOptions: {
parser: tsParser,
},
rules: {
...tseslint.configs.recommended.rules,
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', destructuredArrayIgnorePattern: '^_' }],
'@typescript-eslint/no-non-null-assertion': 'off',
},
},

// JSX files (React components)
{
files: ['**/*.jsx'],
plugins: {
'jsx-a11y': jsxA11y,
},
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
rules: {
...jsxA11y.configs.strict.rules,
},
},

// TypeScript JSX files (React components)
{
files: ['**/*.tsx'],
plugins: {
'@typescript-eslint': tseslint,
'jsx-a11y': jsxA11y,
},
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
rules: {
...tseslint.configs.recommended.rules,
...jsxA11y.configs.strict.rules,
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', destructuredArrayIgnorePattern: '^_' }],
'@typescript-eslint/no-non-null-assertion': 'off',
},
},
]
25 changes: 15 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"version": "4.0.0",
"author": "Incluud",
"license": "MIT",
"type": "module",
"homepage": "https://accessible-astro.netlify.app/",
"scripts": {
"dev": "astro dev",
Expand Down Expand Up @@ -33,28 +34,32 @@
"url": "https://github.com/incluud/accessible-astro-starter/issues"
},
"devDependencies": {
"@astrojs/mdx": "^4.2.5",
"@astrojs/mdx": "^4.3.0",
"@astrojs/partytown": "^2.1.4",
"@iconify-json/lucide": "^1.2.39",
"@typescript-eslint/eslint-plugin": "^8.31.0",
"@typescript-eslint/parser": "^8.31.0",
"astro": "^5.7.5",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.27.0",
"@iconify-json/lucide": "^1.2.44",
"@typescript-eslint/eslint-plugin": "^8.32.1",
"@typescript-eslint/parser": "^8.32.1",
"astro": "^5.8.0",
"astro-compress": "^2.3.8",
"astro-eslint-parser": "^1.2.2",
"astro-icon": "^1.1.5",
"eslint": "^9.0.0",
"eslint": "^9.27.0",
"eslint-plugin-astro": "^1.3.1",
"eslint-plugin-jsx-a11y": "^6.10.2",
"globals": "^16.1.0",
"prettier": "^3.5.3",
"prettier-plugin-astro": "^0.14.1",
"prettier-plugin-css-order": "^2.1.2",
"prettier-plugin-tailwindcss": "^0.6.11",
"sanitize-html": "^2.16.0",
"sass": "^1.87.0",
"sanitize-html": "^2.17.0",
"sass": "^1.89.0",
"svgo": "^3.3.2",
"tailwindcss": "^4.1.4"
"tailwindcss": "^4.1.7"
},
"dependencies": {
"@tailwindcss/vite": "^4.1.4",
"@tailwindcss/vite": "^4.1.7",
"accessible-astro-components": "^4.1.1"
}
}
1 change: 1 addition & 0 deletions src/assets/scss/base/_breakpoint.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ $breakpoints: (
'l': 1024px,
'xl': 1280px,
'2xl': 1536px,
'nav': 900px,
) !default;

@mixin breakpoint($breakpoint) {
Expand Down
76 changes: 32 additions & 44 deletions src/components/Navigation.astro
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Logo from './Logo.astro'
*/
---

<div id="main-navigation" class="is-desktop py-8">
<div id="main-navigation" class="py-8">
<div class="container">
<Logo />
<div class="wrapper">
Expand Down Expand Up @@ -57,24 +57,6 @@ import Logo from './Logo.astro'
})
}

const checkMenuSize = (): void => {
const mainNavWidth = mainNav.getBoundingClientRect().width
const desktopMenuEl = document.querySelector('.desktop-menu') as HTMLElement | null
if (!desktopMenuEl) return

const desktopMenuWidth = desktopMenuEl.getBoundingClientRect().width
const logoWidthBuffer = 300
const totalMenuWidth = Math.round(desktopMenuWidth) + logoWidthBuffer

if (totalMenuWidth >= mainNavWidth) {
mainNav.classList.remove('is-desktop')
mainNav.classList.add('is-mobile')
} else if (totalMenuWidth <= mainNavWidth) {
mainNav.classList.add('is-desktop')
mainNav.classList.remove('is-mobile')
}
}

const isOutOfViewport = (element: Element): boolean => {
const elementBounds = element.getBoundingClientRect()
return elementBounds.right > (window.innerWidth || document.documentElement.clientWidth)
Expand Down Expand Up @@ -222,9 +204,6 @@ import Logo from './Logo.astro'
})

setActiveMenuItem()
checkMenuSize()

window.addEventListener('resize', checkMenuSize)
window.addEventListener('click', (event: MouseEvent) => {
const element = event.target as Element
if (!element.hasAttribute('aria-haspopup') && !element.classList.contains('submenu-item')) {
Expand All @@ -236,47 +215,47 @@ import Logo from './Logo.astro'

<style lang="scss" is:global>
@use '../assets/scss/base/mixins' as *;
@use '../assets/scss/base/breakpoint' as *;

#main-navigation {
> .container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}

&.is-desktop {
.desktop-menu {
position: static;
visibility: visible;
}
// Mobile-first: show mobile menu by default
.mobile-menu {
display: none;

.mobile-menu {
display: none;
&.show {
display: block;
}
}

&.is-mobile {
flex-direction: column;
.responsive-toggle {
display: flex;
align-items: center;
gap: var(--space-2xs);
}

.desktop-menu {
display: none;
}

// Desktop: switch to desktop menu at nav breakpoint
@include breakpoint('nav') {
.mobile-menu {
display: none;

&.show {
display: block;
}
}

.desktop-menu {
position: absolute;
visibility: hidden;
z-index: -99;
inset-inline-start: 0;
.responsive-toggle {
display: none;
}

.responsive-toggle {
display: flex;
align-items: center;
gap: var(--space-2xs);
.desktop-menu {
display: block;
}
}

Expand All @@ -297,6 +276,10 @@ import Logo from './Logo.astro'
gap: var(--space-m);
list-style-type: none;

li {
align-content: center;
}

a:hover,
a:focus-visible,
.is-active,
Expand Down Expand Up @@ -419,6 +402,11 @@ import Logo from './Logo.astro'
border: none;
padding: 0;

@include breakpoint('nav') {
// Align with the menu items
margin-block-start: 7px;
}

.icon {
inline-size: 30px;
block-size: 30px;
Expand Down
2 changes: 0 additions & 2 deletions src/components/ResponsiveToggle.astro
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ const { class: className } = Astro.props

.responsive-toggle {
display: none;
margin-block-start: 6px;
border: none;
background: transparent;
padding: 0;
Expand All @@ -81,7 +80,6 @@ const { class: className } = Astro.props
}

svg {
margin-block-start: 4px;
width: 30px;

path {
Expand Down