-
Notifications
You must be signed in to change notification settings - Fork 281
[Remove Vuetify from Studio] Main navigation in Channels #5642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: unstable
Are you sure you want to change the base?
Changes from all commits
7d07bcb
5d90ece
d43a8db
21025e9
57bc907
2015bdc
ebe5c29
5203327
c710316
54c85eb
50fa709
95fc646
7e1ec05
34c8a02
bc124a2
8d53da0
f30205b
2138fd1
143a1a4
101b323
14173b2
ed5b67d
730ada4
4c3496f
f5e56c9
fc1acdf
1c5082f
0bfe43e
d2ec50f
4b17df3
443b2a5
56edddb
92bc483
c70d685
920f132
79fa4b6
e7ba119
382de7c
4b6871a
c716f74
4d845b9
7796ebb
858af8c
2205f10
445ccf2
dc79262
46afbee
1ba780d
3983437
6af0c90
c8a54eb
7004dad
2aefb26
5fbb3ea
ff95e6e
f7d437e
0c1a2de
d2383be
9057ce4
07aee46
4ab184e
3268fe4
49f3990
21d7a44
427fb74
74eac84
e32937c
4910918
79a0f38
2427703
adb8767
4740318
fbcf22d
243528f
bf31a49
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,47 +27,21 @@ | |
| {{ isFAQPage ? $tr('frequentlyAskedQuestions') : $tr('libraryTitle') }} | ||
| </VToolbarTitle> | ||
| </VToolbar> | ||
| <AppBar v-else> | ||
| <template | ||
| v-if="loggedIn" | ||
| #tabs | ||
| > | ||
| <VTab | ||
| v-for="listType in lists" | ||
| :key="listType.id" | ||
| :to="getChannelLink(listType)" | ||
| @click="trackTabClick(listType)" | ||
| > | ||
| <VBadge | ||
| :value="invitationsByListCounts[listType]" | ||
| color="black" | ||
| > | ||
| <template #badge> | ||
| <span>{{ $formatNumber(invitationsByListCounts[listType]) }}</span> | ||
| </template> | ||
| <span>{{ translateConstant(listType) }}</span> | ||
| </VBadge> | ||
| </VTab> | ||
| <VTab | ||
| :to="catalogLink" | ||
| @click="publicTabClick" | ||
| > | ||
| {{ $tr('catalog') }} | ||
| </VTab> | ||
| <VTab | ||
| :to="channelSetLink" | ||
| @click="channelSetsTabClick" | ||
| > | ||
| {{ $tr('channelSets') }} | ||
| </VTab> | ||
| </template> | ||
| </AppBar> | ||
|
|
||
| <StudioNavigation | ||
| v-else | ||
| :tabs="navigationTabs" | ||
| /> | ||
|
|
||
| <VContent> | ||
| <StudioOfflineAlert | ||
| v-if="!isCatalogPage" | ||
| :offset="toolbarHeight" | ||
| /> | ||
| <VContainer | ||
| id="main" | ||
| role="main" | ||
| tabindex="-1" | ||
| fluid | ||
| class="main-container pa-0" | ||
| :style="`height: calc(100vh - ${contentOffset}px); margin-top: ${offline ? 48 : 0}px;`" | ||
|
|
@@ -137,7 +111,7 @@ | |
| import { ChannelListTypes } from 'shared/constants'; | ||
| import { constantsTranslationMixin, routerMixin } from 'shared/mixins'; | ||
| import GlobalSnackbar from 'shared/views/GlobalSnackbar'; | ||
| import AppBar from 'shared/views/AppBar'; | ||
| import StudioNavigation from 'shared/views/StudioNavigation'; | ||
| import StudioOfflineAlert from 'shared/views/StudioOfflineAlert.vue'; | ||
| import PolicyModals from 'shared/views/policies/PolicyModals'; | ||
|
|
||
|
|
@@ -159,7 +133,7 @@ | |
| export default { | ||
| name: 'ChannelListIndex', | ||
| components: { | ||
| AppBar, | ||
| StudioNavigation, | ||
| ChannelInvitation, | ||
| ChannelListAppError, | ||
| GlobalSnackbar, | ||
|
|
@@ -174,6 +148,41 @@ | |
| }), | ||
| ...mapGetters(['loggedIn']), | ||
| ...mapGetters('channelList', ['invitations']), | ||
|
|
||
| navigationTabs() { | ||
| if (!this.loggedIn) return []; | ||
|
|
||
| const tabs = []; | ||
|
|
||
| this.lists.forEach(listType => { | ||
| tabs.push({ | ||
| id: listType, | ||
| label: this.translateConstant(listType), | ||
| to: this.getChannelLink(listType), | ||
| badgeValue: this.invitationsByListCounts[listType] || 0, | ||
| analyticsLabel: ListTypeToAnalyticsLabel[listType], | ||
| }); | ||
| }); | ||
|
|
||
| tabs.push({ | ||
| id: 'catalog', | ||
| label: this.$tr('catalog'), | ||
| to: this.catalogLink, | ||
| badgeValue: 0, | ||
| analyticsLabel: 'PUBLIC', | ||
| }); | ||
|
|
||
| tabs.push({ | ||
| id: CHANNEL_SETS, | ||
| label: this.$tr('channelSets'), | ||
| to: this.channelSetLink, | ||
| badgeValue: 0, | ||
| analyticsLabel: 'CHANNEL_SETS', | ||
|
Comment on lines
+172
to
+180
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems that the analyticsLabel has slightly changed a bit for these two tabs, right? I think we should use |
||
| }); | ||
|
|
||
| return tabs; | ||
| }, | ||
|
|
||
| fullPageError() { | ||
| return this.$store.state.errors.fullPageError; | ||
| }, | ||
|
|
@@ -227,12 +236,6 @@ | |
| homeLink() { | ||
| return this.libraryMode ? window.Urls.base() : window.Urls.channels(); | ||
| }, | ||
| publicTabClick() { | ||
| return this.trackTabClick.bind(this, ChannelListTypes.PUBLIC); | ||
| }, | ||
| channelSetsTabClick() { | ||
| return this.trackTabClick.bind(this, CHANNEL_SETS); | ||
| }, | ||
| }, | ||
| watch: { | ||
| $route(route) { | ||
|
|
@@ -289,9 +292,6 @@ | |
| this.updateTabTitle(title); | ||
| } | ||
| }, | ||
| trackTabClick(list) { | ||
| this.$analytics.trackClick('channel_list', ListTypeToAnalyticsLabel[list]); | ||
| }, | ||
| }, | ||
| $trs: { | ||
| channelSets: 'Collections', | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,7 +26,7 @@ | |
| <div | ||
| class="header-content" | ||
| :style="{ | ||
| flexDirection: closeButtonIconType === 'close' ? 'row' : 'row-reverse', | ||
| flexDirection: headerFlexDirection, | ||
| }" | ||
| > | ||
| <div style="overflow: hidden"> | ||
|
|
@@ -104,6 +104,13 @@ | |
| return ['close', 'back'].includes(value); | ||
| }, | ||
| }, | ||
| closeButtonPosition: { | ||
| type: String, | ||
| required: false, | ||
| default: null, | ||
| validator: value => ['left', 'right'].includes(value), | ||
| }, | ||
|
|
||
| /* Optionally override the default width of the side panel with valid CSS value */ | ||
| sidePanelWidth: { | ||
| type: String, | ||
|
|
@@ -118,6 +125,11 @@ | |
| return ['right', 'left'].includes(value); | ||
| }, | ||
| }, | ||
| fixedWidth: { | ||
| type: Boolean, | ||
| required: false, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @MisRob This prop is added here to deal with the full width functionality of sidepanelmodel |
||
| default: false, | ||
| }, | ||
| ariaLabel: { | ||
| type: String, | ||
| required: false, | ||
|
|
@@ -151,7 +163,15 @@ | |
| [this.rtlAlignment]: 0, | ||
| }; | ||
| }, | ||
| headerFlexDirection() { | ||
| if (this.closeButtonPosition === 'left') return 'row-reverse'; | ||
| if (this.closeButtonPosition === 'right') return 'row'; | ||
| return this.closeButtonIconType === 'close' ? 'row' : 'row-reverse'; | ||
| }, | ||
| responsiveWidth() { | ||
| if (this.fixedWidth) { | ||
| return this.sidePanelWidth; | ||
| } | ||
| return this.isMobile ? '100vw' : this.sidePanelWidth; | ||
| }, | ||
| /** Styling Properties */ | ||
|
|
@@ -253,7 +273,6 @@ | |
|
|
||
| .side-panel-content { | ||
| flex-grow: 1; | ||
| padding: 24px 32px 16px; | ||
| overflow-x: hidden; | ||
| overflow-y: auto; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| <template> | ||
|
|
||
| <div class="skip-nav-link"> | ||
| <KButton | ||
| ref="button" | ||
| :style="linkStyles" | ||
| appearance="basic-link" | ||
| :text="$tr('skipToMainContentAction')" | ||
| @click="handleClickSkipLink" | ||
| /> | ||
| </div> | ||
|
|
||
| </template> | ||
|
|
||
|
|
||
| <script> | ||
|
|
||
| export default { | ||
| name: 'SkipNavigationLink', | ||
| computed: { | ||
| linkStyles() { | ||
| return { | ||
| backgroundColor: this.$themeTokens.surface + ' !important', | ||
| }; | ||
| }, | ||
| }, | ||
| methods: { | ||
| handleClickSkipLink() { | ||
| // Every page where this is supposed to work needs to have a top-level | ||
| // element with 'role' and 'id' attribute equal to 'main' and 'tabindex= -1'. | ||
| // If it doesn't have one, clicking this link is a noop, but will re-focus itself | ||
| // as a convenience (in case main div is still loading). | ||
| const mainEl = document.getElementById('main'); | ||
| if (mainEl) { | ||
| // If it exists, actually target and focus on the main header | ||
| const header = mainEl.querySelector('h1'); | ||
| if (header) { | ||
| // HACK: Need to set its tabindex attribute on the fly to get tab behavior | ||
| header.setAttribute('tabindex', -1); | ||
| header.focus(); | ||
| } else { | ||
| mainEl.focus(); | ||
| } | ||
| } else { | ||
| // NOTE: the button retains focus, but loses :focus styling after hitting "Enter" | ||
| // TODO: look into theme input modality to see if we can get consistent | ||
| // styling when in keyboard modality | ||
| this.$refs.button.$el.focus(); | ||
| } | ||
| }, | ||
| }, | ||
| $trs: { | ||
| skipToMainContentAction: { | ||
| message: 'Skip to main content', | ||
| context: | ||
| 'Button label for the hamburger menu in the top left corner. Accessible only to those who use screen readers and other assistive technology (AT).', | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| </script> | ||
|
|
||
|
|
||
| <style lang="scss" scoped> | ||
|
|
||
| @import '~kolibri-design-system/lib/styles/definitions'; | ||
|
|
||
| .skip-nav-link { | ||
| position: relative; | ||
| z-index: 2; | ||
| } | ||
|
|
||
| .skip-nav-link a { | ||
| @extend %dropshadow-2dp; | ||
|
|
||
| position: absolute; | ||
| left: -1000px; | ||
| padding: 8px 16px; | ||
| font-size: 14px; | ||
| outline-offset: 0 !important; | ||
|
|
||
| &:focus { | ||
| top: 8px; | ||
| left: 8px; | ||
| z-index: 2; | ||
| } | ||
| } | ||
|
|
||
| </style> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'll be better to add these styles directly in the CatalogFilters component, since that's where we have the context of when we use the side panel or not.
We can just do something like
This way we will have a cleaner and clearer reason why this component has that style