├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ └── feature-request.yml └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── package.json ├── pnpm-lock.yaml ├── src ├── app.html ├── global.d.ts ├── lib │ ├── Acrylic │ │ ├── AcrylicSurface.scss │ │ └── AcrylicSurface.svelte │ ├── AutoSuggestBox │ │ ├── AutoSuggestBox.scss │ │ └── AutoSuggestBox.svelte │ ├── Button │ │ ├── Button.scss │ │ └── Button.svelte │ ├── CalendarDatePicker │ │ ├── CalendarDatePicker.scss │ │ └── CalendarDatePicker.svelte │ ├── CalendarView │ │ ├── CalendarView.scss │ │ ├── CalendarView.svelte │ │ ├── CalendarViewItem.scss │ │ └── CalendarViewItem.svelte │ ├── Checkbox │ │ ├── Checkbox.scss │ │ └── Checkbox.svelte │ ├── ComboBox │ │ ├── ComboBox.scss │ │ ├── ComboBox.svelte │ │ ├── ComboBoxItem.scss │ │ └── ComboBoxItem.svelte │ ├── ContentDialog │ │ ├── ContentDialog.scss │ │ └── ContentDialog.svelte │ ├── ContextMenu │ │ ├── ContextMenu.scss │ │ └── ContextMenu.svelte │ ├── ExpandMenu │ │ └── ExpandMenu.svelte │ ├── Expander │ │ ├── Expander.scss │ │ └── Expander.svelte │ ├── Flipper │ │ └── Flipper.svelte │ ├── Flyout │ │ ├── FlyoutSurface.scss │ │ ├── FlyoutSurface.svelte │ │ ├── FlyoutWrapper.scss │ │ └── FlyoutWrapper.svelte │ ├── GridView │ │ ├── GridViewItem.scss │ │ └── GridViewItem.svelte │ ├── IconButton │ │ ├── IconButton.scss │ │ └── IconButton.svelte │ ├── InfoBadge │ │ ├── InfoBadge.scss │ │ └── InfoBadge.svelte │ ├── InfoBar │ │ ├── InfoBar.scss │ │ └── InfoBar.svelte │ ├── ListItem │ │ ├── ListItem.scss │ │ └── ListItem.svelte │ ├── MenuBar │ │ ├── MenuBar.scss │ │ ├── MenuBar.svelte │ │ ├── MenuBarItem.scss │ │ ├── MenuBarItem.svelte │ │ └── flyoutState.ts │ ├── MenuFlyout │ │ ├── MenuFlyoutDivider.scss │ │ ├── MenuFlyoutDivider.svelte │ │ ├── MenuFlyoutItem.scss │ │ ├── MenuFlyoutItem.svelte │ │ ├── MenuFlyoutSurface.scss │ │ ├── MenuFlyoutSurface.svelte │ │ ├── MenuFlyoutWrapper.scss │ │ └── MenuFlyoutWrapper.svelte │ ├── NavigationView │ │ ├── NavigationView.scss │ │ └── NavigationView.svelte │ ├── NumberBox │ │ ├── NumberBox.scss │ │ └── NumberBox.svelte │ ├── PersonPicture │ │ ├── PersonPicture.scss │ │ └── PersonPicture.svelte │ ├── ProgressBar │ │ ├── ProgressBar.scss │ │ └── ProgressBar.svelte │ ├── ProgressRing │ │ ├── ProgressRing.scss │ │ └── ProgressRing.svelte │ ├── RadioButton │ │ ├── RadioButton.scss │ │ └── RadioButton.svelte │ ├── RangeSlider │ │ └── RangeSlider.svelte │ ├── ScrollView │ │ └── ScrollView.svelte │ ├── SegmentedControl │ │ ├── SegmentedControl.scss │ │ ├── SegmentedControl.svelte │ │ ├── SegmentedControlButton.scss │ │ └── SegmentedControlButton.svelte │ ├── Slider │ │ ├── Slider.scss │ │ └── Slider.svelte │ ├── SplitButton │ │ ├── SplitButton.scss │ │ └── SplitButton.svelte │ ├── TeachingTip │ │ ├── TeachingTipSurface.scss │ │ ├── TeachingTipSurface.svelte │ │ ├── TeachingTipWrapper.scss │ │ └── TeachingTipWrapper.svelte │ ├── TextArea │ │ ├── TextArea.scss │ │ └── TextArea.svelte │ ├── TextBlock │ │ ├── TextBlock.scss │ │ └── TextBlock.svelte │ ├── TextBox │ │ ├── TextBox.scss │ │ ├── TextBox.svelte │ │ ├── TextBoxButton.scss │ │ └── TextBoxButton.svelte │ ├── ToggleSwitch │ │ ├── ToggleSwitch.scss │ │ └── ToggleSwitch.svelte │ ├── Tooltip │ │ ├── TooltipSurface.scss │ │ ├── TooltipSurface.svelte │ │ ├── TooltipWrapper.scss │ │ └── TooltipWrapper.svelte │ ├── _mixins.scss │ ├── index.ts │ ├── internal.ts │ ├── svelte-jsx.d.ts │ ├── switchable.css │ └── theme.css ├── routes │ ├── __layout.svelte │ ├── docs │ │ ├── __layout.svelte │ │ ├── components │ │ │ ├── button.md │ │ │ ├── calendarview.md │ │ │ ├── checkbox.md │ │ │ ├── contentdialog.md │ │ │ ├── expander.md │ │ │ ├── flyout.md │ │ │ ├── iconbutton.md │ │ │ ├── infobadge.md │ │ │ ├── infobar.md │ │ │ ├── listitem.md │ │ │ ├── personpicture.md │ │ │ ├── progressring.md │ │ │ ├── radiobutton.md │ │ │ ├── slider.md │ │ │ ├── splitbutton.md │ │ │ ├── textblock.md │ │ │ ├── textbox.md │ │ │ └── toggleswitch.md │ │ ├── getting-started.md │ │ ├── index.md │ │ └── internals │ │ │ └── index.md │ ├── index.svelte │ ├── selam.svelte │ └── test │ │ ├── __layout-test.svelte │ │ ├── index.svelte │ │ └── nav.svelte └── site │ ├── data │ ├── docs.ts │ └── home.ts │ ├── lib │ ├── APIDocs │ │ ├── APIDocs.svelte │ │ └── ParsedComponent.d.ts │ ├── CopyBox │ │ └── CopyBox.svelte │ ├── Example │ │ ├── Example.scss │ │ └── Example.svelte │ ├── HeroCard │ │ ├── HeroCard.scss │ │ └── HeroCard.svelte │ ├── Metadata │ │ └── Metadata.svelte │ ├── Navbar │ │ ├── Navbar.scss │ │ └── Navbar.svelte │ ├── PageSection │ │ ├── PageSection.scss │ │ └── PageSection.svelte │ ├── Showcase │ │ ├── Showcase.scss │ │ └── Showcase.svelte │ ├── Toc │ │ ├── Toc.scss │ │ └── Toc.svelte │ ├── TreeView │ │ └── TreeView.svelte │ └── index.ts │ └── styles │ ├── _markdown.scss │ ├── _mixins.scss │ ├── global.scss │ └── pages │ ├── docs.scss │ └── home.scss ├── static ├── bloom-mica-dark.png ├── bloom-mica-light.png ├── logo.svg └── segoeui.ttf ├── svelte.config.js └── tsconfig.json /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: "\U0001F41E Bug report" 2 | description: Report an issue or bug 3 | labels: ["🚧 pending triage"] 4 | body: 5 | - type: textarea 6 | id: reproduction 7 | attributes: 8 | label: Reproduction 9 | description: Please provide a link to a repo that can reproduce the problem you ran into. A **minimal reproduction** is required unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "need reproduction" label. If no reproduction is provided we might close it. 10 | placeholder: Reproduction 11 | validations: 12 | required: true 13 | - type: textarea 14 | id: bug-description 15 | attributes: 16 | label: Describe the bug 17 | description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks! 18 | placeholder: Bug description 19 | validations: 20 | required: true 21 | - type: textarea 22 | id: additional 23 | attributes: 24 | label: Additional context 25 | description: If applicable, add any other context about the problem here 26 | - type: textarea 27 | id: logs 28 | attributes: 29 | label: Logs 30 | description: | 31 | Optional if provided reproduction. Please try not to insert an image but copy paste the log text. 32 | render: sh 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: "🚀 Feature request" 2 | description: Suggest a feature or improvement 3 | labels: ["🚧 pending triage"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thank you for taking the time to fill out this feature request! 9 | - type: textarea 10 | id: feature-description 11 | attributes: 12 | label: Describe the feature 13 | description: A clear and concise description of what you think would be a helpful addition, including the possible use cases and alternatives you have considered. If you have a working prototype or module that implements it, please include a link. 14 | placeholder: Feature description 15 | validations: 16 | required: true 17 | - type: checkboxes 18 | id: additional-info 19 | attributes: 20 | label: Additional information 21 | description: Additional information that helps us decide how to proceed. 22 | options: 23 | - label: Would you be willing to help implement this feature? 24 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 15 | 16 | ### 🔗 Linked issue 17 | 18 | 19 | 20 | ### ❓ Type of change 21 | 22 | 23 | 24 | - [ ] 🐞 Bug fix (a non-breaking change that fixes an issue) 25 | - [ ] 👌 Enhancement (improving an existing functionality like performance) 26 | - [ ] ✨ New feature (a non-breaking change that adds functionality) 27 | - [ ] 🧹 Chore (updates to the build process or auxiliary tools and libraries) 28 | - [ ] 🛠️ Refactor (a code change that neither fixes a bug nor adds a feature) 29 | - [ ] ⚠️ Breaking change (fix or feature that would cause existing functionality to change) 30 | 31 | ### 📚 Description 32 | 33 | 34 | 35 | 36 | 37 | ### 📝 Checklist 38 | 39 | 40 | 41 | 42 | 43 | - [ ] I have linked an issue or discussion. 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | /.idea 7 | package-lock.json 8 | .vercel_build_output -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | src/routes/docs/** 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "tabWidth": 4, 4 | "trailingComma": "none", 5 | "arrowParens": "avoid", 6 | "printWidth": 100 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2022 Fluent Svelte Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fluent-svelte-extra 2 | 3 | A fork of fluent-svelte which is in active development. 4 | 5 | # Undocumented Components 6 | 7 | Components that we develop won't be in docs. But you can view the detailed usage [here](https://github.com/OpenAnime/fluent-svelte-extra/blob/main/src/routes/test/index.svelte) 8 | 9 | # Switching between themes 10 | 11 | Along with the new components, we have also added the ability to switch between dark and light themes. To switch between themes you should import `fluent-svelte-extra/switchable.css` in your +layout.svelte file and add `fds-theme-dark` or `fds-theme-light` classes to your `` tag in app.html file. `fluent-svelte-extra/switchable.css` does not contain anything that can be controlled by `prefers-color-scheme` 12 | 13 | If you use `fluent-svelte-extra/theme.css` it will use the system default until you add `fds-theme-dark` or `fds-theme-light` classes to your `` tag. 14 | 15 | Based on your needs, you can select a file which will be the best fit for your project. 16 | 17 | # Note 18 | 19 | Thanks to the [creator](https://github.com/Tropix126) of [fluent-svelte](https://github.com/tropix126/fluent-svelte) library for making such an awesome library! -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fluent-svelte-extra", 3 | "version": "2.0.8", 4 | "description": "A faithful implementation of Microsoft's Fluent Design System in Svelte.", 5 | "homepage": "https://github.com/OpenAnime/fluent-svelte-extra", 6 | "license": "MIT", 7 | "author": { 8 | "name": "SpongeBed", 9 | "url": "https://github.com/SpongeBed81" 10 | }, 11 | "keywords": [ 12 | "design", 13 | "design-system", 14 | "design-language", 15 | "microsoft", 16 | "fluent", 17 | "fluentui", 18 | "fluent-design", 19 | "fluent-design-system", 20 | "svelte", 21 | "svelte3", 22 | "sveltejs", 23 | "svelte-component", 24 | "svelte-components", 25 | "ui-components", 26 | "winui", 27 | "windows" 28 | ], 29 | "repository": { 30 | "type": "git", 31 | "url": "https://github.com/OpenAnime/fluent-svelte-extra.git" 32 | }, 33 | "bugs": { 34 | "url": "https://github.com/OpenAnime/fluent-svelte-extra/issues" 35 | }, 36 | "scripts": { 37 | "dev": "svelte-kit dev", 38 | "build": "svelte-kit build", 39 | "package": "svelte-kit package", 40 | "publish": "npm run package && cd package && npm publish", 41 | "preview": "svelte-kit preview", 42 | "check": "svelte-check --tsconfig ./tsconfig.json", 43 | "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", 44 | "lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. .", 45 | "format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ." 46 | }, 47 | "devDependencies": { 48 | "@fec/remark-a11y-emoji": "^3.1.0", 49 | "@fluentui/svg-icons": "^1.1.166", 50 | "@sveltejs/adapter-vercel": "next", 51 | "@sveltejs/kit": "^1.0.0-next.310", 52 | "@sveltejs/svelte-repl": "^0.2.2", 53 | "@types/prismjs": "^1.26.0", 54 | "autoprefixer": "^10.4.4", 55 | "cssnano": "^5.1.7", 56 | "mdsvex": "^0.9.8", 57 | "mdsvexamples": "0.2.3", 58 | "panzoom": "^9.4.2", 59 | "postcss": "^8.4.12", 60 | "postcss-variables-prefixer": "^1.1.1", 61 | "prettier": "^2.6.2", 62 | "prettier-plugin-svelte": "^2.7.0", 63 | "prism-svelte": "^0.4.7", 64 | "prismjs": "^1.27.0", 65 | "rehype-slug": "^5.0.1", 66 | "remark-github": "^11.2.2", 67 | "sass": "^1.50.0", 68 | "svelte": "^3.58.0", 69 | "svelte-check": "^3.6.9", 70 | "svelte-codesandbox": "^1.0.0", 71 | "svelte-preprocess": "^4.10.5", 72 | "svelte2tsx": "^0.4.14", 73 | "tslib": "^2.3.1", 74 | "typescript": "^4.6.3", 75 | "vite-node": "^0.1.27", 76 | "vite-plugin-sveld": "^1.0.3" 77 | }, 78 | "dependencies": { 79 | "@bulatdashiev/svelte-slider": "^1.0.3", 80 | "@sveltejs/adapter-auto": "^3.1.1", 81 | "fluent-svelte": "^1.6.0", 82 | "focus-trap": "^6.7.3", 83 | "tabbable": "^5.2.1" 84 | }, 85 | "type": "module" 86 | } 87 | -------------------------------------------------------------------------------- /src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %svelte.head% 8 | 9 | 10 |
%svelte.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /src/global.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/lib/Acrylic/AcrylicSurface.scss: -------------------------------------------------------------------------------- 1 | .acrylic-surface { 2 | background: var(--acrylic-background-default) var(--acrylic-noise-asset-alpha); 3 | backdrop-filter: var(--acrylic-blur-factor); 4 | -webkit-backdrop-filter: var(--acrylic-blur-factor); 5 | mix-blend-mode: luminosity; 6 | } 7 | -------------------------------------------------------------------------------- /src/lib/Acrylic/AcrylicSurface.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | 37 | 38 | 39 | 40 | 43 | -------------------------------------------------------------------------------- /src/lib/AutoSuggestBox/AutoSuggestBox.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .auto-suggest-box-flyout { 4 | z-index: 100; 5 | overflow: auto; 6 | position: absolute; 7 | inset-inline-start: -1px; 8 | inset-block-start: calc(100% + 1px); 9 | inline-size: calc(100% + 2px); 10 | margin: 0; 11 | padding: 0; 12 | padding-block: 2px; 13 | box-sizing: border-box; 14 | color: var(--text-primary); 15 | border-radius: var(--overlay-corner-radius); 16 | border-end-start-radius: 0; 17 | border-end-end-radius: 0; 18 | border: 1px solid var(--surface-stroke-flyout); 19 | background-color: var(--solid-background-quarternary); 20 | background-clip: padding-box; 21 | box-shadow: var(--flyout-shadow); 22 | max-block-size: 472px; 23 | &.acrylic { 24 | background-color: var(--acrylic-fallback-background-base); 25 | background-image: var(--acrylic-noise-asset-alpha); 26 | backdrop-filter: var(--acrylic-fallback-filter); 27 | background-clip: border-box; 28 | } 29 | } 30 | 31 | .auto-suggest-item-wrapper { 32 | display: block; 33 | } 34 | 35 | :global { 36 | .auto-suggest-box.open { 37 | background-color: var(--control-fill-input-active) !important; 38 | .text-box-underline::after { 39 | content: ""; 40 | border-bottom: 2px solid var(--fds-accent-default); 41 | } 42 | input::placeholder { 43 | color: var(--text-tertiary); 44 | } 45 | .text-box-underline { 46 | border-bottom-left-radius: 0; 47 | border-bottom-right-radius: 0; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/lib/Button/Button.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .button { 4 | @include flex($inline: true, $align: center, $justify: center); 5 | @include typography-body; 6 | 7 | position: relative; 8 | box-sizing: border-box; 9 | padding-block: 4px 6px; 10 | padding-inline: 11px; 11 | text-decoration: none; 12 | border: none; 13 | outline: none; 14 | cursor: default; 15 | border-radius: var(--control-corner-radius); 16 | transition: var(--control-faster-duration) ease background; 17 | 18 | &:focus-visible { 19 | box-shadow: var(--focus-stroke); 20 | } 21 | 22 | &.style- { 23 | &standard { 24 | border: 1px solid; 25 | border-color: var(--control-border-default); 26 | background-color: var(--control-fill-default); 27 | color: var(--text-primary); 28 | background-clip: padding-box; 29 | 30 | &:hover { 31 | background-color: var(--control-fill-secondary); 32 | } 33 | 34 | &:active { 35 | border-color: var(--control-stroke-default); 36 | background-color: var(--control-fill-tertiary); 37 | color: var(--text-secondary); 38 | } 39 | 40 | &.disabled { 41 | border-color: var(--control-stroke-default); 42 | background-color: var(--control-fill-disabled); 43 | color: var(--text-disabled); 44 | } 45 | } 46 | 47 | &accent { 48 | border: 1px solid var(--control-stroke-on-accent-default); 49 | border-bottom-color: var(--control-stroke-on-accent-secondary); 50 | background-color: var(--accent-default); 51 | color: var(--text-on-accent-primary); 52 | transition: var(--control-faster-duration) ease border-color; 53 | 54 | &:hover { 55 | background-color: var(--accent-secondary); 56 | } 57 | 58 | &:active { 59 | border-color: transparent; 60 | background-color: var(--accent-tertiary); 61 | color: var(--text-on-accent-secondary); 62 | } 63 | 64 | &.disabled { 65 | border-color: transparent; 66 | background-color: var(--accent-disabled); 67 | color: var(--text-on-accent-disabled); 68 | } 69 | } 70 | 71 | &hyperlink { 72 | background-color: var(--subtle-fill-transparent); 73 | color: var(--accent-text-primary); 74 | cursor: pointer; 75 | 76 | &:hover { 77 | background-color: var(--subtle-fill-secondary); 78 | } 79 | 80 | &:active { 81 | background-color: var(--subtle-fill-tertiary); 82 | color: var(--accent-text-tertiary); 83 | } 84 | 85 | &.disabled { 86 | color: var(--accent-text-disabled); 87 | } 88 | } 89 | } 90 | 91 | &.disabled { 92 | pointer-events: none; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/lib/Button/Button.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 | 33 | 44 | 45 | 46 | 47 | 50 | -------------------------------------------------------------------------------- /src/lib/CalendarDatePicker/CalendarDatePicker.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .calendar-date-picker- { 4 | &label { 5 | padding-inline-end: 2px; 6 | &.placeholder:not(.disabled) { 7 | color: var(--text-secondary); 8 | } 9 | } 10 | &icon { 11 | @include icon($size: 12px); 12 | margin-inline-start: 8px; 13 | color: currentColor; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/lib/CalendarView/CalendarView.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .calendar-view { 4 | @include flex($inline: true, $direction: column); 5 | text-align: start; 6 | inline-size: 300px; 7 | block-size: 347px; 8 | position: relative; 9 | user-select: none; 10 | color: var(--text-primary); 11 | background-clip: padding-box; 12 | background-color: var(--fds-solid-background-quarternary); 13 | border-radius: var(--control-corner-radius); 14 | border: 1px solid var(--surface-stroke-flyout); 15 | font-family: var(--font-family-text); 16 | &.floating { 17 | border-radius: var(--overlay-corner-radius); 18 | box-shadow: var(--flyout-shadow); 19 | } 20 | &-header, 21 | &-pagination-controls { 22 | @include flex($align: center); 23 | } 24 | &-pagination-controls button { 25 | padding: 0; 26 | inline-size: 30px; 27 | margin-inline-start: 4px; 28 | } 29 | &-header { 30 | box-sizing: border-box; 31 | border-block-end: 1px solid var(--card-stroke-default); 32 | inline-size: 100%; 33 | padding: 7px; 34 | button { 35 | @include flex($align: center, $justify: center); 36 | border: none; 37 | outline: none; 38 | padding: 0; 39 | min-block-size: 32px; 40 | color: var(--text-primary); 41 | background-color: var(--subtle-fill-transparent); 42 | border-radius: var(--control-corner-radius); 43 | line-height: 20px; 44 | font: { 45 | size: 14px; 46 | weight: 600; 47 | family: var(--font-family-text); 48 | } 49 | &:focus-visible { 50 | box-shadow: var(--focus-stroke); 51 | } 52 | &:hover { 53 | background-color: var(--subtle-fill-secondary); 54 | } 55 | &:active { 56 | background-color: var(--subtle-fill-tertiary); 57 | color: var(--text-secondary); 58 | } 59 | &:disabled { 60 | background-color: var(--sutble-fill-disabled); 61 | color: var(--text-disabled); 62 | svg { 63 | color: var(--control-strong-fill-disabled); 64 | } 65 | } 66 | svg { 67 | @include icon($size: 16px); 68 | color: var(--control-strong-fill-default); 69 | } 70 | } 71 | &-text { 72 | flex: 1 1 auto; 73 | button { 74 | inline-size: 100%; 75 | padding-inline: 9px; 76 | justify-content: flex-start; 77 | flex: 1 1 auto; 78 | } 79 | } 80 | } 81 | &-table { 82 | inset: 0; 83 | display: block; 84 | overflow: hidden; 85 | position: absolute; 86 | box-sizing: border-box; 87 | inline-size: calc(100% - 6px); 88 | block-size: calc(100% - 6px); 89 | margin: 3px; 90 | font-size: 14px; 91 | &-wrapper { 92 | inline-size: 298px; 93 | block-size: 298px; 94 | position: relative; 95 | contain: layout; 96 | overflow: hidden; 97 | background-color: var(--layer-on-acrylic-background-default); 98 | } 99 | &.view- { 100 | &months, 101 | &years { 102 | margin: 11px; 103 | inline-size: calc(100% - 22px); 104 | block-size: calc(100% - 22px); 105 | tr { 106 | grid-template-columns: repeat(4, 1fr); 107 | grid-gap: calc(52px / 3); 108 | margin-block-end: calc(52px / 3); 109 | } 110 | } 111 | } 112 | td, 113 | th { 114 | padding: 0; 115 | } 116 | th { 117 | @include flex($align: center, $justify: center); 118 | block-size: 40px; 119 | text-align: center; 120 | font: { 121 | size: 13px; 122 | weight: 600; 123 | } 124 | } 125 | thead, 126 | tbody { 127 | inline-size: 100%; 128 | display: flex; 129 | flex-direction: column; 130 | } 131 | thead tr, 132 | tbody { 133 | background-color: var(--fds-solid-background-quarternary); 134 | box-shadow: inset 0 0 0 100vmax var(--fds-layer-on-acrylic-background-default); 135 | } 136 | thead { 137 | position: relative; 138 | z-index: 1; 139 | } 140 | tbody { 141 | position: absolute; 142 | inset-inline-start: 0; 143 | inset-block-end: 0; 144 | tr:last-child { 145 | margin-block-end: 0; 146 | } 147 | } 148 | tr { 149 | display: grid; 150 | inline-size: 100%; 151 | grid-template-columns: repeat(7, 1fr); 152 | grid-gap: 2px; 153 | margin-block-end: 2px; 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/lib/CalendarView/CalendarViewItem.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .calendar-view-item { 4 | @include flex($inline: true, $justify: center, $align: center); 5 | position: relative; 6 | user-select: none; 7 | text-align: center; 8 | box-sizing: border-box; 9 | padding: 0; 10 | border: 1px solid transparent; 11 | outline: none; 12 | background-color: var(--subtle-fill-transparent); 13 | color: var(--text-primary); 14 | border-radius: 50%; 15 | line-height: 20px; 16 | font: { 17 | family: var(--font-family-text); 18 | size: 14px; 19 | weight: 400; 20 | } 21 | &:focus-visible { 22 | box-shadow: var(--focus-stroke); 23 | } 24 | &:hover { 25 | background-color: var(--subtle-fill-secondary); 26 | } 27 | &:active { 28 | background-color: var(--subtle-fill-tertiary); 29 | color: var(--text-secondary); 30 | } 31 | &.out-of-range { 32 | color: var(--text-secondary); 33 | &:active { 34 | color: var(--text-tertiary); 35 | } 36 | } 37 | &.disabled { 38 | background-color: var(--subtle-fill-disabled); 39 | color: var(--text-disabled); 40 | &.blackout::after { 41 | content: none; 42 | } 43 | } 44 | &.blackout { 45 | pointer-events: none; 46 | &::after { 47 | content: ""; 48 | transform-origin: center; 49 | inline-size: 26px; 50 | block-size: 1px; 51 | position: absolute; 52 | transform: matrix(-0.71, -0.71, -0.71, 0.71, 0, 0); 53 | border-block-start: 1px solid var(--control-strong-stroke-default); 54 | } 55 | } 56 | &.type- { 57 | &day { 58 | inline-size: 40px; 59 | block-size: 40px; 60 | small { 61 | inset-block-start: 2px; 62 | } 63 | } 64 | &month-year { 65 | inline-size: 56px; 66 | block-size: 56px; 67 | small { 68 | inset-block-start: 9.58px; // figma toolkit is weird idk 69 | } 70 | } 71 | } 72 | &.selected { 73 | color: var(--accent-text-primary); 74 | border: 1px solid var(--accent-default); 75 | &:hover { 76 | background-color: var(--subtle-fill-secondary); 77 | border-color: var(--accent-secondary); 78 | } 79 | &:active { 80 | background-color: var(--subtle-fill-tertiary); 81 | border-color: var(--accent-tertiary); 82 | } 83 | &.disabled { 84 | color: var(--accent-text-disabled); 85 | background-color: var(--subtle-fill-disabled); 86 | border-color: var(--accent-disabled); 87 | } 88 | &.current { 89 | box-shadow: inset 0 0 0 1px var(--text-on-accent-primary); 90 | &:focus-visible { 91 | box-shadow: inset 0 0 0 1px var(--text-on-accent-primary), var(--focus-stroke); 92 | } 93 | } 94 | &.blackout::after { 95 | border-block-start-color: var(--accent-tertiary); 96 | } 97 | } 98 | &.current { 99 | color: var(--text-on-accent-primary); 100 | background-color: var(--accent-default); 101 | &:hover { 102 | background-color: var(--accent-secondary); 103 | } 104 | &:active { 105 | background-color: var(--accent-tertiary); 106 | color: var(--text-on-accent-secondary); 107 | } 108 | &.disabled { 109 | background-color: var(--accent-disabled); 110 | } 111 | &.blackout::after { 112 | border-block-start-color: var(--text-on-accent-primary); 113 | } 114 | } 115 | small { 116 | pointer-events: none; 117 | position: absolute; 118 | inline-size: 100%; 119 | padding-inline: 1px; 120 | letter-spacing: 0.04em; 121 | text-align: center; 122 | color: inherit; 123 | line-height: 12px; 124 | font: { 125 | family: var(--font-family-small); 126 | weight: 400; 127 | size: 8px; 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/lib/CalendarView/CalendarViewItem.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 30 | 31 | 34 | -------------------------------------------------------------------------------- /src/lib/Checkbox/Checkbox.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .checkbox { 4 | @include typography-body; 5 | 6 | margin: 0; 7 | border: 1px solid var(--control-strong-stroke-default); 8 | border-radius: var(--control-corner-radius); 9 | outline: none; 10 | background-clip: padding-box; 11 | background-color: var(--control-alt-fill-secondary); 12 | appearance: none; 13 | inline-size: 20px; 14 | block-size: 20px; 15 | 16 | &:focus-visible { 17 | box-shadow: var(--focus-stroke); 18 | } 19 | 20 | &:hover { 21 | background-color: var(--control-alt-fill-tertiary); 22 | } 23 | 24 | &:active { 25 | border-color: var(--control-strong-stroke-disabled); 26 | background-color: var(--control-alt-fill-quarternary); 27 | + .checkbox-glyph { 28 | color: var(--text-on-accent-secondary); 29 | } 30 | } 31 | 32 | &:disabled { 33 | border-color: var(--control-strong-stroke-disabled); 34 | background-color: var(--control-alt-fill-disabled); 35 | pointer-events: none; 36 | } 37 | 38 | &:checked, 39 | &:indeterminate { 40 | border: none; 41 | background-color: var(--accent-default); 42 | 43 | &:hover { 44 | background-color: var(--accent-secondary); 45 | } 46 | 47 | &:active { 48 | background-color: var(--accent-tertiary); 49 | } 50 | 51 | &:disabled { 52 | border-color: var(--control-strong-stroke-disabled); 53 | background-color: var(--accent-disabled); 54 | + .checkbox-glyph { 55 | color: var(--text-on-accent-disabled); 56 | } 57 | } 58 | 59 | + .checkbox-glyph .path-checkmark { 60 | transition: var(--control-normal-duration) cubic-bezier(0.55, 0, 0, 1) stroke-dashoffset; 61 | stroke-dashoffset: 0; 62 | } 63 | } 64 | 65 | &-container { 66 | @include flex($inline: true, $align: center); 67 | @include typography-body; 68 | 69 | color: var(--text-primary); 70 | user-select: none; 71 | min-block-size: 32px; 72 | 73 | > span { 74 | padding-inline-start: 8px; 75 | } 76 | 77 | &.disabled > span { 78 | color: var(--text-disabled); 79 | } 80 | } 81 | 82 | &-inner { 83 | @include flex($align: center, $justify: center); 84 | position: relative; 85 | } 86 | 87 | &-glyph { 88 | position: absolute; 89 | color: inherit; 90 | color: var(--text-on-accent-primary); 91 | inline-size: 12px; 92 | block-size: 12px; 93 | 94 | path { 95 | transform-origin: center; 96 | } 97 | 98 | .path- { 99 | &checkmark { 100 | transform: scale(1.2); 101 | stroke: currentColor; 102 | stroke: { 103 | width: 2; 104 | linecap: round; 105 | linejoin: round; 106 | dasharray: 20.5; 107 | dashoffset: 20.5; 108 | } 109 | } 110 | 111 | &indeterminate { 112 | transform: scale(calc(2 / 3)) translateX(80px) translateY(240px); 113 | fill: currentColor; 114 | } 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/lib/Checkbox/Checkbox.svelte: -------------------------------------------------------------------------------- 1 | 29 | 30 | 38 | 39 | 40 | 78 | 79 | 82 | -------------------------------------------------------------------------------- /src/lib/ComboBox/ComboBox.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | @keyframes menu-in { 4 | 0% { 5 | clip-path: var(--grow-clip-path); 6 | } 7 | 100% { 8 | clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); 9 | } 10 | } 11 | 12 | @keyframes shadow-in { 13 | 0% { 14 | box-shadow: none; 15 | } 16 | 100% { 17 | box-shadow: var(--flyout-shadow); 18 | } 19 | } 20 | 21 | .combo-box { 22 | position: relative; 23 | display: inline-flex; 24 | user-select: none; 25 | 26 | :global { 27 | .button, 28 | .text-box { 29 | flex: 1 1 auto; 30 | } 31 | 32 | .text-box { 33 | border-color: var(--control-border-default); 34 | &-underline::after { 35 | border-color: transparent; 36 | } 37 | &-container { 38 | cursor: default; 39 | &:focus-visible { 40 | cursor: text; 41 | } 42 | } 43 | } 44 | } 45 | 46 | &.editable { 47 | :global { 48 | .combo-box-textbox:not(:focus-within) { 49 | cursor: default; 50 | border-color: var(--control-border-default); 51 | .text-box-underline::after { 52 | content: none; 53 | } 54 | } 55 | &.combo-box-textbox.disabled { 56 | border-color: var(--control-stroke-default); 57 | } 58 | } 59 | &.open { 60 | :global { 61 | .combo-box-textbox { 62 | cursor: text; 63 | background-color: var(--control-fill-input-active); 64 | .text-box-underline::after { 65 | content: ""; 66 | border-bottom: 2px solid var(--fds-accent-default); 67 | } 68 | input::placeholder { 69 | color: var(--text-tertiary); 70 | } 71 | } 72 | .text-box-underline { 73 | border-end-start-radius: 0; 74 | border-end-end-radius: 0; 75 | } 76 | } 77 | } 78 | .combo-box-dropdown { 79 | margin: 0; 80 | inset-inline-start: 0; 81 | inset-block-start: 100%; 82 | inline-size: 100%; 83 | border-radius: var(--overlay-corner-radius); 84 | border-start-start-radius: 0; 85 | border-start-end-radius: 0; 86 | } 87 | .combo-box-icon { 88 | margin: 0; 89 | } 90 | } 91 | 92 | &-label { 93 | flex: 1 1 auto; 94 | text-align: start; 95 | min-block-size: 20px; 96 | 97 | &.placeholder { 98 | color: var(--text-secondary); 99 | } 100 | } 101 | 102 | &.disabled .placeholder { 103 | color: var(--text-disabled); 104 | } 105 | 106 | &-icon { 107 | margin-inline-start: 8px; 108 | inline-size: 12px; 109 | block-size: 12px; 110 | } 111 | 112 | &-dropdown { 113 | z-index: 100; 114 | position: absolute; 115 | box-sizing: border-box; 116 | margin: 0; 117 | margin-block-start: -6px; 118 | margin-inline-start: -5px; 119 | padding: 1px; 120 | border: 1px solid var(--surface-stroke-flyout); 121 | border-radius: var(--overlay-corner-radius); 122 | background-color: var(--solid-background-quarternary); 123 | background-clip: padding-box; 124 | box-shadow: var(--flyout-shadow); 125 | animation: menu-in var(--control-normal-duration) var(--control-fast-out-slow-in-easing), 126 | shadow-in var(--control-normal-duration) var(--control-fast-out-slow-in-easing) 127 | var(--control-normal-duration); 128 | overflow: auto; 129 | inline-size: calc(100% + 8px); 130 | max-block-size: 504px; 131 | inset-block-start: var(--menu-offset, 0); 132 | inset-inline-start: 0; 133 | 134 | &.acrylic { 135 | background-color: var(--acrylic-fallback-background-base); 136 | background-image: var(--acrylic-noise-asset-alpha); 137 | backdrop-filter: var(--acrylic-fallback-filter); 138 | background-clip: border-box; 139 | } 140 | @supports (overflow: overlay) { 141 | overflow: overlay; 142 | } 143 | 144 | &.direction- { 145 | &top { 146 | --grow-clip-path: polygon(0 0, 100% 0, 100% 25%, 0 25%); 147 | } 148 | 149 | ¢er { 150 | --grow-clip-path: polygon(0 25%, 100% 24%, 100% 75%, 0 75%); 151 | } 152 | 153 | &bottom { 154 | --grow-clip-path: polygon(0 75%, 100% 75%, 100% 100%, 0 100%); 155 | } 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/lib/ComboBox/ComboBoxItem.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .combo-box-item { 4 | @include flex($align: center); 5 | @include typography-body; 6 | 7 | position: relative; 8 | box-sizing: border-box; 9 | flex: 0 0 auto; 10 | margin: 4px; 11 | padding: 0 11px; 12 | border-radius: var(--control-corner-radius); 13 | outline: none; 14 | background-color: var(--subtle-fill-transparent); 15 | color: var(--text-primary); 16 | text-decoration: none; 17 | cursor: default; 18 | user-select: none; 19 | block-size: 32px; 20 | 21 | &::before { 22 | content: ""; 23 | position: absolute; 24 | border-radius: 3px; 25 | background-color: var(--accent-default); 26 | transition: transform var(--control-fast-duration) var(--control-fast-out-slow-in-easing); 27 | opacity: 0; 28 | inset-inline-start: 0; 29 | inline-size: 3px; 30 | block-size: 0; 31 | } 32 | 33 | &:focus-visible { 34 | box-shadow: var(--focus-stroke); 35 | } 36 | 37 | &:hover, 38 | &.selected { 39 | background-color: var(--subtle-fill-secondary); 40 | } 41 | 42 | &:active { 43 | background-color: var(--subtle-fill-tertiary); 44 | color: var(--text-secondary); 45 | 46 | &::before { 47 | transform: scaleY(0.625); 48 | } 49 | } 50 | 51 | &.disabled { 52 | background-color: var(--subtle-fill-transparent); 53 | color: var(--text-disabled); 54 | pointer-events: none; 55 | &.selected { 56 | background-color: var(--subtle-fill-secondary); 57 | &::before { 58 | background-color: var(--accent-disabled); 59 | } 60 | } 61 | } 62 | 63 | &.selected::before { 64 | opacity: 1; 65 | block-size: 16px; 66 | } 67 | 68 | > span { 69 | flex: 1 1 auto; 70 | text-overflow: ellipsis; 71 | white-space: nowrap; 72 | overflow: hidden; 73 | max-inline-size: 100%; 74 | } 75 | 76 | > :global(svg) { 77 | @include icon($size: 16px); 78 | margin-inline-end: 16px; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/lib/ComboBox/ComboBoxItem.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
  • 22 | 23 | 24 | 25 | 26 |
  • 27 | 28 | 31 | -------------------------------------------------------------------------------- /src/lib/ContentDialog/ContentDialog.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .content-dialog { 4 | box-sizing: border-box; 5 | animation: dialog-inner var(--control-fast-duration) var(--control-fast-out-slow-in-easing); 6 | max-inline-size: calc(100% - 24px); 7 | border-radius: var(--overlay-corner-radius); 8 | background-color: var(--solid-background-base); 9 | background-clip: padding-box; 10 | box-shadow: var(--dialog-shadow); 11 | border: 1px solid var(--surface-stroke-default); 12 | overflow: hidden; 13 | &.size- { 14 | &min { 15 | inline-size: 320px; 16 | } 17 | &standard { 18 | inline-size: 448px; 19 | } 20 | &max { 21 | inline-size: 540px; 22 | } 23 | } 24 | 25 | &-container { 26 | @include flex($direction: row, $align: start, $justify: center); 27 | #close-button { 28 | @include flex($direction: column, $align: center, $justify: center); 29 | color: var(--text-primary); 30 | top: 0; 31 | margin-inline-start: 8px; 32 | block-size: 48px; 33 | inline-size: 48px; 34 | padding: 0; 35 | border-radius: var(--overlay-corner-radius); 36 | border: 1px solid var(--surface-stroke-default); 37 | background-clip: padding-box; 38 | background-color: var(--control-on-image-fill-default); 39 | transition: background-color var(--control-fast-duration) 40 | var(--control-fast-out-slow-in-easing), 41 | color var(--control-fast-duration) var(--control-fast-out-slow-in-easing); 42 | &:hover { 43 | background-color: var(--control-on-image-fill-secondary); 44 | } 45 | &:active { 46 | background-color: var(--control-on-image-fill-tertiary); 47 | } 48 | &.disabled { 49 | pointer-events: none; 50 | color: var(--text-disabled); 51 | background-color: var(--control-on-image-fill-default) !important; 52 | } 53 | } 54 | } 55 | 56 | &-smoke { 57 | @include flex($direction: column, $align: center, $justify: center); 58 | position: fixed; 59 | inset-inline-start: 0; 60 | inset-block-start: 0; 61 | z-index: 101; 62 | inline-size: 100%; 63 | block-size: 100%; 64 | &.darken { 65 | background-color: var(--smoke-background-default); 66 | } 67 | } 68 | 69 | :global(.content-dialog-title) { 70 | display: block; 71 | margin-bottom: 12px; 72 | color: var(--text-primary); 73 | } 74 | 75 | &-body, 76 | &-footer { 77 | padding: 24px; 78 | } 79 | 80 | &-body { 81 | @include typography-body; 82 | background-color: var(--layer-background-default); 83 | color: var(--text-primary); 84 | } 85 | 86 | &-footer { 87 | display: grid; 88 | grid-auto-rows: 1fr; 89 | grid-auto-flow: column; 90 | grid-gap: 8px; 91 | border-block-start: 1px solid var(--card-stroke-default); 92 | white-space: nowrap; 93 | > :global(.button:only-child) { 94 | inline-size: 50%; 95 | justify-self: end; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/lib/ContextMenu/ContextMenu.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .context-menu- { 4 | &wrapper { 5 | display: contents; 6 | } 7 | &anchor { 8 | position: fixed; 9 | z-index: 10000; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/lib/ContextMenu/ContextMenu.svelte: -------------------------------------------------------------------------------- 1 | 2 | 3 | 87 | 88 | 89 | 90 |
    101 | 102 | {#if open} 103 |
    e.preventDefault()} 108 | bind:this={anchorElement} 109 | on:outermousedown={() => (open = false)} 110 | class="context-menu-anchor" 111 | style="top: {menuPosition.y}px; left: {menuPosition.x}px;" 112 | > 113 | 114 | 115 | 116 |
    117 | {/if} 118 |
    119 | 120 | 123 | -------------------------------------------------------------------------------- /src/lib/ExpandMenu/ExpandMenu.svelte: -------------------------------------------------------------------------------- 1 | 52 | 53 |
    54 |
    55 | 56 |
    57 |
    58 | 59 | 99 | -------------------------------------------------------------------------------- /src/lib/Expander/Expander.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .expander { 4 | @include flex($direction: column); 5 | color: var(--text-primary); 6 | border-radius: var(--control-corner-radius); 7 | inline-size: 100%; 8 | user-select: none; 9 | .expander-header { 10 | transition: var(--fds-control-faster-duration) ease background; 11 | } 12 | 13 | &.expandable .expander-header { 14 | &:hover { 15 | background-color: var(--control-fill-secondary); 16 | border: 1px solid var(--fds-control-stroke-default); 17 | } 18 | &:active { 19 | background-color: var(--control-fill-tertiary); 20 | border: 1px solid var(--fds-control-stroke-default); 21 | } 22 | } 23 | 24 | &.direction- { 25 | &down { 26 | .expander-content { 27 | border-block-start: none; 28 | border-radius: var(--control-corner-radius); 29 | border-start-start-radius: 0 !important; 30 | border-start-end-radius: 0 !important; 31 | } 32 | &.expanded .expander-header { 33 | border-radius: var(--control-corner-radius); 34 | border-end-start-radius: 0 !important; 35 | border-end-end-radius: 0 !important; 36 | } 37 | } 38 | &up { 39 | .expander-content { 40 | border-bottom: none; 41 | border-radius: var(--control-corner-radius); 42 | border-end-start-radius: 0 !important; 43 | border-end-end-radius: 0 !important; 44 | &-anchor { 45 | order: -1; 46 | } 47 | } 48 | &.expanded .expander-header { 49 | border-radius: var(--control-corner-radius); 50 | border-start-start-radius: 0 !important; 51 | border-start-end-radius: 0 !important; 52 | } 53 | } 54 | } 55 | &.expanded { 56 | .expander { 57 | &-content { 58 | transform: none; 59 | } 60 | &-chevron svg { 61 | transform: rotate(180deg); 62 | } 63 | } 64 | } 65 | > h3 { 66 | display: contents; 67 | } 68 | &-icon { 69 | flex: 0 0 auto; 70 | color: var(--text-primary); 71 | inline-size: 16px; 72 | block-size: 16px; 73 | margin-inline-end: 16px; 74 | > :global(svg) { 75 | @include icon($size: 16px); 76 | } 77 | } 78 | &-header { 79 | @include flex($align: center); 80 | @include typography-body; 81 | text-align: start; 82 | outline: none; 83 | box-sizing: border-box; 84 | min-height: 50px; 85 | padding-inline-start: 16px; 86 | padding: 8px; 87 | background-clip: padding-box; 88 | background-color: var(--card-background-default); 89 | border: 1px solid var(--card-stroke-default); 90 | border-radius: var(--control-corner-radius); 91 | &-title { 92 | flex: 1 1 auto; 93 | } 94 | &:focus-visible { 95 | box-shadow: var(--focus-stroke); 96 | } 97 | &:active .expander-chevron { 98 | color: var(--text-secondary); 99 | } 100 | } 101 | &-chevron { 102 | @include flex($align: center, $justify: center); 103 | flex: 0 0 auto; 104 | inline-size: 32px; 105 | block-size: 32px; 106 | margin-inline-start: 20px; 107 | border: none; 108 | outline: none; 109 | appearance: none; 110 | color: var(--text-primary); 111 | border-radius: var(--control-corner-radius); 112 | background-color: var(--subtle-fill-transparent); 113 | &:focus-visible { 114 | box-shadow: var(--focus-stroke); 115 | } 116 | svg { 117 | inline-size: 12px; 118 | block-size: 12px; 119 | fill: currentColor; 120 | transition: calc(var(--control-fast-duration)) var(--control-fast-out-slow-in-easing) 121 | transform var(--control-fast-duration); 122 | } 123 | } 124 | &-content { 125 | @include typography-body; 126 | background-clip: padding-box; 127 | background-color: var(--card-background-secondary); 128 | border: 1px solid var(--card-stroke-default); 129 | padding: 16px; 130 | transition: var(--control-fast-duration) cubic-bezier(1, 1, 0, 1) transform; 131 | &-anchor { 132 | position: relative; 133 | max-block-size: 6.02e23vmax; 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/lib/Flipper/Flipper.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 40 | 41 | 77 | -------------------------------------------------------------------------------- /src/lib/Flyout/FlyoutSurface.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .flyout { 4 | @include typography-body; 5 | padding: 16px; 6 | min-inline-size: 320px; 7 | box-sizing: border-box; 8 | color: var(--text-primary); 9 | border-radius: var(--overlay-corner-radius); 10 | border: 1px solid var(--surface-stroke-flyout); 11 | background-color: var(--solid-background-quarternary); 12 | background-clip: padding-box; 13 | box-shadow: var(--flyout-shadow); 14 | &.acrylic { 15 | background-color: var(--acrylic-fallback-background-base); 16 | background-image: var(--acrylic-noise-asset-alpha); 17 | background-clip: border-box; 18 | backdrop-filter: var(--acrylic-fallback-filter); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/lib/Flyout/FlyoutSurface.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 |
    19 | 20 |
    21 | 22 | 25 | -------------------------------------------------------------------------------- /src/lib/Flyout/FlyoutWrapper.scss: -------------------------------------------------------------------------------- 1 | @keyframes flyout-in { 2 | 0% { 3 | opacity: 0; 4 | transform: var(--flyout-transform) var(--flyout-transition-offset, translateY(12px)); 5 | } 6 | 100% { 7 | opacity: 1; 8 | transform: var(--flyout-transform); 9 | } 10 | } 11 | 12 | .flyout- { 13 | &wrapper { 14 | display: inline-block; 15 | inline-size: fit-content; 16 | block-size: fit-content; 17 | position: relative; 18 | } 19 | &backdrop { 20 | position: fixed; 21 | top: 0; 22 | left: 0; 23 | inline-size: 100%; 24 | block-size: 100%; 25 | z-index: 9999; 26 | } 27 | &anchor { 28 | position: absolute; 29 | z-index: 10000; 30 | animation: flyout-in var(--control-normal-duration) var(--control-fast-out-slow-in-easing); 31 | transform: var(--flyout-transform); 32 | &.placement- { 33 | --flyout-transform: translateX(0%); 34 | &top { 35 | bottom: calc(100% + var(--flyout-offset)); 36 | --flyout-transition-offset: translateY(12px); 37 | } 38 | &bottom { 39 | top: calc(100% + var(--flyout-offset)); 40 | --flyout-transition-offset: translateY(-12px); 41 | } 42 | &left { 43 | right: calc(100% + var(--flyout-offset)); 44 | --flyout-transition-offset: translateX(12px); 45 | } 46 | &right { 47 | left: calc(100% + var(--flyout-offset)); 48 | --flyout-transition-offset: translateX(-12px); 49 | } 50 | &top, 51 | &bottom { 52 | &.alignment- { 53 | &start { 54 | inset-inline-start: 0; 55 | --flyout-transform: translateX(0%); 56 | } 57 | &end { 58 | inset-inline-end: 0; 59 | --flyout-transform: translateX(0%); 60 | } 61 | ¢er { 62 | inset-inline-start: 50%; 63 | --flyout-transform: translateX(-50%); 64 | } 65 | } 66 | } 67 | &left, 68 | &right { 69 | &.alignment- { 70 | &start { 71 | inset-block-start: 0; 72 | --flyout-transform: translateY(0%); 73 | } 74 | &end { 75 | inset-block-end: 0; 76 | --flyout-transform: translateY(0%); 77 | } 78 | ¢er { 79 | inset-block-start: 50%; 80 | --flyout-transform: translateY(-50%); 81 | } 82 | } 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/lib/GridView/GridViewItem.scss: -------------------------------------------------------------------------------- 1 | .grid-view-item { 2 | position: relative; 3 | border-radius: var(--control-corner-radius); 4 | transition: box-shadow var(--control-fast-duration); 5 | width: fit-content; 6 | user-select: none; 7 | 8 | &.selected { 9 | box-shadow: inset 0 0 0 2px var(--control-solid-fill-default), 10 | 0 0 0 3px var(--accent-default); 11 | } 12 | 13 | & > .item-checkbox { 14 | position: absolute; 15 | top: 0; 16 | right: 6px; 17 | overflow: hidden; 18 | z-index: 1; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/lib/GridView/GridViewItem.svelte: -------------------------------------------------------------------------------- 1 | 53 | 54 | 55 |
    { 61 | setSelected(!selected, false); 62 | dispatch("change", { selected: selected }); 63 | }} 64 | on:keydown={e => { 65 | if (e.key !== "Enter") return; 66 | setSelected(!selected, false); 67 | dispatch("change", { selected: selected }); 68 | }} 69 | > 70 | {#if !singleSelect} 71 |
    72 | { 76 | dispatch("change", { selected: !selected }); 77 | }} 78 | /> 79 |
    80 | {/if} 81 | 82 |
    83 | 84 | 87 | -------------------------------------------------------------------------------- /src/lib/IconButton/IconButton.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .icon-button { 4 | @include flex($inline: true, $align: center, $justify: center); 5 | outline: none; 6 | border: none; 7 | box-sizing: border-box; 8 | min-inline-size: 30px; 9 | min-block-size: 30px; 10 | padding: 8px; 11 | color: var(--text-primary); 12 | border-radius: var(--control-corner-radius); 13 | background-color: var(--subtle-fill-transparent); 14 | &:focus-visible { 15 | box-shadow: var(--focus-stroke); 16 | } 17 | &:hover { 18 | background-color: var(--subtle-fill-secondary); 19 | } 20 | &:active { 21 | color: var(--text-secondary); 22 | background-color: var(--subtle-fill-tertiary); 23 | } 24 | &:disabled, 25 | &.disabled { 26 | background-color: var(--subtle-fill-disabled); 27 | color: var(--text-disabled); 28 | } 29 | :global(svg) { 30 | @include icon($size: 16px); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/lib/IconButton/IconButton.svelte: -------------------------------------------------------------------------------- 1 | 21 | 22 | 34 | 44 | 45 | 46 | 47 | 50 | -------------------------------------------------------------------------------- /src/lib/InfoBadge/InfoBadge.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .info-badge { 4 | @include flex($inline: true, $align: center, $justify: center); 5 | box-sizing: border-box; 6 | user-select: none; 7 | min-inline-size: 16px; 8 | min-block-size: 16px; 9 | border-radius: 16px; 10 | padding: 2px 4px; 11 | color: var(--text-on-accent-primary); 12 | line-height: var(--caption-font-size); 13 | font: { 14 | family: var(--font-family-small); 15 | size: var(--caption-font-size); 16 | } 17 | &.severity- { 18 | &attention { 19 | background-color: var(--system-attention); 20 | } 21 | &success { 22 | background-color: var(--system-success); 23 | } 24 | &caution { 25 | background-color: var(--system-caution); 26 | } 27 | &critical { 28 | background-color: var(--system-critical); 29 | } 30 | &information { 31 | background-color: var(--system-solid-neutral); 32 | } 33 | } 34 | :global(svg) { 35 | inline-size: 8px; 36 | block-size: 8px; 37 | fill: currentColor; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/lib/InfoBar/InfoBar.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .info-bar { 4 | @include flex($align: center); 5 | position: relative; 6 | min-block-size: 48px; 7 | padding-inline-start: 15px; 8 | box-sizing: border-box; 9 | user-select: none; 10 | background-clip: padding-box; 11 | font-family: var(--font-family-text); 12 | border: 1px solid var(--card-stroke-default); 13 | border-radius: var(--control-corner-radius); 14 | &.severity- { 15 | &information { 16 | background-color: var(--card-background-secondary); 17 | } 18 | &success { 19 | background-color: var(--system-background-success); 20 | } 21 | &caution { 22 | background-color: var(--system-background-caution); 23 | } 24 | &critical { 25 | background-color: var(--system-background-critical); 26 | } 27 | &attention { 28 | background-color: var(--system-background-attention); 29 | } 30 | } 31 | &-icon { 32 | align-self: flex-start; 33 | display: flex; 34 | flex: 0 0 auto; 35 | margin: { 36 | block-start: 16px; 37 | } 38 | } 39 | &-content { 40 | @include flex($align: center, $wrap: true); 41 | position: relative; 42 | box-sizing: border-box; 43 | flex: 1 1 auto; 44 | margin: { 45 | inline-start: 13px; 46 | block-start: 7px; 47 | block-end: 7px; 48 | } 49 | &.message-wrapped, 50 | &.action-wrapped { 51 | margin: { 52 | block-start: 13px; 53 | block-end: 15px; 54 | } 55 | } 56 | &.message-wrapped { 57 | h5, 58 | p { 59 | align-self: flex-start; 60 | } 61 | .info-bar-action { 62 | margin-inline-end: 50%; 63 | } 64 | } 65 | &.action-wrapped .info-bar-action { 66 | padding-block-start: 16px; 67 | } 68 | } 69 | h5, 70 | p { 71 | color: var(--text-primary); 72 | margin: 0; 73 | line-height: 20px; 74 | font: { 75 | size: var(--body-font-size); 76 | weight: 400; 77 | } 78 | } 79 | h5 { 80 | font-weight: 600; 81 | margin-inline-end: 12px; 82 | } 83 | p { 84 | flex: 1 1 auto; 85 | margin-inline-end: 15px; 86 | } 87 | &-action { 88 | @include flex($align: center); 89 | align-self: flex-start; 90 | margin-inline-end: 4px; 91 | } 92 | &-close-button { 93 | @include flex($align: center, $justify: center); 94 | align-self: flex-start; 95 | flex: 0 0 auto; 96 | border: none; 97 | outline: none; 98 | appearance: none; 99 | inline-size: 38px; 100 | block-size: 38px; 101 | margin: 4px; 102 | color: var(--text-primary); 103 | border-radius: var(--control-corner-radius); 104 | background-color: var(--subtle-fill-transparent); 105 | transition: var(--control-fast-duration) var(--control-fast-out-slow-in-easing); 106 | &:focus-visible { 107 | box-shadow: var(--focus-stroke); 108 | } 109 | &:hover { 110 | background-color: var(--subtle-fill-secondary); 111 | } 112 | &:active { 113 | color: var(--text-secondary); 114 | background-color: var(--subtle-fill-tertiary); 115 | } 116 | svg { 117 | inline-size: 12px; 118 | block-size: 12px; 119 | fill: currentColor; 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/lib/ListItem/ListItem.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .list-item { 4 | @include flex($align: center); 5 | 6 | white-space: nowrap; 7 | inline-size: calc(100% - 10px); 8 | position: relative; 9 | box-sizing: border-box; 10 | flex: 0 0 auto; 11 | margin: 3px 5px; 12 | padding-inline: 12px; 13 | border-radius: var(--control-corner-radius); 14 | outline: none; 15 | background-color: var(--subtle-fill-transparent); 16 | color: var(--text-primary); 17 | text-decoration: none; 18 | cursor: default; 19 | user-select: none; 20 | block-size: 34px; 21 | text-decoration: none; 22 | transition: var(--fds-control-faster-duration) ease background; 23 | 24 | &::before { 25 | content: ""; 26 | position: absolute; 27 | border-radius: 3px; 28 | background-color: var(--accent-default); 29 | transition: transform var(--control-fast-duration) var(--control-fast-out-slow-in-easing); 30 | opacity: 0; 31 | inset-inline-start: 0; 32 | inline-size: 3px; 33 | block-size: 16px; 34 | transform: scaleY(0); 35 | } 36 | 37 | &.selected::before { 38 | transform: scaleY(1); 39 | opacity: 1; 40 | } 41 | 42 | &:focus-visible { 43 | box-shadow: var(--focus-stroke); 44 | } 45 | 46 | &:hover, 47 | &.selected { 48 | background-color: var(--subtle-fill-secondary); 49 | } 50 | 51 | &:active { 52 | background-color: var(--subtle-fill-tertiary); 53 | color: var(--text-secondary); 54 | 55 | &::before { 56 | transform: scaleY(0.625); 57 | } 58 | } 59 | 60 | &.disabled { 61 | background-color: var(--subtle-fill-transparent); 62 | color: var(--text-disabled); 63 | pointer-events: none; 64 | &.selected { 65 | background-color: var(--subtle-fill-secondary); 66 | &::before { 67 | background-color: var(--accent-disabled); 68 | } 69 | } 70 | } 71 | 72 | > :global(svg) { 73 | @include icon($size: 16px); 74 | margin-inline-end: 16px; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/lib/ListItem/ListItem.svelte: -------------------------------------------------------------------------------- 1 | 37 | 38 | 46 | {#if href && !disabled} 47 | 59 | 60 | 61 | 62 | 63 | 64 | {:else} 65 |
  • 77 | 78 | 79 | 80 | 81 |
  • 82 | {/if} 83 | 84 | 87 | -------------------------------------------------------------------------------- /src/lib/MenuBar/MenuBar.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .menu-bar { 4 | @include flex($align: center); 5 | cursor: default; 6 | user-select: none; 7 | block-size: 40px; 8 | margin: 0; 9 | padding: 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/lib/MenuBar/MenuBar.svelte: -------------------------------------------------------------------------------- 1 | 42 | 43 | 46 | 47 | 50 | -------------------------------------------------------------------------------- /src/lib/MenuBar/MenuBarItem.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .menu-bar-item { 4 | @include typography-body; 5 | @include flex($inline: true, $align: center); 6 | 7 | position: relative; 8 | padding: 5px 11px; 9 | margin: 4px; 10 | cursor: default; 11 | color: var(--text-primary); 12 | background-color: var(--subtle-fill-transparent); 13 | border-radius: var(--control-corner-radius); 14 | &:hover { 15 | background-color: var(--subtle-fill-secondary); 16 | } 17 | &:active, 18 | &[aria-expanded="true"] { 19 | background-color: var(--subtle-fill-tertiary); 20 | &:hover { 21 | background-color: var(--subtle-fill-secondary); 22 | } 23 | } 24 | &:active { 25 | color: var(--text-secondary); 26 | } 27 | &.disabled { 28 | color: var(--text-disabled); 29 | background-color: var(--subtle-fill-disabled) !important; 30 | } 31 | } 32 | 33 | .menu-flyout-anchor { 34 | z-index: 10000; 35 | position: absolute; 36 | inset-block-start: 100%; 37 | inset-inline-start: 0; 38 | } 39 | -------------------------------------------------------------------------------- /src/lib/MenuBar/flyoutState.ts: -------------------------------------------------------------------------------- 1 | import type { SvelteComponentTyped } from "svelte"; 2 | 3 | import { writable } from "svelte/store"; 4 | 5 | export const currentMenu = writable(null); 6 | -------------------------------------------------------------------------------- /src/lib/MenuFlyout/MenuFlyoutDivider.scss: -------------------------------------------------------------------------------- 1 | .menu-flyout-divider { 2 | inline-size: 100%; 3 | margin-block: 2px; 4 | block-size: 1px; 5 | border: none; 6 | border-block-start: 1px solid var(--divider-stroke-default); 7 | } 8 | -------------------------------------------------------------------------------- /src/lib/MenuFlyout/MenuFlyoutDivider.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 15 | -------------------------------------------------------------------------------- /src/lib/MenuFlyout/MenuFlyoutItem.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | .menu-flyout-item { 4 | @include flex($align: center); 5 | @include typography-body; 6 | 7 | inline-size: calc(100% - 8px); 8 | position: relative; 9 | box-sizing: border-box; 10 | flex: 0 0 auto; 11 | // overflow: hidden; 12 | margin: 2px 4px; 13 | padding-inline: 12px; 14 | border-radius: var(--control-corner-radius); 15 | outline: none; 16 | background-color: var(--subtle-fill-transparent); 17 | color: var(--text-primary); 18 | text-decoration: none; 19 | cursor: default; 20 | user-select: none; 21 | min-block-size: 28px; 22 | white-space: nowrap; 23 | text-overflow: ellipsis; 24 | text-decoration: none; 25 | 26 | &::before { 27 | content: ""; 28 | position: absolute; 29 | border-radius: 3px; 30 | background-color: var(--accent-default); 31 | transition: transform var(--control-fast-duration) var(--control-fast-out-slow-in-easing); 32 | opacity: 0; 33 | inset-inline-start: 0; 34 | inline-size: 3px; 35 | block-size: 0; 36 | } 37 | 38 | &:focus-visible { 39 | box-shadow: var(--focus-stroke); 40 | } 41 | 42 | &:hover, 43 | &[aria-expanded="true"], 44 | &.selected { 45 | background-color: var(--subtle-fill-secondary); 46 | } 47 | 48 | &.checked { 49 | :global { 50 | .menu-flyout-item- { 51 | &bullet, 52 | &checkmark { 53 | visibility: visible; 54 | } 55 | } 56 | } 57 | } 58 | 59 | &:active { 60 | background-color: var(--subtle-fill-tertiary); 61 | 62 | &::before { 63 | transform: scaleY(0.625); 64 | } 65 | } 66 | 67 | &.disabled { 68 | background-color: var(--subtle-fill-transparent); 69 | color: var(--text-disabled); 70 | pointer-events: none; 71 | &.selected { 72 | background-color: var(--subtle-fill-secondary); 73 | &::before { 74 | background-color: var(--accent-disabled); 75 | } 76 | } 77 | > :global(.menu-flyout-item-hint) { 78 | color: var(--text-disabled); 79 | } 80 | } 81 | 82 | &.selected::before { 83 | opacity: 1; 84 | block-size: 16px; 85 | } 86 | 87 | &.indented { 88 | padding-inline-start: 40px; 89 | } 90 | 91 | &-checkmark, 92 | &-bullet { 93 | visibility: hidden; 94 | } 95 | 96 | & &-arrow { 97 | box-sizing: content-box; 98 | inline-size: 12px; 99 | block-size: 12px; 100 | margin-inline-end: 0; 101 | margin-inline-start: auto; 102 | padding-inline-start: 24px; 103 | } 104 | 105 | &-checkmark { 106 | @include flex($align: center, $justify: center); 107 | inline-size: 12px; 108 | block-size: 12px; 109 | margin-inline-start: 2px; 110 | margin-inline-end: 14px; 111 | } 112 | 113 | &-bullet { 114 | inline-size: 4px; 115 | block-size: 4px; 116 | border-radius: 4px; 117 | margin-inline-start: 6px; 118 | margin-inline-end: 18px; 119 | background-color: currentColor; 120 | } 121 | 122 | &-input-label { 123 | display: contents; 124 | } 125 | 126 | > :global(svg) { 127 | @include icon($size: 16px); 128 | margin-inline-end: 12px; 129 | } 130 | 131 | > :global(.menu-flyout-item-hint) { 132 | flex: 1 1 auto; 133 | text-align: end; 134 | padding-left: 24px; 135 | overflow: hidden; 136 | text-overflow: ellipsis; 137 | color: var(--text-secondary); 138 | } 139 | } 140 | 141 | .menu-flyout-submenu-anchor { 142 | z-index: 10000; 143 | position: absolute; 144 | inset-block-start: 0; 145 | inset-inline-start: 100%; 146 | } 147 | -------------------------------------------------------------------------------- /src/lib/MenuFlyout/MenuFlyoutSurface.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins" as *; 2 | 3 | @keyframes menu-open { 4 | from { 5 | transform: translateY(var(--menu-flyout-transition-offset, -50%)); 6 | } 7 | to { 8 | transform: none; 9 | } 10 | } 11 | 12 | @keyframes menu-shadow { 13 | from { 14 | box-shadow: none; 15 | } 16 | to { 17 | box-shadow: var(--flyout-shadow); 18 | } 19 | } 20 | 21 | .menu-flyout { 22 | @include typography-body; 23 | @include flex($direction: column); 24 | animation: menu-open var(--control-normal-duration) var(--control-fast-out-slow-in-easing), 25 | menu-shadow var(--control-fast-duration) var(--control-fast-out-slow-in-easing) 26 | var(--control-normal-duration) forwards; 27 | min-inline-size: 120px; 28 | max-inline-size: 100%; 29 | max-block-size: 100vh; 30 | margin: 0; 31 | padding: 0; 32 | padding-block: 2px; 33 | box-sizing: border-box; 34 | color: var(--text-primary); 35 | border-radius: var(--overlay-corner-radius); 36 | border: 1px solid var(--surface-stroke-flyout); 37 | background-color: var(--solid-background-quarternary); 38 | background-clip: padding-box; 39 | &-surface-container { 40 | overflow: hidden; 41 | } 42 | &.acrylic { 43 | background-color: var(--acrylic-fallback-background-base); 44 | background-image: var(--acrylic-noise-asset-alpha); 45 | backdrop-filter: var(--acrylic-fallback-filter); 46 | background-clip: border-box; 47 | } 48 | } -------------------------------------------------------------------------------- /src/lib/MenuFlyout/MenuFlyoutSurface.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 29 | 30 | 33 | -------------------------------------------------------------------------------- /src/lib/MenuFlyout/MenuFlyoutWrapper.scss: -------------------------------------------------------------------------------- 1 | .menu-flyout- { 2 | &wrapper { 3 | display: inline-block; 4 | height: auto; 5 | position: relative; 6 | } 7 | &backdrop { 8 | position: fixed; 9 | top: 0; 10 | left: 0; 11 | width: 100%; 12 | height: 100%; 13 | z-index: 9999; 14 | } 15 | &anchor { 16 | position: absolute; 17 | z-index: 10000; 18 | &.placement- { 19 | &top { 20 | --fds-menu-flyout-transition-offset: 50%; 21 | bottom: calc(100% + var(--menu-flyout-offset)); 22 | } 23 | &bottom { 24 | top: calc(100% + var(--menu-flyout-offset)); 25 | } 26 | &left { 27 | right: calc(100% + var(--menu-flyout-offset)); 28 | } 29 | &right { 30 | left: calc(100% + var(--menu-flyout-offset)); 31 | } 32 | &top, 33 | &bottom { 34 | &.alignment- { 35 | &start { 36 | inset-inline-start: 0; 37 | } 38 | &end { 39 | inset-inline-end: 0; 40 | } 41 | ¢er { 42 | inset-inline-start: 50%; 43 | transform: translateX(-50%); 44 | } 45 | } 46 | } 47 | &left, 48 | &right { 49 | &.alignment- { 50 | &start { 51 | inset-block-start: 0; 52 | } 53 | &end { 54 | inset-block-end: 0; 55 | } 56 | ¢er { 57 | inset-block-start: 50%; 58 | transform: translateY(-50%); 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /src/lib/MenuFlyout/MenuFlyoutWrapper.svelte: -------------------------------------------------------------------------------- 1 | 80 | 81 | 82 | 83 |