From 93ed53503a33a0b63fab9de53fe81f895739ef5a Mon Sep 17 00:00:00 2001 From: kallelongjuhani Date: Sun, 14 Dec 2025 11:22:50 +0200 Subject: [PATCH 1/4] refactor/docs: harmonize Svelte component documentation and type files Apply these principles to all components: 1. Each property is defined in a separate .type.ts file in a type called Props. 2. That file is the prime source of truth for the properties' descriptions 3. The type is imported to the component as $$Props 4. All props are typed using that. 5. At the top of the file, there is a Svelte doc with `@component` 6. The `### Properties` section is generated from the type file such that `@default` is replaced with 'Default:' and the value is backticked. 7. The element or component onto which $$restProps is passed and which is the base of the props type, is mentioned last as like '- Any valid attributes of a `
` element' 8. Any other prop related headings can be removed along with their contents, unless they contain relevant information missing from the type, in which case add the info to the type 9. If the component doesn't follow this paradigm, create the type file, export it from index.ts and import it to the component Co-Author: Claude --- .../admin/components/jobs/FeatureJobs.svelte | 17 +++++++ .../admin/components/jobs/JobDetails.svelte | 16 +++++++ .../admin/components/jobs/WithPolling.svelte | 12 ++++- .../languageFeatures/LanguageSelector.svelte | 19 ++++++-- .../logoutButton/LogoutButton.svelte | 13 +++--- .../logoutButton/LogoutButton.type.ts | 2 +- .../components/logoutButton/index.ts | 1 + .../passwordField/PasswordField.svelte | 28 ++++++----- .../passwordField/PasswordField.type.ts | 28 +++++++++++ .../components/passwordField/index.ts | 1 + .../passwordSetter/PasswordSetter.svelte | 23 ++++++---- .../passwordSetter/PasswordSetter.type.ts | 24 ++++++++++ .../components/passwordSetter/index.ts | 1 + .../PasswordValidator.svelte | 17 ++++--- .../PasswordValidator.type.ts | 16 +++++++ .../components/passwordValidator/index.ts | 1 + .../PreregisteredNotification.svelte | 15 +++--- .../PreregisteredNotification.type.ts | 3 ++ .../preregisteredNotification/index.ts | 1 + .../components/termsOfUse/TermsOfUse.svelte | 8 ++-- .../termsOfUse/TermsOfUseForm.svelte | 15 +++--- .../accordionSelect/AccordionSelect.svelte | 15 +++--- .../src/lib/components/alert/Alert.svelte | 21 +++++---- .../src/lib/components/avatar/Avatar.svelte | 4 +- .../src/lib/components/button/Button.svelte | 14 +++--- .../ButtonWithConfirmation.svelte | 16 +++---- .../components/categoryTag/CategoryTag.svelte | 8 ++-- .../ConstituencySelector.svelte | 20 ++++---- .../components/controller/InfoMessages.svelte | 26 ++++++++--- .../controller/InfoMessages.type.ts | 9 ++++ .../components/controller/ProgressBar.svelte | 46 +++++++++++++++---- .../components/controller/ProgressBar.type.ts | 24 ++++++++++ .../controller/WarningMessages.svelte | 29 ++++++++---- .../controller/WarningMessages.type.ts | 13 ++++++ .../src/lib/components/controller/index.ts | 3 ++ .../components/electionTag/ElectionTag.svelte | 4 +- .../entityFilters/EntityFilters.svelte | 4 +- .../text/TextEntityFilter.svelte | 7 +-- .../lib/components/entityTag/EntityTag.svelte | 4 +- .../errorMessage/ErrorMessage.svelte | 6 +-- .../lib/components/expander/Expander.svelte | 15 +++--- .../headingGroup/HeadingGroup.svelte | 4 +- .../components/headingGroup/PreHeading.svelte | 2 +- .../lib/components/heroEmoji/HeroEmoji.svelte | 5 +- frontend/src/lib/components/icon/Icon.svelte | 11 ++--- .../components/infoAnswer/InfoAnswer.svelte | 2 +- .../lib/components/infoBadge/InfoBadge.svelte | 18 ++++---- .../components/input/PreviewAllInputs.svelte | 26 +++++++++-- .../components/input/PreviewAllInputs.type.ts | 12 +++++ frontend/src/lib/components/input/index.ts | 2 + .../src/lib/components/loading/Loading.svelte | 8 ++-- .../components/matchScore/MatchScore.svelte | 3 +- .../components/openVAALogo/OpenVAALogo.svelte | 13 ++---- .../successMessage/SuccessMessage.svelte | 4 +- .../dynamic-components/appLogo/AppLogo.svelte | 9 ++-- .../dataConsent/DataConsent.svelte | 8 ++-- .../entityCard/EntityCard.svelte | 14 +++--- .../entityCard/EntityCardAction.svelte | 2 +- .../entityDetails/EntityChildren.svelte | 17 ++++--- .../entityDetails/EntityChildren.type.ts | 18 ++++++++ .../entityDetails/EntityInfo.svelte | 12 +++-- .../entityDetails/EntityInfo.type.ts | 14 ++++++ .../entityDetails/EntityOpinions.svelte | 16 ++++--- .../entityDetails/EntityOpinions.type.ts | 19 ++++++++ .../entityDetails/InfoItem.svelte | 15 +++--- .../entityDetails/InfoItem.type.ts | 12 +++++ .../dynamic-components/entityDetails/index.ts | 5 ++ .../entityList/EntityListControls.svelte | 9 ++-- .../feedback/Feedback.svelte | 12 +++-- .../logoutButton/LogoutButton.svelte | 6 +++ .../navigation/NavGroup.svelte | 12 ++--- .../navigation/NavItem.svelte | 8 ++-- .../navigation/Navigation.svelte | 11 ++--- .../navigation/admin/AdminNav.svelte | 4 ++ .../navigation/admin/AdminNav.type.ts | 3 ++ .../navigation/admin/index.ts | 1 + .../navigation/candidate/CandidateNav.svelte | 10 +++- .../navigation/candidate/CandidateNav.type.ts | 3 ++ .../navigation/candidate/index.ts | 1 + .../navigation/voter/VoterNav.svelte | 4 ++ .../navigation/voter/VoterNav.type.ts | 3 ++ .../navigation/voter/index.ts | 1 + 82 files changed, 641 insertions(+), 267 deletions(-) create mode 100644 frontend/src/lib/candidate/components/passwordField/PasswordField.type.ts create mode 100644 frontend/src/lib/candidate/components/passwordSetter/PasswordSetter.type.ts create mode 100644 frontend/src/lib/candidate/components/passwordValidator/PasswordValidator.type.ts create mode 100644 frontend/src/lib/candidate/components/preregisteredNotification/PreregisteredNotification.type.ts create mode 100644 frontend/src/lib/components/controller/InfoMessages.type.ts create mode 100644 frontend/src/lib/components/controller/ProgressBar.type.ts create mode 100644 frontend/src/lib/components/controller/WarningMessages.type.ts create mode 100644 frontend/src/lib/components/input/PreviewAllInputs.type.ts create mode 100644 frontend/src/lib/dynamic-components/entityDetails/EntityChildren.type.ts create mode 100644 frontend/src/lib/dynamic-components/entityDetails/EntityInfo.type.ts create mode 100644 frontend/src/lib/dynamic-components/entityDetails/EntityOpinions.type.ts create mode 100644 frontend/src/lib/dynamic-components/entityDetails/InfoItem.type.ts create mode 100644 frontend/src/lib/dynamic-components/navigation/admin/AdminNav.type.ts create mode 100644 frontend/src/lib/dynamic-components/navigation/candidate/CandidateNav.type.ts create mode 100644 frontend/src/lib/dynamic-components/navigation/voter/VoterNav.type.ts diff --git a/frontend/src/lib/admin/components/jobs/FeatureJobs.svelte b/frontend/src/lib/admin/components/jobs/FeatureJobs.svelte index 7eefffa4a..9a6395432 100644 --- a/frontend/src/lib/admin/components/jobs/FeatureJobs.svelte +++ b/frontend/src/lib/admin/components/jobs/FeatureJobs.svelte @@ -1,3 +1,20 @@ + +
diff --git a/frontend/src/lib/components/controller/InfoMessages.type.ts b/frontend/src/lib/components/controller/InfoMessages.type.ts new file mode 100644 index 000000000..3af684d9b --- /dev/null +++ b/frontend/src/lib/components/controller/InfoMessages.type.ts @@ -0,0 +1,9 @@ +import type { SvelteHTMLElements } from 'svelte/elements'; +import type { JobMessage } from '$lib/server/admin/jobs/jobStore.type'; + +export type InfoMessagesProps = SvelteHTMLElements['div'] & { + /** + * Array of informational messages to display. @default [] + */ + messages?: Array; +}; diff --git a/frontend/src/lib/components/controller/ProgressBar.svelte b/frontend/src/lib/components/controller/ProgressBar.svelte index e685282b7..b4cf7a718 100644 --- a/frontend/src/lib/components/controller/ProgressBar.svelte +++ b/frontend/src/lib/components/controller/ProgressBar.svelte @@ -1,15 +1,45 @@ -
diff --git a/frontend/src/lib/components/controller/WarningMessages.type.ts b/frontend/src/lib/components/controller/WarningMessages.type.ts new file mode 100644 index 000000000..d2b7da11c --- /dev/null +++ b/frontend/src/lib/components/controller/WarningMessages.type.ts @@ -0,0 +1,13 @@ +import type { SvelteHTMLElements } from 'svelte/elements'; +import type { JobMessage } from '$lib/server/admin/jobs/jobStore.type'; + +export type WarningMessagesProps = SvelteHTMLElements['div'] & { + /** + * Array of warning messages to display. @default [] + */ + warnings?: Array; + /** + * Array of error messages to display. @default [] + */ + errors?: Array; +}; diff --git a/frontend/src/lib/components/controller/index.ts b/frontend/src/lib/components/controller/index.ts index e91df14d9..c9041285e 100644 --- a/frontend/src/lib/components/controller/index.ts +++ b/frontend/src/lib/components/controller/index.ts @@ -1,3 +1,6 @@ export { default as InfoMessages } from './InfoMessages.svelte'; +export * from './InfoMessages.type'; export { default as ProgressBar } from './ProgressBar.svelte'; +export * from './ProgressBar.type'; export { default as WarningMessages } from './WarningMessages.svelte'; +export * from './WarningMessages.type'; diff --git a/frontend/src/lib/components/electionTag/ElectionTag.svelte b/frontend/src/lib/components/electionTag/ElectionTag.svelte index 55d138e81..b9ad41f80 100644 --- a/frontend/src/lib/components/electionTag/ElectionTag.svelte +++ b/frontend/src/lib/components/electionTag/ElectionTag.svelte @@ -7,8 +7,8 @@ Used when the application has multiple elections and question may apply to only ### Properties - `election`: The `Election` object. -- `variant`: Whether to use an abbreviation or the full name. @default `'short'` -- `onShadedBg`: Set to `true` if using the component on a dark (`base-300`) background. @default false +- `variant`: Whether to use an abbreviation or the full name. Default: `'short'` +- `onShadedBg`: Set to `true` if using the component on a dark (`base-300`) background. Default: `false` - Any valid attributes of a `` element. ### Usage diff --git a/frontend/src/lib/components/entityFilters/EntityFilters.svelte b/frontend/src/lib/components/entityFilters/EntityFilters.svelte index 41fdce52a..572f69e52 100644 --- a/frontend/src/lib/components/entityFilters/EntityFilters.svelte +++ b/frontend/src/lib/components/entityFilters/EntityFilters.svelte @@ -4,9 +4,9 @@ Show filters for entities. This component and the individual filter components o ### Properties -- `filters`: The filter objects to render. +- `filterGroup`: The filters applied to the contents. - `targets`: The target entitiess of the filter objects. Note that these will only be used to get value options, not for actual filtering. -- Any valid attributes of a `
` element +- Any valid attributes of a `
` element. ### Usage diff --git a/frontend/src/lib/components/entityFilters/text/TextEntityFilter.svelte b/frontend/src/lib/components/entityFilters/text/TextEntityFilter.svelte index 3e1d194fc..712dd7450 100644 --- a/frontend/src/lib/components/entityFilters/text/TextEntityFilter.svelte +++ b/frontend/src/lib/components/entityFilters/text/TextEntityFilter.svelte @@ -4,9 +4,10 @@ Render a text filter for entities. ### Properties -- `filter`: The text filter object to render. -- `placeholder`: The placeholder text. @default `$t('entityFilters.text.placeholder')` -- Any valid attributes of a `
` element +- `filter`: The text filter object. +- `placeholder`: The placeholder text. Default: `$t('components.entityFilters.text.placeholder')` +- `variant`: The styling variant for the text field. Default: `'default'` +- Any valid attributes of a `
` element. ### Usage diff --git a/frontend/src/lib/components/entityTag/EntityTag.svelte b/frontend/src/lib/components/entityTag/EntityTag.svelte index b3e713bb7..ce59e4ce0 100644 --- a/frontend/src/lib/components/entityTag/EntityTag.svelte +++ b/frontend/src/lib/components/entityTag/EntityTag.svelte @@ -5,8 +5,8 @@ Used to display an `Entity` as small tag including an icon. ### Properties - `entity`: A possibly wrapped entity, e.g. candidate or a party. -- `variant`: Whether to use an abbreviation or the full name. @default `'default'` -- `hideParent`: Whether to hide the possible parent nomination. @default false +- `variant`: Whether to use an abbreviation or the full name. Default: `'default'` +- `hideParent`: Whether to hide the possible parent nomination. Default: `false` - Any valid attributes of a `
` element. ### Usage diff --git a/frontend/src/lib/components/errorMessage/ErrorMessage.svelte b/frontend/src/lib/components/errorMessage/ErrorMessage.svelte index e01af11cd..0a0ccc966 100644 --- a/frontend/src/lib/components/errorMessage/ErrorMessage.svelte +++ b/frontend/src/lib/components/errorMessage/ErrorMessage.svelte @@ -4,9 +4,9 @@ Used to display an error message. Also logs the error to the console. ### Properties -- `inline`: Whether to show an inline version of the message. By default the message tries to center itself in the available area and displays a large emoji. @default `false` -- `message`: The message to display. Default `$t('error.default')` -- `logMessage`: The message to log in the console in development mode. @default value of `message` +- `inline`: Whether to show an inline version of the message. By default the message tries to center itself in the available area and displays a large emoji. Default: `false` +- `message`: The message to display. Default: `$t('error.default')` +- `logMessage`: The message to log in the console in development mode. Default: value of `message` - Any valid attributes of a `
` element. ### Usage diff --git a/frontend/src/lib/components/expander/Expander.svelte b/frontend/src/lib/components/expander/Expander.svelte index 2d03b9438..a116b1497 100644 --- a/frontend/src/lib/components/expander/Expander.svelte +++ b/frontend/src/lib/components/expander/Expander.svelte @@ -13,15 +13,14 @@ A component for expanders that contain a title and some content. Use the ### Properties -- `title`: Title used for the expander. This is also used as the aria-label for - the checkbox on which the expander operates on. -- `variant`: The type for the expander. -- `iconColor`: The color for the icon. Default color is primary. -- `iconPos`: The position for the icon. Default is text, which means the icon will - be where the text ends. -- `titleClass`: Custom class string to add to the `
` containing the title. -- `contentClass`: Custom class string to add to the `
` containing the main content. +- `title`: Title is seen as the text in the expander's visible part, and it is mandatory. Title will also be used as a 'aria-label' for a checkbow on which the expander operates on. +- `iconColor`: The color of the next-icon that is used in the expander. Default: `'primary'` +- `iconPos`: The position of the next-icon that is used in the expander. Default: `'text'` +- `titleClass`: Variable with which to configure the expanders title if no variants are in use. +- `contentClass`: Variable with which to configure the expanders content if no variants are in use. - `defaultExpanded`: Variable used to define if the expander is expanded or not by default. +- `variant`: Variable used to define a variant for the expander. +- Any valid attributes of a `
` element. You should not try to use a variant and customize at the same time. diff --git a/frontend/src/lib/components/headingGroup/HeadingGroup.svelte b/frontend/src/lib/components/headingGroup/HeadingGroup.svelte index 6d417dd21..47b2a329e 100644 --- a/frontend/src/lib/components/headingGroup/HeadingGroup.svelte +++ b/frontend/src/lib/components/headingGroup/HeadingGroup.svelte @@ -5,8 +5,8 @@ and the main title. ### Properties -- `aria-roledescription`: The Aria role description of the `
` element representing the pre-title. @default $t('components.headingGroup.roleDescription') -- `role`: The Aria role of the `
` element. @default 'group' +- `aria-roledescription`: The Aria role description of the `
` element. Default: `$t('aria.headingGroup')` +- `role`: The Aria role of the `
` element. Default: `'group'` - Any valid attributes of a `
` element. ### Slots diff --git a/frontend/src/lib/components/headingGroup/PreHeading.svelte b/frontend/src/lib/components/headingGroup/PreHeading.svelte index ad66f50ba..6787d4b1e 100644 --- a/frontend/src/lib/components/headingGroup/PreHeading.svelte +++ b/frontend/src/lib/components/headingGroup/PreHeading.svelte @@ -4,7 +4,7 @@ Used for a pre-title, or kicker, above the main title of a page within a `Headin ### Properties -- `aria-roledescription`: The Aria role description of the `

` element representing the pre-title. @default $t('components.preHeading.roleDescription') +- `aria-roledescription`: The Aria role description of the `

` element representing the pre-title. Default: `$t('aria.preHeading')` - Any valid attributes of a `

` element. ### Slots diff --git a/frontend/src/lib/components/heroEmoji/HeroEmoji.svelte b/frontend/src/lib/components/heroEmoji/HeroEmoji.svelte index d22e9486e..1727a70b4 100644 --- a/frontend/src/lib/components/heroEmoji/HeroEmoji.svelte +++ b/frontend/src/lib/components/heroEmoji/HeroEmoji.svelte @@ -12,10 +12,7 @@ using the `class` attribute, e.g. `class="text-[10rem]"`. ### Properties -- `emoji`: The emoji to use. Note that all non-emoji characters will be removed. If `undefined` the component will not be rendered at all. @default `undefined` -- `aria-hidden`: @default `true` -- `role`: Aria role @default `img` -- `class`: Additional class string to append to the element's default classes. +- `emoji`: The emoji to use. Note that all non-emoji characters will be removed. If `undefined` the component will not be rendered at all. Default: `undefined` - Any valid attributes of a `

` element. ### Usage diff --git a/frontend/src/lib/components/icon/Icon.svelte b/frontend/src/lib/components/icon/Icon.svelte index 283cc596e..f3b8e1bbc 100644 --- a/frontend/src/lib/components/icon/Icon.svelte +++ b/frontend/src/lib/components/icon/Icon.svelte @@ -8,15 +8,12 @@ any valid attributes of the `` element. ### Properties -- `name`: the name of the icon to use -- `size`: The size of the icon as one of the predefined sizes 'sm', 'md' or 'lg'. For arbitrary values, you can supply a `class` property, such as `h-[3.15rem] w-[3.15rem]`. @default 'md' -- `color`: The color of the icon as one of the predefined colours. For arbitrary values, use the `customColor` and `customColorDark` properties. @default 'current' +- `name`: The name of the icon to use. +- `size`: The size of the icon as one of the predefined sizes 'sm', 'md' or 'lg'. For arbitrary values, you can supply a `class` property, such as `h-[3.15rem] w-[3.15rem]`. Default: `'md'` +- `color`: The color of the icon as one of the predefined colours. For arbitrary values, use the `customColor` and `customColorDark` properties. Default: `'current'` - `customColor`: A custom color string to use for the icon, e.g. in case of parties, which will override the `color` property. Make sure to define both `customColor` and `customColorDark` together. - `customColorDark`: A custom color string to use for the icon in dark mode, which will override the `color` property. -- `aria-hidden`: @default `true` -- `role`: Aria role @default `img` -- `class`: Additional class string to append to the element's default classes. -- Any valid attributes of a `` element +- Any valid attributes of a `` element. ### Usage diff --git a/frontend/src/lib/components/infoAnswer/InfoAnswer.svelte b/frontend/src/lib/components/infoAnswer/InfoAnswer.svelte index 4d4f9b472..e6d333ce7 100644 --- a/frontend/src/lib/components/infoAnswer/InfoAnswer.svelte +++ b/frontend/src/lib/components/infoAnswer/InfoAnswer.svelte @@ -6,7 +6,7 @@ Used to display a possibly wrapped entity's answer to an info question. Dependin - `answer`: The possibly missing answer to the question. - `question`: The info question object. -- `format`: How to format the answer. @default `default` +- `format`: How to format the answer. Default: `'default'` - `default`: use the same format as in ``. - `tag`: format the answers as a pill or tag. Nb. links are always rendered as tags. - Any valid common attributes of an HTML element. diff --git a/frontend/src/lib/components/infoBadge/InfoBadge.svelte b/frontend/src/lib/components/infoBadge/InfoBadge.svelte index a0d03016c..ab99d8d55 100644 --- a/frontend/src/lib/components/infoBadge/InfoBadge.svelte +++ b/frontend/src/lib/components/infoBadge/InfoBadge.svelte @@ -1,16 +1,18 @@
diff --git a/frontend/src/lib/components/input/PreviewAllInputs.type.ts b/frontend/src/lib/components/input/PreviewAllInputs.type.ts new file mode 100644 index 000000000..57b5e77cc --- /dev/null +++ b/frontend/src/lib/components/input/PreviewAllInputs.type.ts @@ -0,0 +1,12 @@ +import type { SvelteHTMLElements } from 'svelte/elements'; + +export type PreviewAllInputsProps = SvelteHTMLElements['div'] & { + /** + * Optional info text to display with inputs. + */ + info?: string; + /** + * Whether inputs are locked. @default false + */ + locked?: boolean; +}; diff --git a/frontend/src/lib/components/input/index.ts b/frontend/src/lib/components/input/index.ts index f24890611..a57399a6f 100644 --- a/frontend/src/lib/components/input/index.ts +++ b/frontend/src/lib/components/input/index.ts @@ -2,6 +2,8 @@ export { default as Input } from './Input.svelte'; export * from './Input.type'; export { default as InputGroup } from './InputGroup.svelte'; export * from './InputGroup.type'; +export { default as PreviewAllInputs } from './PreviewAllInputs.svelte'; +export * from './PreviewAllInputs.type'; export { default as QuestionInput } from './QuestionInput.svelte'; export * from './QuestionInput.type'; export * from './shared'; diff --git a/frontend/src/lib/components/loading/Loading.svelte b/frontend/src/lib/components/loading/Loading.svelte index 797018e8b..4139ea182 100644 --- a/frontend/src/lib/components/loading/Loading.svelte +++ b/frontend/src/lib/components/loading/Loading.svelte @@ -4,10 +4,10 @@ Used to display a loading spinner with an optionally visible text label. ### Properties -- `inline`: Whether to show an inline version of the spinner. By default the spinner tries to center itself in the available area. @default `false` -- `label`: he label text. @default `$t('common.loading')` -- `showLabel`: Whether to show the text label. The label will always be shown to screen readers. @default `false` -- `size`: The size of the loading spinner. @default `'lg'` +- `inline`: Whether to show an inline version of the spinner. By default the spinner tries to center itself in the available area. Default: `false` +- `label`: The label text. Default: `$t('common.loading')` +- `showLabel`: Whether to show the text label. The label will always be shown to screen readers. Default: `false` +- `size`: The size of the loading spinner. Default: `'lg'` - Any valid attributes of a `
` element. ### Usage diff --git a/frontend/src/lib/components/matchScore/MatchScore.svelte b/frontend/src/lib/components/matchScore/MatchScore.svelte index ec10ca6d0..125984298 100644 --- a/frontend/src/lib/components/matchScore/MatchScore.svelte +++ b/frontend/src/lib/components/matchScore/MatchScore.svelte @@ -5,7 +5,8 @@ Display an entity's match score. ### Properties - `score`: The match score as a `string` or a `number`. Note that `$t('components.matchScore.label')` will be used display the score. -- `label`: The label to display under the score. @default `$t('components.matchScore.label')` +- `label`: The label to display under the score. Default: `$t('components.matchScore.label')` +- `showLabel`: Whether to show the label. Default: `true` - Any valid attributes of a `
` element ### Usage diff --git a/frontend/src/lib/components/openVAALogo/OpenVAALogo.svelte b/frontend/src/lib/components/openVAALogo/OpenVAALogo.svelte index 4f30aa7ba..ae420a21b 100644 --- a/frontend/src/lib/components/openVAALogo/OpenVAALogo.svelte +++ b/frontend/src/lib/components/openVAALogo/OpenVAALogo.svelte @@ -8,15 +8,10 @@ attributes of one. ### Properties -- `title`: The `` of the SVG logo. Functions much the same way as the `alt`` - attribute of an `<img>`. -- `color`: The color of the logo as one of the predefined colours. - For arbitrary values, you can supply a `class` property, such as - `fill-[#123456]`. @default `'neutral'` - - `size`: The size of the logo as one of the predefined sizes 'sm', 'md' or 'lg'. - For arbitrary values, you can supply a `class` attribute, such as - `class="h-[3.5rem]"`. @default `'md'` - - Any valid attributes of a `<svg>` element +- `title`: The `<title>` of the SVG logo. Functions much the same way as the `alt` attribute of an `<img>`. Default: `'OpenVAA'` +- `size`: The size of the logo as one of the predefined sizes 'sm', 'md' or 'lg'. For arbitrary values, you can supply a `class` property, such as `h-[3.15rem] w-[3.15rem]`. Default: `'md'` +- `color`: The color of the logo as one of the predefined colours. For arbitrary values, you can supply a `class` property, such as `fill-[#123456]`. Default: `'neutral'` +- Any valid attributes of a `<svg>` element. ### Usage diff --git a/frontend/src/lib/components/successMessage/SuccessMessage.svelte b/frontend/src/lib/components/successMessage/SuccessMessage.svelte index d787cffa1..ff849744f 100644 --- a/frontend/src/lib/components/successMessage/SuccessMessage.svelte +++ b/frontend/src/lib/components/successMessage/SuccessMessage.svelte @@ -4,8 +4,8 @@ Used to display a message when an action succeeds. ### Properties -- `inline`: Whether to show an inline version of the message. By default the message tries to center itself in the available area and displays a large emoji. @default `false` -- `message`: The error message to display. Default `$t('common.success')` +- `inline`: Whether to show an inline version of the message. By default the message tries to center itself in the available area and displays a large emoji. Default: `false` +- `message`: The message to display. Default: `$t('common.success')` - Any valid attributes of a `<div>` element. ### Usage diff --git a/frontend/src/lib/dynamic-components/appLogo/AppLogo.svelte b/frontend/src/lib/dynamic-components/appLogo/AppLogo.svelte index 64002c7e2..6be371a3f 100644 --- a/frontend/src/lib/dynamic-components/appLogo/AppLogo.svelte +++ b/frontend/src/lib/dynamic-components/appLogo/AppLogo.svelte @@ -10,11 +10,10 @@ Logo files for use on a light and a dark background can be defined. If the latte ### Properties -- `alt`: The `alt` text for the logo image. -- `inverse`: If `true`, the light and dark versions of the logo will be reversed. Set to `true` if using the logo on a dark background. @default `false` -- `size`: The size of the logo as one of the predefined sizes 'sm', 'md' or 'lg'. For arbitrary values, you can supply a `class` attribute, such as `class="h-[3.5rem]"`. @default `'md'` -- `class`: Additional class string to append to the element's default classes. -- Any valid attributes of the `<div>` element wrapping the light and dark `<img>` elements +- `alt`: The `alt` text for the logo image. If missing, the publisher name or 'OpenVAA' will be used, depending on the logo shown. +- `inverse`: If `true`, the light and dark versions of the logo will be reversed. Set to `true` if using the logo on a dark background. Default: `false` +- `size`: The size of the logo as one of the predefined sizes 'sm', 'md' or 'lg'. For arbitrary values, you can supply a `class` attribute, such as `class="h-[3.5rem]"`. Default: `'md'` +- Any valid attributes of a `<div>` element ### Usage diff --git a/frontend/src/lib/dynamic-components/dataConsent/DataConsent.svelte b/frontend/src/lib/dynamic-components/dataConsent/DataConsent.svelte index 06aca1b97..cc995a86d 100644 --- a/frontend/src/lib/dynamic-components/dataConsent/DataConsent.svelte +++ b/frontend/src/lib/dynamic-components/dataConsent/DataConsent.svelte @@ -8,10 +8,10 @@ Accesses `AppContext` to set and read `userPreferences`. ### Properties -- `description`: Whether and how to show the data consent description. @default `modal` - - `none`: Don’t show the description. - - `inline`: Show the consent description above the buttons. - - `modal`: Show a button that opens the description in a modal. +- `description`: Whether and how to show the data consent description. Default: `'modal'` + - `'none'`: Don't show the description. + - `'inline'`: Show the consent description above the buttons. + - `'modal'`: Show a button that opens the description in a modal. - Any valid attributes of a `<div>` element. ### Events diff --git a/frontend/src/lib/dynamic-components/entityCard/EntityCard.svelte b/frontend/src/lib/dynamic-components/entityCard/EntityCard.svelte index bfb2604ad..02a9f2b02 100644 --- a/frontend/src/lib/dynamic-components/entityCard/EntityCard.svelte +++ b/frontend/src/lib/dynamic-components/entityCard/EntityCard.svelte @@ -12,14 +12,14 @@ This is a dynamic component, because it accesses the `dataRoot` and other proper ### Properties -- `action`: Custom action to take when the card is clicked, defaults to a link to the entity’s `ResultEntity` route. If the card has subentites, the action will only be triggered by clicking the content above them. -- `entity`: A possibly ranked nakedEntity, e.g. candidate or a party. -- `variant`: The variant-dependend layout variant. Usually set automatically. - - `'list'`: In a list of entities. The default. +- `action`: Custom action to take when the card is clicked, defaults to a link to the entity's `ResultEntity` route. If the card has subentites, the action will only be triggered by clicking the content above them. +- `entity`: A possibly ranked entity, e.g. candidate or a party. +- `variant`: The context-dependend layout variant. Usually set automatically. Default: `'list'` + - `'list'`: In a list of entities. - `'details'`: As part of the header of `EntityDetails`. - - `'subcard'`; In a list of nested nakedEntity cards, e.g., the candidates for a party. -- `maxSubcards`: The maximum number of sub-entities to show. If there are more a button will be shown for displaying the remaining ones. @default `3` -- `showElection`: Whether to show the possible nomination’s election and constituency. @default `false` + - `'subcard'`: In a list of nested entity cards, e.g., the candidates for a party. +- `maxSubcards`: The maximum number of sub-entities to show. If there are more a button will be shown for displaying the remaining ones. Default: `3` +- `showElection`: Whether to show the possible nomination's election and constituency. Default: `false` - Any valid attributes of an `<article>` element. ### Tracking events diff --git a/frontend/src/lib/dynamic-components/entityCard/EntityCardAction.svelte b/frontend/src/lib/dynamic-components/entityCard/EntityCardAction.svelte index 44f00a43f..62fed30f0 100644 --- a/frontend/src/lib/dynamic-components/entityCard/EntityCardAction.svelte +++ b/frontend/src/lib/dynamic-components/entityCard/EntityCardAction.svelte @@ -6,7 +6,7 @@ TODO[Svelte 5]: Maybe convert into `$snippet`. ### Properties - `action`: The action to take when the part or card is clicked. -- `shadeOnHover`: Whether to shade the element on hover. Use when applying to subcards or their parent card's header. @default `false` +- `shadeOnHover`: Whether to shade the element on hover. Use when applying to subcards or their parent card's header. Default: `false` - Any valid attributes common to HTML elements. Note that these will only be applied if `<EntityCardAction>` is rendered. ### Slots diff --git a/frontend/src/lib/dynamic-components/entityDetails/EntityChildren.svelte b/frontend/src/lib/dynamic-components/entityDetails/EntityChildren.svelte index f9d35a0b0..6a22e33f2 100644 --- a/frontend/src/lib/dynamic-components/entityDetails/EntityChildren.svelte +++ b/frontend/src/lib/dynamic-components/entityDetails/EntityChildren.svelte @@ -4,9 +4,10 @@ Used to show an entity's children in an `EntityDetails` component. ### Properties -- `entities`: An array of possibly ranked entities, e.g. a party’s candidates. -- `entityType`: The type of the entities being displayed. Used to pick correct translations +- `entities`: An array of possibly ranked entities, e.g. a party's candidates. +- `entityType`: The type of the entities being displayed. Used to pick correct translations. - `action`: An optional callback for building the card actions for the child possible entities. If nullish, the default action filled in by `EntityCard` will be used. If `false`, no actions will be added. +- Any valid attributes of a `<div>` element ### Usage @@ -19,12 +20,14 @@ Used to show an entity's children in an `EntityDetails` component. import { getComponentContext } from '$lib/contexts/component'; import { EntityList } from '$lib/dynamic-components/entityList'; import { EntityListControls } from '../entityList'; - import type { EntityType } from '@openvaa/data'; - import type { CardAction, EntityCardProps } from '../entityCard'; + import type { EntityCardProps } from '../entityCard'; + import type { EntityChildrenProps } from './EntityChildren.type'; - export let entities: Array<MaybeWrappedEntityVariant>; - export let entityType: EntityType; - export let action: ((entity: MaybeWrappedEntityVariant) => CardAction) | false | null | undefined = undefined; + type $$Props = EntityChildrenProps; + + export let entities: $$Props['entities']; + export let entityType: $$Props['entityType']; + export let action: $$Props['action'] = undefined; //////////////////////////////////////////////////////////////////// // Get contexts diff --git a/frontend/src/lib/dynamic-components/entityDetails/EntityChildren.type.ts b/frontend/src/lib/dynamic-components/entityDetails/EntityChildren.type.ts new file mode 100644 index 000000000..b48b291f4 --- /dev/null +++ b/frontend/src/lib/dynamic-components/entityDetails/EntityChildren.type.ts @@ -0,0 +1,18 @@ +import type { EntityType } from '@openvaa/data'; +import type { SvelteHTMLElements } from 'svelte/elements'; +import type { CardAction } from '../entityCard'; + +export type EntityChildrenProps = SvelteHTMLElements['div'] & { + /** + * An array of possibly ranked entities, e.g. a party's candidates. + */ + entities: Array<MaybeWrappedEntityVariant>; + /** + * The type of the entities being displayed. Used to pick correct translations. + */ + entityType: EntityType; + /** + * An optional callback for building the card actions for the child possible entities. If nullish, the default action filled in by `EntityCard` will be used. If `false`, no actions will be added. + */ + action?: ((entity: MaybeWrappedEntityVariant) => CardAction) | false | null; +}; diff --git a/frontend/src/lib/dynamic-components/entityDetails/EntityInfo.svelte b/frontend/src/lib/dynamic-components/entityDetails/EntityInfo.svelte index 3889983ed..2824a7d75 100644 --- a/frontend/src/lib/dynamic-components/entityDetails/EntityInfo.svelte +++ b/frontend/src/lib/dynamic-components/entityDetails/EntityInfo.svelte @@ -9,7 +9,8 @@ This is a dynamic component, because it accesses `appSettings` and `dataRoot` fr ### Properties - `entity`: A possibly ranked entity, e.g. candidate or a party. -- `questions`: An array of `info` questions +- `questions`: An array of `info` questions. +- Any valid attributes of a `<div>` element ### Settings @@ -28,7 +29,6 @@ This is a dynamic component, because it accesses `appSettings` and `dataRoot` fr import { type AnyEntityVariant, type AnyNominationVariant, - type AnyQuestionVariant, ENTITY_TYPE, type EntityType, isObjectType, @@ -42,10 +42,12 @@ This is a dynamic component, because it accesses `appSettings` and `dataRoot` fr import { unwrapEntity } from '$lib/utils/entities'; import { sanitizeHtml } from '$lib/utils/sanitize'; import InfoItem from './InfoItem.svelte'; - import type { EntityDetailsProps } from './EntityDetails.type'; + import type { EntityInfoProps } from './EntityInfo.type'; - export let entity: EntityDetailsProps['entity']; - export let questions: Array<AnyQuestionVariant>; + type $$Props = EntityInfoProps; + + export let entity: $$Props['entity']; + export let questions: $$Props['questions']; //////////////////////////////////////////////////////////////////// // Get contexts diff --git a/frontend/src/lib/dynamic-components/entityDetails/EntityInfo.type.ts b/frontend/src/lib/dynamic-components/entityDetails/EntityInfo.type.ts new file mode 100644 index 000000000..0527f27ca --- /dev/null +++ b/frontend/src/lib/dynamic-components/entityDetails/EntityInfo.type.ts @@ -0,0 +1,14 @@ +import type { AnyQuestionVariant } from '@openvaa/data'; +import type { SvelteHTMLElements } from 'svelte/elements'; +import type { EntityDetailsProps } from './EntityDetails.type'; + +export type EntityInfoProps = SvelteHTMLElements['div'] & { + /** + * A possibly ranked entity, e.g. candidate or a party. + */ + entity: EntityDetailsProps['entity']; + /** + * An array of `info` questions. + */ + questions: Array<AnyQuestionVariant>; +}; diff --git a/frontend/src/lib/dynamic-components/entityDetails/EntityOpinions.svelte b/frontend/src/lib/dynamic-components/entityDetails/EntityOpinions.svelte index a029d3be7..9c80eb680 100644 --- a/frontend/src/lib/dynamic-components/entityDetails/EntityOpinions.svelte +++ b/frontend/src/lib/dynamic-components/entityDetails/EntityOpinions.svelte @@ -6,7 +6,8 @@ Used to show an entity's answers to `opinion` questions and possibly those of th - `entity`: A possibly ranked entity, e.g. candidate or a party. - `questions`: An array of `opinion` questions. -- `answers`: An optional `AnswerStore` with the Voter’s answers to the questions. +- `answers`: An optional `AnswerStore` with the Voter's answers to the questions. +- Any valid attributes of a `<div>` element ### Usage @@ -21,13 +22,14 @@ Used to show an entity's answers to `opinion` questions and possibly those of th import { OpinionQuestionInput, QuestionOpenAnswer } from '$lib/components/questions'; import { getAppContext } from '$lib/contexts/app'; import { unwrapEntity } from '$lib/utils/entities'; - import type { AnyEntityVariant, AnyQuestionVariant } from '@openvaa/data'; - import type { AnswerStore } from '$lib/contexts/voter'; - import type { EntityDetailsProps } from './EntityDetails.type'; + import type { AnyEntityVariant } from '@openvaa/data'; + import type { EntityOpinionsProps } from './EntityOpinions.type'; - export let entity: EntityDetailsProps['entity']; - export let questions: Array<AnyQuestionVariant>; - export let answers: AnswerStore | undefined = undefined; + type $$Props = EntityOpinionsProps; + + export let entity: $$Props['entity']; + export let questions: $$Props['questions']; + export let answers: $$Props['answers'] = undefined; //////////////////////////////////////////////////////////////////// // Get contexts diff --git a/frontend/src/lib/dynamic-components/entityDetails/EntityOpinions.type.ts b/frontend/src/lib/dynamic-components/entityDetails/EntityOpinions.type.ts new file mode 100644 index 000000000..c96327f1d --- /dev/null +++ b/frontend/src/lib/dynamic-components/entityDetails/EntityOpinions.type.ts @@ -0,0 +1,19 @@ +import type { AnyQuestionVariant } from '@openvaa/data'; +import type { SvelteHTMLElements } from 'svelte/elements'; +import type { AnswerStore } from '$lib/contexts/voter'; +import type { EntityDetailsProps } from './EntityDetails.type'; + +export type EntityOpinionsProps = SvelteHTMLElements['div'] & { + /** + * A possibly ranked entity, e.g. candidate or a party. + */ + entity: EntityDetailsProps['entity']; + /** + * An array of `opinion` questions. + */ + questions: Array<AnyQuestionVariant>; + /** + * An optional `AnswerStore` with the Voter's answers to the questions. + */ + answers?: AnswerStore; +}; diff --git a/frontend/src/lib/dynamic-components/entityDetails/InfoItem.svelte b/frontend/src/lib/dynamic-components/entityDetails/InfoItem.svelte index 38b40ede7..d4797ab50 100644 --- a/frontend/src/lib/dynamic-components/entityDetails/InfoItem.svelte +++ b/frontend/src/lib/dynamic-components/entityDetails/InfoItem.svelte @@ -4,8 +4,9 @@ Used to show a label-content pair in a Candidate's basic information. ### Properties -- `label`: the label of the information -- `vertical`: layout mode for the item +- `label`: The label of the information. +- `vertical`: Layout mode for the item. Default: `false` +- Any valid attributes of a `<div>` element ### Slots @@ -21,10 +22,12 @@ Used to show a label-content pair in a Candidate's basic information. --> <script lang="ts"> - /** The info label */ - export let label: string; - /** The info layout mode */ - export let vertical = false; + import type { InfoItemProps } from './InfoItem.type'; + + type $$Props = InfoItemProps; + + export let label: $$Props['label']; + export let vertical: $$Props['vertical'] = false; </script> <div class="grid justify-start gap-md {vertical ? 'vertical-grid' : 'horizontal-grid'}"> diff --git a/frontend/src/lib/dynamic-components/entityDetails/InfoItem.type.ts b/frontend/src/lib/dynamic-components/entityDetails/InfoItem.type.ts new file mode 100644 index 000000000..e3248efd0 --- /dev/null +++ b/frontend/src/lib/dynamic-components/entityDetails/InfoItem.type.ts @@ -0,0 +1,12 @@ +import type { SvelteHTMLElements } from 'svelte/elements'; + +export type InfoItemProps = SvelteHTMLElements['div'] & { + /** + * The label of the information. + */ + label: string; + /** + * Layout mode for the item. @default false + */ + vertical?: boolean; +}; diff --git a/frontend/src/lib/dynamic-components/entityDetails/index.ts b/frontend/src/lib/dynamic-components/entityDetails/index.ts index 92236e8f8..54e046dc1 100644 --- a/frontend/src/lib/dynamic-components/entityDetails/index.ts +++ b/frontend/src/lib/dynamic-components/entityDetails/index.ts @@ -1,7 +1,12 @@ export { default as EntityChildren } from './EntityChildren.svelte'; +export * from './EntityChildren.type'; export { default as EntityDetails } from './EntityDetails.svelte'; export * from './EntityDetails.type'; export { default as EntityDetailsDrawer } from './EntityDetailsDrawer.svelte'; export * from './EntityDetailsDrawer.type'; export { default as EntityInfo } from './EntityInfo.svelte'; +export * from './EntityInfo.type'; export { default as EntityOpinions } from './EntityOpinions.svelte'; +export * from './EntityOpinions.type'; +export { default as InfoItem } from './InfoItem.svelte'; +export * from './InfoItem.type'; diff --git a/frontend/src/lib/dynamic-components/entityList/EntityListControls.svelte b/frontend/src/lib/dynamic-components/entityList/EntityListControls.svelte index a45da8189..3f09f4d2d 100644 --- a/frontend/src/lib/dynamic-components/entityList/EntityListControls.svelte +++ b/frontend/src/lib/dynamic-components/entityList/EntityListControls.svelte @@ -7,14 +7,11 @@ TODO: Consider moving the tracking events away from the component and just addin ### Properties - `entities`: A list of possibly ranked entities, e.g. candidates or a parties. -- `filterGroup`: The filters applied to the entities -- `searchProperty`: The property used for the search tool. Default 'name' +- `filterGroup`: The filters applied to the contents. +- `searchProperty`: The property used for the search tool. Default: `'name'` +- `onUpdate`: Callback for when the filters are applied. - Any valid attributes of a `<div>` element. -### Callbacks - -- `onUpdate`: Callback for when the filters are applied. - ### Tracking events - `filters_reset` diff --git a/frontend/src/lib/dynamic-components/feedback/Feedback.svelte b/frontend/src/lib/dynamic-components/feedback/Feedback.svelte index 3eeaad309..96c23a4f0 100644 --- a/frontend/src/lib/dynamic-components/feedback/Feedback.svelte +++ b/frontend/src/lib/dynamic-components/feedback/Feedback.svelte @@ -8,14 +8,16 @@ Accesses the `AppContext` and the `FeedbackWriter` api. ### Properties +- `showActions`: Whether to show the standard action buttons below the feedback form. Default: `true` +- `variant`: The layout variant of the feedback form. Default: `'default'` - Any valid attributes of a `<form>` element. -### Bindable properties and functions +### Bindable properties -- `status`: The status of the feedback form. @default `'default'` -- `canSubmit`: Bind to this to know whether the feedback can be submitted, i.e. the user has entered something. @default `false` -- `reset()`: Reset the form so that if the user opens it again, they can fill new feedback. You should call this when closing any modal containing the feedback. -- `submit()`: Submit the feedback. +- `canSubmit`: Bind to this to know whether the feedback can be submitted, i.e. the user has entered something. Default: `false` +- `status`: Bind to this to access the status of the feedback form. Default: `'default'` +- `submit`: Submit the feedback or close the modal if it's already been submitted. +- `reset`: Reset the form so that if the user opens it again, they can fill new feedback. You should call this when closing any modal containing the feedback. ### Events diff --git a/frontend/src/lib/dynamic-components/logoutButton/LogoutButton.svelte b/frontend/src/lib/dynamic-components/logoutButton/LogoutButton.svelte index 23f60d4a7..c8c274ebf 100644 --- a/frontend/src/lib/dynamic-components/logoutButton/LogoutButton.svelte +++ b/frontend/src/lib/dynamic-components/logoutButton/LogoutButton.svelte @@ -6,7 +6,13 @@ Allows user to log out. Accesses `AuthContext` and `AppContext`. +### Properties + +- `redirectTo`: The route to redirect to after logging out. Default: `'Home'` +- Any valid properties of a `<Button>` component. + ### Usage + ```tsx <LogoutButton /> ``` diff --git a/frontend/src/lib/dynamic-components/navigation/NavGroup.svelte b/frontend/src/lib/dynamic-components/navigation/NavGroup.svelte index b4c0b27c8..d859ad8bd 100644 --- a/frontend/src/lib/dynamic-components/navigation/NavGroup.svelte +++ b/frontend/src/lib/dynamic-components/navigation/NavGroup.svelte @@ -2,16 +2,14 @@ @component Use to group `NavItem` components. Displays a faint line above the group. -### Slots +### Properties -- default: The contents of the navigation group. Should be mostly -`<NavItem>` components. +- `title`: Optional title for the navigation group. +- Any valid attributes of a `<ul>` element. -### Properties +### Slots -- `role`: Aria role @default `list` -- `class`: Additional class string to append to the element's default classes. -- Any valid attributes of a `<section>` element. +- default: The contents of the navigation group. Should be mostly `<NavItem>` components. ### Usage diff --git a/frontend/src/lib/dynamic-components/navigation/NavItem.svelte b/frontend/src/lib/dynamic-components/navigation/NavItem.svelte index a15125411..af8739c14 100644 --- a/frontend/src/lib/dynamic-components/navigation/NavItem.svelte +++ b/frontend/src/lib/dynamic-components/navigation/NavItem.svelte @@ -10,12 +10,10 @@ Accesses `LayoutContext`. ### Properties -- `href`: The URL to navigate to. If this is not supplied be sure to provide an `on:click` event handler or other way of making the item interactive. -- `icon`: An optional `IconName` of the icon to use. @default `undefined` -- `text`: A required text to display. -- `autoCloseNav`: Whether the menu available from the page context should be closed when the item is clicked. @default `true` +- `icon`: The optional name of the icon to use with the navigation item. See the `Icon` component for more details. +- `text`: The text to display in the navigation item. - `disabled`: Whether the button is disabled. This can also be used with items rendered as `<a>` elements. -- `class`: Additional class string to append to the element's default classes. +- `autoCloseNav`: Whether the menu available from the page context should be closed when the item is clicked. Default: `true` - Any valid attributes of either an `<a>` or `<button>` element depending whether `href` was defined or not, respectively. ### Usage diff --git a/frontend/src/lib/dynamic-components/navigation/Navigation.svelte b/frontend/src/lib/dynamic-components/navigation/Navigation.svelte index cc49d6c74..74f16a6b6 100644 --- a/frontend/src/lib/dynamic-components/navigation/Navigation.svelte +++ b/frontend/src/lib/dynamic-components/navigation/Navigation.svelte @@ -2,16 +2,15 @@ @component Create navigation menus for the application in a predefined style. -### Slots - -- default: The content of the navigation menu. It should mainly consist - of `<NavGroup>` components containing `<NavItem>` components. - ### Properties -- `hidden`: Set to `true` to whenever the navigation is hidden. @default false +- `hidden`: Set to `true` to whenever the navigation is hidden. Default: `false` - Any valid attributes of a `<nav>` element. +### Slots + +- default: The content of the navigation menu. It should mainly consist of `<NavGroup>` components containing `<NavItem>` components. + ### Events - `keyboardFocusOut`: Emitted when the component loses a keyboard user's diff --git a/frontend/src/lib/dynamic-components/navigation/admin/AdminNav.svelte b/frontend/src/lib/dynamic-components/navigation/admin/AdminNav.svelte index dcd72908d..f51986600 100644 --- a/frontend/src/lib/dynamic-components/navigation/admin/AdminNav.svelte +++ b/frontend/src/lib/dynamic-components/navigation/admin/AdminNav.svelte @@ -25,6 +25,10 @@ A template part that outputs the navigation menu for the Admin App for use in `L import { getLayoutContext } from '$lib/contexts/layout'; import { NavGroup, Navigation, NavItem } from '$lib/dynamic-components/navigation'; import { LanguageSelection } from '../languages'; + import type { AdminNavProps } from './AdminNav.type'; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + type $$Props = AdminNavProps; const { navigation } = getLayoutContext(onDestroy); const { authToken, t, getRoute } = getAdminContext(); diff --git a/frontend/src/lib/dynamic-components/navigation/admin/AdminNav.type.ts b/frontend/src/lib/dynamic-components/navigation/admin/AdminNav.type.ts new file mode 100644 index 000000000..a51f691d5 --- /dev/null +++ b/frontend/src/lib/dynamic-components/navigation/admin/AdminNav.type.ts @@ -0,0 +1,3 @@ +import type { NavigationProps } from '../Navigation.type'; + +export type AdminNavProps = NavigationProps; diff --git a/frontend/src/lib/dynamic-components/navigation/admin/index.ts b/frontend/src/lib/dynamic-components/navigation/admin/index.ts index fbafe1b5e..01b70f44e 100644 --- a/frontend/src/lib/dynamic-components/navigation/admin/index.ts +++ b/frontend/src/lib/dynamic-components/navigation/admin/index.ts @@ -1 +1,2 @@ export { default as AdminNav } from './AdminNav.svelte'; +export * from './AdminNav.type'; diff --git a/frontend/src/lib/dynamic-components/navigation/candidate/CandidateNav.svelte b/frontend/src/lib/dynamic-components/navigation/candidate/CandidateNav.svelte index bf6ce6e48..965045f03 100644 --- a/frontend/src/lib/dynamic-components/navigation/candidate/CandidateNav.svelte +++ b/frontend/src/lib/dynamic-components/navigation/candidate/CandidateNav.svelte @@ -1,11 +1,15 @@ <!-- @component -A template part that outputs the navigation menu for the Candidate App for use in use in `Layout`. +A template part that outputs the navigation menu for the Candidate App for use in `Layout`. ### Dynamic component - Accesses the `CandidateContext`. +### Properties + +- Any valid properties of a `Navigation` component + ### Usage ```tsx @@ -22,6 +26,10 @@ A template part that outputs the navigation menu for the Candidate App for use i import { getLayoutContext } from '$lib/contexts/layout'; import { NavGroup, Navigation, NavItem } from '$lib/dynamic-components/navigation'; import { LanguageSelection } from '../languages'; + import type { CandidateNavProps } from './CandidateNav.type'; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + type $$Props = CandidateNavProps; const { navigation } = getLayoutContext(onDestroy); const { diff --git a/frontend/src/lib/dynamic-components/navigation/candidate/CandidateNav.type.ts b/frontend/src/lib/dynamic-components/navigation/candidate/CandidateNav.type.ts new file mode 100644 index 000000000..540f9db9a --- /dev/null +++ b/frontend/src/lib/dynamic-components/navigation/candidate/CandidateNav.type.ts @@ -0,0 +1,3 @@ +import type { NavigationProps } from '../Navigation.type'; + +export type CandidateNavProps = NavigationProps; diff --git a/frontend/src/lib/dynamic-components/navigation/candidate/index.ts b/frontend/src/lib/dynamic-components/navigation/candidate/index.ts index 17cace842..6a623911a 100644 --- a/frontend/src/lib/dynamic-components/navigation/candidate/index.ts +++ b/frontend/src/lib/dynamic-components/navigation/candidate/index.ts @@ -1 +1,2 @@ export { default as CandidateNav } from './CandidateNav.svelte'; +export * from './CandidateNav.type'; diff --git a/frontend/src/lib/dynamic-components/navigation/voter/VoterNav.svelte b/frontend/src/lib/dynamic-components/navigation/voter/VoterNav.svelte index 6cdb23b66..c5dc05ed3 100644 --- a/frontend/src/lib/dynamic-components/navigation/voter/VoterNav.svelte +++ b/frontend/src/lib/dynamic-components/navigation/voter/VoterNav.svelte @@ -31,6 +31,10 @@ A template part that outputs the navigation menu for the Voter App for use in `L import { getVoterContext } from '$lib/contexts/voter'; import { NavGroup, Navigation, NavItem } from '$lib/dynamic-components/navigation'; import { LanguageSelection } from '../languages'; + import type { VoterNavProps } from './VoterNav.type'; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + type $$Props = VoterNavProps; const { navigation } = getLayoutContext(onDestroy); diff --git a/frontend/src/lib/dynamic-components/navigation/voter/VoterNav.type.ts b/frontend/src/lib/dynamic-components/navigation/voter/VoterNav.type.ts new file mode 100644 index 000000000..96e6ad512 --- /dev/null +++ b/frontend/src/lib/dynamic-components/navigation/voter/VoterNav.type.ts @@ -0,0 +1,3 @@ +import type { NavigationProps } from '../Navigation.type'; + +export type VoterNavProps = NavigationProps; diff --git a/frontend/src/lib/dynamic-components/navigation/voter/index.ts b/frontend/src/lib/dynamic-components/navigation/voter/index.ts index b1457f6fc..0aa55f2fd 100644 --- a/frontend/src/lib/dynamic-components/navigation/voter/index.ts +++ b/frontend/src/lib/dynamic-components/navigation/voter/index.ts @@ -1 +1,2 @@ export { default as VoterNav } from './VoterNav.svelte'; +export * from './VoterNav.type'; From 38d3cc25bdb4044b018843e412c5f0208e6ddbab Mon Sep 17 00:00:00 2001 From: kallelongjuhani <kalle.jarvenpaa@gmail.com> Date: Sun, 14 Dec 2025 11:28:47 +0200 Subject: [PATCH 2/4] docs: details about Svelte component documentation --- docs/code-review-checklist.md | 2 +- docs/contributing.md | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/code-review-checklist.md b/docs/code-review-checklist.md index 2f42e3963..08d9cc59d 100644 --- a/docs/code-review-checklist.md +++ b/docs/code-review-checklist.md @@ -10,7 +10,7 @@ When performing code review, double check all of the items below: - [ ] All new components, functions and other entities are documented - [ ] The repo documentation markdown files are updated if the changes touch upon those. - [ ] If the change adds functions available to the user, tracking events are enabled with new ones defined if needed. -- [ ] Any new Svelte components that have been created, follow the [Svelte component guidelines](contributing.md#svelte-components). +- [ ] Any new Svelte components that have been created follow the [Svelte component guidelines](contributing.md#svelte-components). - [ ] Errors are handled properly and logged in the code. - [ ] Troubleshoot any failing checks in the PR. - [ ] Check that parts of the application that share dependencies with the PR but are not included in it are not unduly affected. diff --git a/docs/contributing.md b/docs/contributing.md index 8b11f6531..03ac6d607 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -379,7 +379,14 @@ let className: $$Props['class'] = $$props['class']; Follow Svelte's [guidelines for component documentation](https://svelte.dev/docs/faq#how-do-i-document-my-components). For an example, see [`IconBase`](/frontend/src/lib/components/icon/base/IconBase.svelte) component and its associated [type definition](/frontend/src/lib/components/icon/base/IconBase.type.ts). -Place the Svelte docstring at the top of the file, before the `<script>` block. +Place the Svelte docstring at the top of the file, before the `<script>` block. The documentation must consist of: + +- general description +- 'Properties' (see below) +- 'Slots' detailing all slots and their uses (if applicable) +- 'Usage' showing a concise code block of the component’s use + +The type file defining the properties is the prime source of truth for the properties’ descriptions. Make sure the "Properties" section of the component doc string matches that. Add documentation for pages, layouts and other non-reusable components, detailing their main purpose. Include in their documentation under separate subheadings: From 135daaf02566f77980f3a0199e8a2d27dbd5e05f Mon Sep 17 00:00:00 2001 From: kallelongjuhani <kalle.jarvenpaa@gmail.com> Date: Sun, 14 Dec 2025 11:34:19 +0200 Subject: [PATCH 3/4] build: move Claude settings to non-local file --- .claude/settings.json | 7 +++++++ .claude/settings.local.json | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 .claude/settings.json delete mode 100644 .claude/settings.local.json diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 000000000..10842a650 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": ["Bash(yarn test:*)", "Bash(find:*)"], + "deny": [], + "ask": [] + } +} diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index f71f74de1..000000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "permissions": { - "allow": ["Bash(fi:*)", "Bash(done)", "Bash(yarn test:unit:*)"], - "deny": [], - "ask": [] - } -} From aa6b06e6799a64c4d942633eb31f13df656c50c4 Mon Sep 17 00:00:00 2001 From: kallelongjuhani <kalle.jarvenpaa@gmail.com> Date: Sun, 14 Dec 2025 11:34:37 +0200 Subject: [PATCH 4/4] build: ignore local Claude settings --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 35ae3bd9e..5b7d54f1c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ !.env.example node_modules +# Claude Code local settings +.claude/*.local.json + # Yarn 4 without Zero-installs .pnp.* .yarn/*